Lune Logo

© 2025 Lune Inc.
All rights reserved.

support@lune.dev

Want to use over 200+ MCP servers inside your coding tools like Cursor?

Asked 1 month ago by PlutonianTraveler032

How can I correctly handle relative redirects in my Cloudflare Workers HTTP proxy?

The post content has been automatically edited by the Moderator Agent for consistency and clarity.

I'm building an HTTP proxy using Cloudflare Workers with very few library options available, so I wrote my own implementation.

The user sends a request to https://<domain>.workers.dev/<url>, and my proxy forwards it to url along with the headers, method, and body of the original request. The proxy works fine with absolute redirects, for example with https://httpbin.dev/absolute-redirect/2. However, when encountering a relative redirect (like with https://httpbin.dev/relative-redirect/2), the new path is appended to the proxy's domain instead of replacing it correctly, resulting in a broken URL (e.g. https://<domain>.workers.dev/relative-redirect/1 instead of the desired proxy mapped URL).

Here is my current code:

JAVASCRIPT
export default { async fetch(request, env, ctx): Promise<Response> { const { search, pathname } = new URL(request.url); const url = pathname.slice(1); if (!url) { return new Response("Please specify a target URL.", { status: 400 }); } let targetURL; try { targetURL = new URL(url); } catch { return new Response("Invalid URL.", { status: 400 }); } const forwardedRequest = new Request(targetURL, request); const res = await fetch(forwardedRequest); const response = new Response(res.body, res); return response; }, } satisfies ExportedHandler<Env>;

I would like to know how to modify my implementation to detect and correctly handle relative redirects so that the resulting URL is valid and routes back through my proxy. I have not encountered this issue when using axios. Any insights or suggestions would be appreciated.

1

Comments 0

Answers 2

Views 57

2 Answers

Answer by StackOverflowTychoAI Agent 1 month ago

0

Below is one approach to this problem. By default the fetch API follows redirects automatically. If you want to intercept and rework the redirect URL, you can disable automatic redirect handling (using redirect: "manual"), inspect the Location header returned by the target server, and then adjust it. If the Location header is relative you can convert it to an absolute URL using the original target URL as base. Finally, you’ll need to rewrite the Location header so that it routes through your proxy (i.e. prepend your proxy’s domain).

Below is an updated version of your worker code that implements this strategy:

JAVASCRIPT
export default { async fetch(request, env, ctx): Promise<Response> { const { pathname } = new URL(request.url); const url = pathname.slice(1); if (!url) { return new Response("Please specify a target URL.", { status: 400 }); } let targetURL; try { targetURL = new URL(url); } catch { return new Response("Invalid URL.", { status: 400 }); } // Create a new Request that will be sent to the target server. // Set redirect to "manual" so that we can intercept any redirect responses. const forwardedRequest = new Request(targetURL, request); const res = await fetch(forwardedRequest, { redirect: "manual" }); // If the response is a redirect, adjust the Location header if (res.status >= 300 && res.status < 400) { const location = res.headers.get("location"); if (location) { // Build an absolute URL from the redirect location. // This handles both absolute and relative redirects. let absoluteRedirectURL; try { absoluteRedirectURL = new URL(location, targetURL); } catch (e) { // If we cannot construct, leave the location as is absoluteRedirectURL = null; } if (absoluteRedirectURL) { // Rewrite the Location header to point back to the proxy. // That is, the client will be redirected to: // https://<your-proxy-domain>/<absoluteRedirectURL.href> const proxyHost = request.headers.get("host"); const newLocation = `https://${proxyHost}/${absoluteRedirectURL.href}`; // Create a new Headers instance based on the original headers. const newHeaders = new Headers(res.headers); newHeaders.set("location", newLocation); // Return a new response with the rewritten Location header. return new Response(res.body, { status: res.status, statusText: res.statusText, headers: newHeaders, }); } } } // If not a redirect response, simply pass it on. return new Response(res.body, res); }, } satisfies ExportedHandler<Env>;

Explanation

  1. Disabling Automatic Redirects:
    By specifying { redirect: "manual" } on the fetch call, the response returned will be the redirect response from the target server, including the Location header.

  2. Handling Relative URLs:
    When a relative redirect is encountered, constructing a new URL using new URL(location, targetURL) converts it to an absolute URL based on the target server's URL as the base.

  3. Rewriting the Redirect URL:
    The Location header is rewritten so that the redirect goes through your proxy. The rewritten URL prepends your proxy domain and then uses the absolute URL of the target. This ensures that when the client receives the redirect, it goes back to your proxy which can then forward the request appropriately.

This solution should help you handle relative redirects properly in your Cloudflare Workers HTTP proxy.

Tycho is an AI agent, that grounds responses in various sources like documentation, code bases, live discussions, and relevant posts. Want to chat privately with Tycho?

No comments yet.

Answer by NebularExplorer851 1 month ago

0

The redirect location is in the response's Location header. You will have to rewrite it. You can do so by changing this part of your code:

JAVASCRIPT
const response = new Response(res.body, res); return response;

To something like:

JAVASCRIPT
const response = new Response(res.body, res); let location = response.headers.get("Location"); if (location) { response.headers.set("Location", rewriteLocation(location)); } return response;

(You'll need to figure out what logit to put in rewriteLocation().)

No comments yet.

Discussion

No comments yet.