Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- addEventListener("fetch", event => {
- /*event.respondWith(handleRequest(event.request))*/
- event.respondWith(handleRequest(event))
- })
- /**
- * Fetch and log a request
- * @param {Request} request
- */
- async function handleRequest(event) {
- const request = event.request
- // console.log(request.url)
- if(request.method == "GET") {
- // Your Worker is responsible for automatic format negotiation. Check the Accept header. Avoid the cache returning an unsupported image format. Instead, check the acceptable format and cache the different formats independently.
- const accept = request.headers.get("Accept");
- let format = ""
- if (/image\/avif/.test(accept)) {
- // format = "avif"
- format = "native"
- } else if (/image\/webp/.test(accept)) {
- format = "webp"
- } else {
- format = "native"
- }
- // Hook in to the cache and have any cache-control headers respected
- const cache = caches.default;
- let resp = await cache.match(request.url + "&" + format)
- // let resp = null; //test code
- if (!resp) { // If not found in the edge cache, proceed to R2 check
- // Make some variables to get the original request's info and params
- const cacheCheckURL = new URL(request.url);
- const cacheCheckImagePath = cacheCheckURL.searchParams.get("image").substring(1); // get rid of that leading slash since it was issues
- const cacheCheckImageQ = cacheCheckURL.searchParams.get("q");
- const cacheCheckImageW = cacheCheckURL.searchParams.get("w");
- // Check if the image is in the R2 bucket
- let R2Object = await IR_CACHE.get(cacheCheckImagePath + "&" + format + "&" + cacheCheckImageQ + "&" + cacheCheckImageW);
- // If R2Object is available [i.e., it exists or is not stale (2 weeks)], then we'll return it directly. Otherwise, we have to run Image Resizing again and add it into both Edge Cache and R2 bucket.
- if (R2Object && new Date() - R2Object.uploaded < 1000 * 60 * 60 * 24 * 7 * 2) {
- // The resized image is in the R2 bucket so we just return that in full
- console.log("Matched R2 Cache");
- // Set the relevant headers as necessary
- const R2ObjectHeaders = new Headers(request.headers);
- R2ObjectHeaders.set("Cache-Control", "public, max-age=604800, stale-while-revalidate=86400");
- R2ObjectHeaders.set('etag', R2Object.httpEtag);
- R2ObjectHeaders.set("R2-Status", "HIT");
- resp = new Response(R2Object.body, {headers: R2ObjectHeaders}); // return the R2 object
- // if R2 is hit that meant Edge Cache got evicted. Put request back into edge cache to still utilize that over R2 preferably.
- event.waitUntil(cache.put(request.url + "&" + format, resp.clone()));
- } else {
- // Run Image Resizing per resize params
- resp = await runResize(request)
- // Use event waitUntil so we can send the response but
- // script keeps executing until the response is saved in the cache
- if(resp.status == 200) {
- // Put the resized image into Colo Cache
- event.waitUntil(cache.put(request.url + "&" + format, resp.clone()));
- // Put the resized image into R2 bucket
- event.waitUntil(
- IR_CACHE.put(cacheCheckImagePath + "&" + format + "&" + cacheCheckImageQ + "&" + cacheCheckImageW, resp.clone().body, {
- // Use the headers from the Image Resizing response so we maintain contentType and other HTTP headers
- httpMetadata: resp.headers,
- // Add some custom metadata to the R2 object just in case even though we'll probably not need it
- customMetadata: {
- format: format,
- putDate: new Date().toISOString()
- }
- })
- );
- }
- }
- } else {
- console.log("Matched Edge Cache")
- }
- return resp
- }
- // const resp = await runResize(request)
- // console.log("second return")
- // return resp
- }
- async function runResize(request) {
- // Parse request URL to get access to query string
- let url = new URL(request.url)
- // console.log(url.searchParams.get("w"))
- // Cloudflare-specific options are in the cf object.
- let options = { cf: { image: {} } }
- // Copy parameters from query string to request options.
- // You can implement various different parameters here.
- options.cf.image.fit = "contain"
- if (url.searchParams.has("w")) options.cf.image.width = url.searchParams.get("w")
- if (url.searchParams.has("q")) {
- options.cf.image.quality = url.searchParams.get("q")
- } else {
- options.cf.image.quality = "100"
- }
- if ( options.cf.image.width == "2560" ) {
- options.cf.image.draw = [{
- url: "https://fjlaboratories.com/cdn/miscellaneous/watermark.png", // draw this image
- bottom: 30, // 5 pixels from the bottom edge
- right: 30, // 5 pixels from the right edge
- fit: "contain", // make it fit within 100x50 area
- width: 120,
- opacity: 0.6, // 20% transparent
- }]
- }
- // console.log(options.cf.image)
- // Your Worker is responsible for automatic format negotiation. Check the Accept header.
- const accept = request.headers.get("Accept");
- if (/image\/avif/.test(accept)) {
- //options.cf.image.format = 'avif';
- } else if (/image\/webp/.test(accept)) {
- options.cf.image.format = 'webp';
- }
- // Get URL of the original (full size) image to resize.
- // You could adjust the URL here, e.g., prefix it with a fixed address of your server,
- // so that user-visible URLs are shorter and cleaner.
- const imageURL = "https://fjlaboratories.com/r2-images/" + url.searchParams.get("image") + "?key=" + IR_KEY
- if (!url.searchParams.get("image")) return new Response('Missing "image" value', { status: 400 })
- console.log(imageURL)
- try {
- // TODO: Customize validation logic
- const { hostname, pathname } = new URL(imageURL)
- // Optionally, only allow URLs with JPEG, PNG, GIF, or WebP file extensions
- // @see https://developers.cloudflare.com/images/url-format#supported-formats-and-limitations
- if (!/\.(jpe?g|png|gif|webp)$/i.test(pathname)) {
- return new Response('Disallowed file extension', { status: 400 })
- }
- // Demo: Only accept "example.com" images
- // if (hostname !== 'r2-images-fetch.fj-homelab.workers.dev) {
- // return new Response('Must use "fjlaboratories.com" source images', { status: 403 })
- // }
- } catch (err) {
- return new Response('Invalid "image" value', { status: 400 })
- }
- // Build a request that passes through request headers
- const imageRequest = new Request(imageURL, {
- headers: request.headers
- })
- // Returning fetch() with resizing options will pass through response with the resized image.
- const resizedRes = await fetch(imageRequest, options);
- // console.log(resizedRes);
- const cachedHeaders = new Headers(resizedRes.headers);
- cachedHeaders.set("Cache-Control", "public, max-age=604800, stale-while-revalidate=86400");
- return new Response(resizedRes.body, {
- headers: cachedHeaders
- });
- // https://dev-images.fjlaboratories.com/?image=/feature-images/shubham-dhage-fcbnWSjh1U8-unsplash.jpg&w=1920&q=70
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement