Redirect not working when transforming via Workers onError event

Hi folks, I have a worker that resizes images; everything works well except when the animated GIF is too large, which returns an error. I'm trying to redirect upon encountering an error, but without success. What I'm doing wrong? The code:
async function handleRequest(request) {
let url = new URL(request.url);
let options = { cf: { image: { onerror: 'redirect' }}};

if (url.searchParams.has('width')) {
options.cf.image.width = url.searchParams.get('width');
}

if (url.searchParams.has('fit')) {
options.cf.image.fit = url.searchParams.get('fit');
}

if (url.searchParams.has('height')) {
options.cf.image.height = url.searchParams.get('height');
}

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';
}

const imagePath = url.pathname.slice(1);
if (!imagePath) {
return new Response('No image path specified', { status: 400 });
}

const imageRequest = new Request(`https://pub-8eca27df6a304971abd1fe716bc29b.r2.dev/files/${imagePath}`, { headers: request.headers });

const response = await fetch(imageRequest, options);

return new Response(response.body, { status: response.status, headers: response.headers });
}
async function handleRequest(request) {
let url = new URL(request.url);
let options = { cf: { image: { onerror: 'redirect' }}};

if (url.searchParams.has('width')) {
options.cf.image.width = url.searchParams.get('width');
}

if (url.searchParams.has('fit')) {
options.cf.image.fit = url.searchParams.get('fit');
}

if (url.searchParams.has('height')) {
options.cf.image.height = url.searchParams.get('height');
}

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';
}

const imagePath = url.pathname.slice(1);
if (!imagePath) {
return new Response('No image path specified', { status: 400 });
}

const imageRequest = new Request(`https://pub-8eca27df6a304971abd1fe716bc29b.r2.dev/files/${imagePath}`, { headers: request.headers });

const response = await fetch(imageRequest, options);

