Last active
January 17, 2025 14:15
-
-
Save jakeisnt/1cae0f2f21c77d9dc5910f670e255fa3 to your computer and use it in GitHub Desktop.
Cloudflare worker: leverage cloudflare image resizing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* - Run `npm run dev` in your terminal to start a development server | |
* - Open a browser tab at http://localhost:8787/ to see your worker in action | |
* - Run `npm run deploy` to publish your worker | |
* | |
* Bind resources to your worker in `wrangler.toml`. After adding bindings, a type definition for the | |
* `Env` object can be regenerated with `npm run cf-typegen`. | |
* | |
* Learn more at https://developers.cloudflare.com/workers/ | |
*/ | |
const B2_URL = 'YOUR_BACKBLAZE_IMAGE_URL'; | |
/** | |
* Parse query parameters and return an object with width, height, quality, and format. | |
* If no query parameters are present, return null. | |
* | |
* @param params - The URLSearchParams object containing query parameters. | |
* @param request - The Request object. | |
* @returns An object with width, height, quality, and format, or null if no query parameters are present. | |
*/ | |
const parseQueryParams = (params: URLSearchParams, request: Request) => { | |
const width = Number(params.get('w') || params.get('width')) || undefined; | |
const height = Number(params.get('h') || params.get('height')) || undefined; | |
const quality = Number(params.get('q') || params.get('quality')) || undefined; | |
const format = request.headers.get('Accept')?.includes('image/webp') ? ('webp' as const) : ('jpeg' as const); | |
if (!width && !height && !quality) { | |
return null; | |
} | |
return { width, height, quality, format }; | |
}; | |
/** | |
* Return a 404 response with a message. | |
* | |
* @param message - The message to return in the response. | |
* @returns A 404 response with the message. | |
*/ | |
const notFound = (message: string = '! img') => | |
new Response(message, { | |
status: 404, | |
headers: { | |
'Content-Type': 'text/plain', | |
'Cache-Control': 'public, max-age=3600', | |
}, | |
}); | |
export default { | |
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> { | |
const url = new URL(request.url); | |
const path = url.pathname; | |
const params = url.searchParams; | |
if (path === '/') { | |
return new Response('OK', { status: 200 }); | |
} | |
const queryConfig = parseQueryParams(params, request); | |
const b2URL = `${B2_URL}${path}`; | |
const originResponse = await fetch(b2URL, { | |
cf: { | |
image: { | |
...queryConfig, | |
fit: 'scale-down', | |
}, | |
}, | |
}); | |
if (originResponse.ok) { | |
return new Response(originResponse.body, { | |
status: 200, | |
headers: { | |
'Cache-Control': 'public, max-age=31536000', | |
'Content-Type': originResponse.headers.get('content-type') || 'image/jpeg', | |
}, | |
}); | |
} | |
// Return 404 if the origin image isn't found | |
return notFound(`${originResponse.statusText}: ${originResponse.status}\n 'failed to fetch original image'`); | |
}, | |
} satisfies ExportedHandler<Env>; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Instructions:
NOTE: This doesn't seem to be compatible with local Wrangler debugging but functions correctly when hosted on their production system. Setting this up for local development involves round-tripping to 'cdn-cgi/image' with URL parameters that correspond to image resizing commands, enabling the route-based Cloudflare image transformation API to do so.