Dave Lozier
Dave Lozier

Reputation: 162

Pass redirect through to visitor?

When my worker encounters a redirect from origin it follows it and returns the content rather than passing the redirect on to the visitor. Does anyone know how to force the worker to respond with the same redirect it receives from origin?

This is in conjunction with a proxy.

http://server.one/proxy-path/old-directory/ request is sent to http://server.two/old-directory/ which responds with a 301 to /new-directory/. The end result should be that the visitor is sent to http://server.one/proxy-path/new-directory/ but what happens is that the worker follows the redirect and serves up the content from /new-directory/ under the /proxy-path/old-directory/ path.

Hopefully this made sense. Thanks for any insight!

Upvotes: 0

Views: 421

Answers (2)

Kenton Varda
Kenton Varda

Reputation: 45336

Following redirects is the default behavior of fetch(). You can override it like:

fetch(url, {redirect: "manual"})

But there may be a deeper problem with your script. Normally, the incoming event.request already has the redirect = "manual" property set, so if you were to pass event.request directly to fetch(), then you would get the behavior you want. If you are seeing redirects being automatically followed, that suggests that you are not passing the original request object and, moreover, you have dropped some of the original request's properties.

This commonly happens when people write code like:

// INCORRECT: Loses request properties and headers!
let newUrl = rewriteUrl(event.request.url);
event.respondWith(fetch(newUrl));

Sometimes people realize that this loses the headers, so they try to add them back like:

// STILL INCORRECT: Loses request properties other than headers!
let newUrl = rewriteUrl(event.request.url);
event.respondWith(fetch(newUrl, {headers: event.request.headers}));

The correct thing to do is to pass the whole request object as the second parameter to fetch(), like:

// CORRECT
let newUrl = rewriteUrl(event.request.url);
event.respondWith(fetch(newUrl, event.request));

This way, all of the request's properties, including redirect, method, body, etc., get copied over.

Note that if you want to modify the URL and the headers, you need to do two steps:

let newUrl = rewriteUrl(event.request.url);
let newHeaders = rewriteHeaders(event.request.headers);
// Create a new Request object with the new headers.
let newRequest = new Request(event.request, {headers: newHeaders});
// Fetch the new URL using the new Request object.
event.respondWith(fetch(newUrl, newRequest));

Alternatively, you can take advantage of the fact that a Request object you created yourself (as opposed to the one you received on the event) is mutable:

let newUrl = rewriteUrl(event.request.url);
// Create a new Request object with modified URL.
let newRequest = new Request(newUrl, event.request);
// Modify the headers directly on this object.
newRequest.headers.set("X-Foo", "Bar");
// Forward it on.
event.respondWith(fetch(newRequest));

Upvotes: 3

Dave Lozier
Dave Lozier

Reputation: 162

I guess I asked the question to soon. Based on https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch I see that I can add redirect: 'manual' to the proxy request which returns the redirect response I expected.

Upvotes: 0

Related Questions