I want to dynamically add http-headers via CloudFlare workers ONLY for the first time visitors. For example these headers:
Link: </path/to/file.css>; rel=preload; as=style; nopush
Link: </path/to/script.js>; rel=preload; as=script; nopush
So, what I need is the following, via JavaScript, in CloudFlare Workers:
You can play with the code here.
Here's a general example (involving cookie and headers) from the CF's blog:
// A Service Worker which skips cache if the request contains
// a cookie.
addEventListener('fetch', event => {
let request = event.request
if (request.headers.has('Cookie')) {
// Cookie present. Add Cache-Control: no-cache.
let newHeaders = new Headers(request.headers)
newHeaders.set('Cache-Control', 'no-cache')
event.respondWith(fetch(request, {headers: newHeaders}))
}
// Use default behavior.
return
})
Here's a Cloudflare Worker that implements what you describe:
addEventListener('fetch', event => {
event.respondWith(handle(event.request))
})
async function handle(request) {
// Check for cookie.
let cookies = request.headers.get('Cookie') || ""
if (cookies.includes("returning=true")) {
// User has been here before. Just pass request through.
return fetch(request)
}
// Forward request to origin, get response.
let response = await fetch(request)
// Copy Response object so that we can edit headers.
response = new Response(response.body, response)
// Add headers.
response.headers.append("Link",
"</path/to/file.css>; rel=preload; as=style; nopush")
response.headers.append("Link",
"</path/to/script.js>; rel=preload; as=script; nopush")
// Set cookie so that we don't add the headers
// next time.
response.headers.set("Set-Cookie", "returning=true")
// Return on to client.
return response
}
I've managed to modify the worker and provide a solution where Cache-Control
header is removed if the user has commented on the website.
addEventListener('fetch', event => {
event.respondWith(addHeaders(event.request))
})
async function addHeaders(request) {
// Forward request to origin, get response.
let response = await fetch(request)
if (response.headers.has("Content-Type") &&
!response.headers.get("Content-Type").includes("text/html")) {
// File is not text/html. Pass request through.
return fetch(request)
}
// Copy Response object so that we can edit headers.
response = new Response(response.body, response)
// Check for cookie.
let cookies = request.headers.get('Cookie') || ""
if (cookies.includes("returning=true")) {
if (cookies.includes("comment_") && response.headers.has("Cache-Control")) {
// User has commented. Delete "cache-control" header.
response.headers.delete("Cache-Control")
// Return on to client.
return response
}
// User has been here before but has not commented.
// Just pass request through.
return fetch(request)
}
// Add headers.
response.headers.set("Link",
"</path/to/file.css>; rel=preload; as=style; nopush")
response.headers.append("Link",
"</path/to/script.js>; rel=preload; as=script; nopush")
// Set cookie so that we don't add the headers next time.
response.headers.set("Set-Cookie", "returning=true")
// Return on to client.
return response
}
However, if you're trying to delete a header which is set by Cloudflare in the first place (in this case Cache-Control
) you'll encounter an unknown error 1101 which will make your site inaccessible. Also you can't modify a header set by Cloudflare. Apparently you can ONLY manipulate headers set by origin and eventually add new headers.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With