return new Response(response.body, { status: response.status, headers: response.headers });
}
C
Chaika40d ago
You shouldn't be using pub-r2.dev URLs. They're not meant for production and are rate-limited The onerror option has this description
In case of a fatal error that prevents the image from being resized, redirects to the unresized source image URL. This may be useful in case some images require user authentication and cannot be fetched anonymously via Worker. This option should not be used if there is a chance the source image is very large. This option is ignored if the image is from another domain, but you can use it with subdomains. Example:
You should be using an R2 Custom Domain anyway, so try using one and then see if that option works.
N
Nuno40d ago
Thanks for the help. I will try it. Again thank you! When I switch to the custom domain upon encountering an error, it returns: 'Error 1014 - CNAME Cross-User Banned.' However, the images that don't return an error work well...
C
Chaika40d ago
Interesting.. it redirects you to the source image on the R2 Custom Domain, and you get that error? Can you access it directly instead of through the redirect, and it works?
N
Nuno40d ago
No, the URL remains the same, so I think it doesn't execute the redirect. I can access the file through the R2 custom domain (s.example.com), but the worker uses a different custom domain (images.example.com). Therefore, when I request images.example.com/big-gif-file, it returns 'Error 1014 - CNAME Cross-User Banned'.
C
Chaika40d ago
how big is your GIF? I haven't played around with the error stuff too much, but for me it just gives up and returns fine with these warnings
No description
C
Chaika40d ago
that's an ~80mb gif
N
Nuno40d ago
C
Chaika40d ago
what settings are you trying to use with it? a specific width/height/fit? opps nvm I get it on that gif as well, must be too small to give up on right away
N
Nuno40d ago
I tried with many... all of them return this error: ERROR 9413: Could not resize the image: The animation is too large. Animation resolution is 2000×1000, and at this size the maximum number of animation frames allowed is 88 (total area of all frames together must be less than 100000000), but the animation is longer than this What I want in these cases is to bypass the original file, or find a workaround to convert it to MP4 in the future
C
Chaika40d ago
Do you want an actual http redirect, or just seamlessly showing the non-modified file?
N
Nuno40d ago
just showing the non-modified file is ok
C
Chaika40d ago
yea it looks like the onerror stuff conflicts with R2 Custom Domains/the CF for SaaS setup. I was trying to see if I could get it to play nice. Might just need to either redirect to source or do a second fetch request if it fails which is silly
N
Nuno40d ago
Thank you for your time. I'd like to buy you a beer as a token of my appreciation 🙂
C
Chaika40d ago
thanks I'm good though, didn't even solve the issue lol. One workaround may be to use the URL format fetching through the Worker (ex, have the worker call /cdn-cgi/image/width=1800,quality=75,format=auto/image), but onerror=redirect quite literally redirects the user. You could accomplish the same in your worker by checking for the cross-domain error (which is silly but works)
if (response.status == 403) { // replace with your url
return Response.redirect(`https://i.chaika.me/${imagePath}`, 302)
}
if (response.status == 403) { // replace with your url
return Response.redirect(`https://i.chaika.me/${imagePath}`, 302)
}
or by fetching the original to seamlessly return the non-resized on failure
if (response.status == 403) {
return fetch(`https://i.chaika.me/${imagePath}`)
}
if (response.status == 403) {
return fetch(`https://i.chaika.me/${imagePath}`)
}
no matter what you're not going to be able to avoid a second request, although if you have caching setup right on your Custom domain, which it looks like you do, that second request is going to be super cheap/from cache
N
Nuno40d ago
Hmm I will try. But like you said this is a bug right? Is expected that it will be fixed soon or not? I think this is a good fix for now. Thank you for your time. 🙂
C
Chaika40d ago
I wouldn't hold your breath but I can make a report and see. It is really strange behavior but understandable from the viewpoint that CF for SaaS (which R2 Custom Domains use) are weird to begin with and this isn't the first feature to have issues with it like this. The whole thing of CF for SaaS applying two zone's/website's settings (yours + r2.dev's in this case) and linking requests over is a bunch of weird magic
N
Nuno40d ago
eheh ok anyway, thank you
C
Chaika39d ago
turns out the onerror option doesn't seem to exist/work in Workers at all, despite the documentation. It's not in worker-types and doesn't work with a normal origin. I reported that first lol There is an interesting section about error handling here: https://developers.cloudflare.com/images/transform-images/transform-via-workers/#error-handling nothing too helpful though
N
Nuno37d ago
Thanks! Please send me a message, as I would like to talk with you about a code review. I'm seeking your help to validate and improve my worker.
Want results from more Discord servers?
Add your server
More Posts
can i run --force here ?can i run --force here ?Workers KV get throws TypeError: Cannot read properties of undefined (reading 'get')My wrangler.toml file looks like this: ``` kv_namespaces = [ { binding = "BH_API_KEYS", id = "xxxPaid for the Services.Paid for support, my site is under DDOs attacks I would like a dev to help me resolve this issue. passh over cloudlare tunnel with iPhoneHi, I successfully got an ssh connection through a cloudflare tunnel on windows but it worked becausView bandwidth usage by pages website?Is there any way to see how much bandwidth a pages project has used?Exporting WAF Logs on Business planIs it possible to use the API to export the WAF logs and then i can parse and import it to an externWorker Loop and error because or External rendering serviceI face an issue... I use a worker that loads a page on an external site but I see a strange Loop comContacting by chat impossible or nightmare?The support system is not showing any option accessing to the live chat.... Can someone help me or gFeature Request: Route Zone LinkA small dashboard feature that would make things a bit more seamless would be adding a link to the rpricing of web3?Hi guys, I am trying to find the pricing of the ethereum web3 gateway. Since it's a usage-based billWebsite domain stuck at verifying but subdomains workingI have a Pages project and I'm trying to add a domain to it. So the site has been added under WebsitStreaming video via tunnelsI read the blogpost on the ToS changes and I'm having trouble discerning whether or not hosting someCan I use CF CDN to cache my images in CF imagesCan I use CF CDN to cache my images in CF images?Can we use `service` bindings withCan we use `service` bindings with `getRequestContext()`? I am trying to add it in `wrangler.toml` b"[Error: Network connection lost.]"I have a KV - which I will be used for keeping track of domains, I have assigned it to the Worker, aPages Inactive (ErroHi everyone, I have a little problem, when adding a custom domain to my page it shows Inactive (ErroPreview branch, custom domain not supportedWhen adding a custom domain for a preview branch using external DNS, this page states that custom donpm install --forceIs there a way to have this be the build command instead of the current npx @Cloudflare/next-on-pageHow to specify "production" deploy via wrangler?We're not using the git integration, but still pass "--branch" parameters when deploying so that we Cloudflare Warp HelpI’ve been using warp for years now and K just switched from an Intel Mac to a silicon Mac. I downloa