Images can be accessed normally through curl/insomnia, but not through a browser

Hello everyone,

My issue is with the following address: https://images.sakurasou.io/33558705/80230341_p12_width_960.webp

I have a worker with a route of images.sakurasou.io/*, which fetches the corresponding image from r2 based on the path content. It works perfectly fine for request like https://images.sakurasou.io/33558705/80230341_p12_width_320.webp and https://images.sakurasou.io/33558705/80230341_p12_width_1280.webp, among others.

However, only the image at https://images.sakurasou.io/33558705/80230341_p12_width_960.webp, which is a webp image with a width of 960px, is not accessible. I am certain it exists in r2, and I have also tried accessing it directly through r2’s domain, which works fine.

For this inaccessible image, I have tried using tools like curl or insomnia, and they can access it without any issues, the response header shows content-type as image/webp. But both Chrome and Firefox respond with a 500 error, and content-type is image/png, return an 1*1’s img

I have checked the ws logs provided by the worker, and they indicate a 200 status response, while the browser shows a 500 error. I am unsure where the problem lies.

Thank you for your assistance.

r2 storage bucket’s domain is images-r2.sakurasou.io. By replacing the authority of the worker URL with this domain, you should be able to access the images.

Here are two more images to reproduce the issue:

  • https://images.sakurasou.io/92965716/106975702_p0_width_960.webp
  • https://images.sakurasou.io/41736171/75846108_p0_width_960.webp

For these images, physical copies exist for widths: 320, 640, 960, 1280, 1440, and 1920. No conversion is needed.

Here is the code for the worker:

// import...

const decodeImage = async (buffer, format) => {
  if (format === "jpeg" || format === "jpg") {
    await initJpegWasm(JPEG_DEC_WASM);
    return decodeJpeg(buffer);
  } else if (format === "png") {
    await initPngWasm(PNG_DEC_WASM);
    return decodePng(buffer);
  } else if (format === "webp") {
    await initWebpDecWasm(WEBP_DEC_WASM);
    return decodeWebp(buffer);
  }

  throw new Error(`Unsupported format: ${format}`);
};

async function handleRequest(request, env, ctx) {
  try {
    const url = new URL(request.url);
    const path = url.pathname.split("/").filter((p) => p);
    if (path.length !== 2) {
      return new Response("Invalid URL format. Expected format: uid/pid", {
        status: 400,
      });
    }
    const [uid, pid] = path;
    const imageType = pid.split(".")[1];
    const r2Key = `${uid}/${pid}`;
    let cacheKey;
    const cacheExpire = 60 * 60 * 24 * 7; // 1 week

    const qualityParam = url.searchParams.get("quality");
    let qualityValue = 75;
    switch (qualityParam) {
      case "0":
        qualityValue = 100;
        break;
      case "1":
        qualityValue = 75;
        break;
      case "2":
        qualityValue = 50;
        break;
    }

    const thParam = url.searchParams.get("th");
    let th;
    if (thParam && !isNaN(parseInt(thParam))) {
      th = parseInt(thParam);
      cacheKey = `image:${uid}:${pid}:${qualityValue}:${th}`;
    } else {
      cacheKey = `image:${uid}:${pid}:${qualityValue}`;
    }

    let webpImage;

    const cacheResult = await env.imagesCache.get(cacheKey, {
      type: "arrayBuffer",
    });

    if (cacheResult) {
      webpImage = cacheResult;
    } else {
      const supportedExtensions = ["jpg", "jpeg", "png", "webp"];
      if (!supportedExtensions.includes(imageType)) {
        return new Response("Unsupported image type", { status: 400 });
      }

      const image = await env.imagesR2.get(r2Key);
      const imageBuffer = await image.arrayBuffer();
      if (!imageBuffer) {
        return new Response("Image not found", { status: 404 });
      }

      if (imageType === "webp" && !th) {
        webpImage = imageBuffer;
        await env.imagesCache.put(cacheKey, webpImage, {
          expirationTtl: cacheExpire,
        });
        return new Response(webpImage, {
          headers: { "Content-Type": "image/webp" },
        });
      }

      let imageData = await decodeImage(imageBuffer, imageType);

      if (th) {
        const originalWidth = imageData.width;
        const originalHeight = imageData.height;

        if (th != originalWidth) {
          const newHeight = (originalHeight * th) / originalWidth;

          await initResize(RESIZE_WASM);
          imageData = await resize(imageData, { height: newHeight, width: th });
        }
      }

      if (imageType !== "webp") {
        await initWebpEncWasm(WEBP_ENC_WASM);
        webpImage = await encodeWebp(imageData, {
          quality: qualityValue,
        });
      } else {
        await initWebpEncWasm(WEBP_ENC_WASM);
        webpImage = await encodeWebp(imageData);
      }

      await env.imagesCache.put(cacheKey, webpImage, {
        expirationTtl: cacheExpire,
      });
    }

    return new Response(webpImage, {
      headers: { "Content-Type": "image/webp" },
    });
  } catch (error) {
    console.error(error);
    return new Response("Error processing image", { status: 500 });
  }
}

export default {
  fetch: handleRequest,
};

Can not reproduce in MacOS:



Yes, it works fine on my iPhone, but not on Windows. Thanks 4 your reply.

1 Like

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.