CJ_Clippy 6caf2dbcc3
Some checks failed
ci / test (push) Failing after 9m42s
fp/our CI/CD / build (push) Successful in 1m19s
add /vods and /vt/:slug/vods
2025-11-08 12:36:26 -08:00

107 lines
3.8 KiB
JavaScript

/// <reference path="../pb_data/types.d.ts" />
/**
* onFileDownloadRequest hook is triggered before each API File download request. Could be used to validate or modify the file response before returning it to the client.
* @see https://pocketbase.io/docs/js-event-hooks/#onfiledownloadrequest
*
* We use this to return a 302 to the CDN asset instead of having the asset proxied via Pocketbase
* @see https://github.com/pocketbase/pocketbase/discussions/5995
*
*/
onFileDownloadRequest((e) => {
// console.log('onFileDownloadRequest hook has been triggered ~~~');
// console.log('onFileDownloadRequest hook has been triggered ~~~');
// console.log('onFileDownloadRequest hook has been triggered ~~~');
// console.log('onFileDownloadRequest hook has been triggered ~~~');
// console.log('onFileDownloadRequest hook has been triggered ~~~');
// console.log('onFileDownloadRequest hook has been triggered ~~~');
// console.log('onFileDownloadRequest hook has been triggered ~~~');
// console.log('onFileDownloadRequest hook has been triggered ~~~');
// console.log('onFileDownloadRequest hook has been triggered ~~~');
// console.log('onFileDownloadRequest hook has been triggered ~~~');
// e.next()
// e.app
// e.collection
// e.record
// e.fileField
// e.servedPath
// e.servedName
// and all RequestEvent fields...
const securityKey = process.env?.BUNNY_TOKEN_KEY;
const baseUrl = process.env?.BUNNY_ZONE_URL;
console.log(`securityKey=${securityKey}, baseUrl=${baseUrl}`)
if (!securityKey) {
console.error('BUNNY_TOKEN_KEY was missing from env');
return e.next();
}
if (!baseUrl) {
console.error('BUNNY_ZONE_URL was missing from env');
return e.next();
}
/**
* Generates a BunnyCDN-style signed URL using directory tokens.
*
* We sign URLs to make hotlinking difficult
* @see https://support.bunny.net/hc/en-us/articles/360016055099-How-to-sign-URLs-for-BunnyCDN-Token-Authentication
* @see https://github.com/pocketbase/pocketbase/discussions/5983#discussioncomment-11426659 // HMAC in pocketbase
* @see https://github.com/pocketbase/pocketbase/discussions/6772 // base64 encode the hex
*/
function signUrl(securityKey, baseUrl, path, expires) {
if (!path.startsWith('/')) path = '/' + path;
if (baseUrl.endsWith('/')) throw new Error(`baseUrl must not end with a slash. got baseUrl=${baseUrl}`);
const hashableBase = securityKey + path + expires;
// Generate and encode the token
const tokenH = $security.sha256(hashableBase);
const token = Buffer.from(tokenH, "hex")
.toString("base64")
.replace(/\n/g, "") // Remove newlines
.replace(/\+/g, "-") // Replace + with -
.replace(/\//g, "_") // Replace / with _
.replace(/=/g, ""); // Remove =
// Generate the URL
const signedUrl = baseUrl + path + '?token=' + token + '&expires=' + expires;
return signedUrl;
}
console.log(`record: ${JSON.stringify(e.record)}`)
console.log(`collection: ${JSON.stringify(e.collection)}`)
console.log(`app: ${JSON.stringify(e.app)}`)
console.log(`fileField: ${JSON.stringify(e.fileField)}`)
console.log(`servedPath: ${JSON.stringify(e.servedPath)}`)
console.log(`servedName: ${JSON.stringify(e.servedName)}`)
// Our job here is to take the servedPath, and sign it using bunnycdn method
// Then serve a 302 redirect instead of serving the file proxied thru PB
const path = e.servedPath;
const expires = Math.round(Date.now() / 1000) + 3600;
const signedUrl = signUrl(securityKey, baseUrl, path, expires);
console.log(`signedUrl=${signedUrl}`);
// This redirect is a tricky thing. We do this to avoid proxying file requests via our pocketbase origin server.
// The idea is to reduce load.
// HOWEVER, this redirect slows down image loading because it now takes 2 requests per image.
e.redirect(302, signedUrl);
e.next()
})