Purge selected files depending on publish or update webhook action with Ghost and Cloudflare
/* eslint-disable no-undef */ | |
const url = require('url'); | |
function generateSimpleResponse(httpCode, strMessage) { | |
return new Response(JSON.stringify({ result: strMessage }), { | |
status: httpCode, | |
headers: { | |
'Content-Type': 'application/json', | |
}, | |
}); | |
} | |
/** | |
* Purge the cache depending on whether this is a new publication or if this | |
* is an update to an existing article. Be explicit about the URLs that we | |
* want to clear from the cache to ensure that we only purge what is | |
* necessary. | |
*/ | |
async function purgeCache(event, request) { | |
let files = []; | |
if (event === 'publish') { | |
console.log('Clearing cache for homepage and rss.'); | |
files = [ | |
'https://www.adammalone.net/', | |
'https://www.adammalone.net/rss/', | |
]; | |
} | |
if (event === 'update') { | |
const reqBody = await readRequestBody(request); | |
const bodyJson = JSON.parse(reqBody); | |
const purgeUrl = bodyJson.post.current.url || 'https://www.adammalone.net'; | |
console.log(`Clearing cache for ${purgeUrl}`); | |
files = [ | |
purgeUrl, | |
]; | |
} | |
apiPayload = { | |
files: files, | |
}; | |
const apiUrl = 'https://api.cloudflare.com/client/v4/zones/' + CF_ZONE_ID + '/purge_cache'; | |
const init = { | |
body: JSON.stringify(apiPayload), | |
method: 'POST', | |
headers: { | |
Authorization: 'Bearer ' + CF_AUTH_TOKEN, | |
}, | |
}; | |
const response = await fetch(apiUrl, init); | |
return await response.json(); | |
} | |
addEventListener('fetch', (event) => { | |
event.respondWith(handleRequest(event.request)); | |
}); | |
/** | |
* readRequestBody reads in the incoming request body | |
* Use await readRequestBody(..) in an async function to get the string | |
* @param {Request} request the incoming request to read from | |
*/ | |
async function readRequestBody(request) { | |
const { headers } = request; | |
const contentType = headers.get('content-type') || ''; | |
if (contentType.includes('application/json')) { | |
return JSON.stringify(await request.json()); | |
} | |
else if (contentType.includes('application/text')) { | |
return await request.text(); | |
} | |
else if (contentType.includes('text/html')) { | |
return await request.text(); | |
} | |
else if (contentType.includes('form')) { | |
const formData = await request.formData(); | |
const body = {}; | |
for (const entry of formData.entries()) { | |
body[entry[0]] = entry[1]; | |
} | |
return JSON.stringify(body); | |
} | |
else { | |
const myBlob = await request.blob(); | |
const objectURL = URL.createObjectURL(myBlob); | |
return objectURL; | |
} | |
} | |
/** | |
* Determines the type of cache clearing that needs to be done by the path that | |
* we hit the endpoint with. Use this to then purge the cache. | |
*/ | |
async function handleRequest(request) { | |
const urlParts = url.parse(request.url); | |
if (urlParts.pathname === `/cf-purge/purge/publish/${WEBHOOK_USER}/${WEBHOOK_PASSWORD}/`) { | |
const responseData = await purgeCache('publish', request); | |
if (responseData.success) { | |
return generateSimpleResponse(200, responseData); | |
} | |
else { | |
return generateSimpleResponse(500, 'FAILED'); | |
} | |
} | |
if (urlParts.pathname === `/cf-purge/purge/update/${WEBHOOK_USER}/${WEBHOOK_PASSWORD}/`) { | |
const responseData = await purgeCache('update', request); | |
if (responseData.success) { | |
return generateSimpleResponse(200, responseData); | |
} | |
else { | |
return generateSimpleResponse(500, 'FAILED'); | |
} | |
} | |
return generateSimpleResponse(404, 'NOT FOUND'); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment