Skip to content

Instantly share code, notes, and snippets.

@techforum-repo
Created August 29, 2020 19:52
Show Gist options
  • Save techforum-repo/5c3f9568d3907a039f55ad552a58e3bc to your computer and use it in GitHub Desktop.
Save techforum-repo/5c3f9568d3907a039f55ad552a58e3bc to your computer and use it in GitHub Desktop.
//Refer the original script - https://blog.cloudflare.com/edge-side-includes-with-cloudflare-workers/
//Modified the script - to include the main request headers while invoking the ESI resources
//- Support ESI source path with complete source URL, fetch the hostname and proptocol from original request
addEventListener("fetch", event => {
event.respondWith(fetchAndStream(event.request))
event.passThroughOnException()
})
async function fetchAndStream(request) {
let response = await fetch(request)
let contentType = response.headers.get('content-type')
if (!contentType || !contentType.startsWith("text/")) {
return response
}
let { readable, writable } = new TransformStream()
let newResponse = new Response(readable, response)
newResponse.headers.set('cache-control', 'max-age=0')
streamTransformBody(request,response.body, writable)
return newResponse
}
async function handleTemplate(request,encoder, templateKey) {
const linkRegex = /(esi:include.*src="(.*?)".*\/)/gm
let result = linkRegex.exec(templateKey);
let esi
if (!result) {
return encoder.encode(`<${templateKey}>`);
}
if (result[2]) {
esi = await subRequests(request,result[2]);
}
return encoder.encode(
`${esi}`
);
}
async function subRequests(request,target){
let requestHeaders = new Headers(request.headers);
let url = new URL(request.url)
let nocacheurl=url.protocol+'//'+url.hostname+target;
const init = {
method: 'GET',
headers:requestHeaders
}
let response = await fetch(nocacheurl, init)
let text = await response.text()
return text
}
async function streamTransformBody(request,readable, writable) {
const startTag = "<".charCodeAt(0);
const endTag = ">".charCodeAt(0);
let reader = readable.getReader();
let writer = writable.getWriter();
let templateChunks = null;
while (true) {
let { done, value } = await reader.read();
if (done) break;
while (value.byteLength > 0) {
if (templateChunks) {
let end = value.indexOf(endTag);
if (end === -1) {
templateChunks.push(value);
break;
} else {
templateChunks.push(value.subarray(0, end));
await writer.write(await translate(request,templateChunks));
templateChunks = null;
value = value.subarray(end + 1);
}
}
let start = value.indexOf(startTag);
if (start === -1) {
await writer.write(value);
break;
} else {
await writer.write(value.subarray(0, start));
value = value.subarray(start + 1);
templateChunks = [];
}
}
}
await writer.close();
}
async function translate(request,chunks) {
const decoder = new TextDecoder();
let templateKey = chunks.reduce(
(accumulator, chunk) =>
accumulator + decoder.decode(chunk, { stream: true }),
""
);
templateKey += decoder.decode();
return handleTemplate(request,new TextEncoder(), templateKey);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment