skip to Main Content

I have a case where I’m calling fetch() and if the response is a 302 Redirect, I want to redirect the calling page to wherever it redirects to instead of following the redirect to retrieve the data.

The scenario is that the user does something on a page which is going to do a fetch to retrieve something to update on the page. But if their login session has expired, the server is going to return a 302 Redirect to the login page. My Javascript is expecting a JSON response back, but instead fetch follows the redirect and it gets an HTML page.
What I really want to do is check if the response.status is 302, get the URL that the redirect pointed to and set window.location.

According to the documentation, I should be able to set redirect: "manual", then if the response.redirected is true redirect to response.url, or some say to retrieve the location header from the response

But none of that works.

  • response.redirected is never true.
  • response.status is zero.
  • response.url is the URL of the page that made the call, not where it was redirected to.
  • The location header is null.

The only thing that seems to work is that the Network tab shows that the server returned a 302 status.
Here’s my code:

   fetch("url-that-forces-a-redirect", {
       method: "POST",
       redirect: "manual",
       body: formData
    }).then((response) => {
       console.log("Response had status " + response.status);
       if (response.redirected) {
           var redirectedUrl = response.headers.get('location');
           console.log("Got redirect: location header = " + redirectedUrl);
           console.log("                 response.url = " + response.url);
           // window.location = redirectedUrl;
           return;
       }
    });

Is there any way to do this?

BTW, I tried doing this with XMLHttpRequest first and couldn’t find a way to do it there either.

2

Answers


  1. I don’t think this is the correct approach. If the ajax page sends and http redirect status, this means the ajax is moved to another place, not the calling page.

    The ajax page instead shoud return a correct 200 Ok reply with a parameter, you decide the name, in the json response that tells the calling page to redirect.

    The inner page could return a reply like:

     {status:"ok", forceRedirectTo: "http://www.page.com", ...}
    

    And the outer page could just test:

    if(reply.hasOwnProperty(forceRedirectTo)) {
    window.location = forceRedirectTo;
    }

    Login or Signup to reply.
  2. Handling a 302 Redirect with the fetch() API is tricky because fetch() will follow redirects automatically by default, and setting redirect: "manual" doesn’t stop the browser from handling the redirect internally, it just prevents fetch from following it automatically. However, the behavior you’re describing—where the status is 0 and response.url points to the original page—indicates that the fetch() API is not giving you access to the redirect response.

    Unfortunately, the fetch API doesn’t provide a straightforward way to access the redirection target URL in the way you’d like due to the security model of most modern browsers. Here’s what you can try:

    Workaround using server-side handling

    The best solution in such cases is to handle this on the server side. When the session expires, instead of responding with a 302 Redirect, return a specific JSON response with a status indicating session expiration (for example, 401 Unauthorized or a custom status). You can then check this status in your client-side code and perform a manual redirect:

    On the server-side:

    {
        "error": "Session expired",
        "redirectUrl": "https://login.page"
    }
    

    On the client-side:

    fetch("url-that-forces-a-redirect", {
        method: "POST",
        body: formData
    })
    .then((response) => {
        if (!response.ok && response.status === 401) {
            return response.json().then(data => {
                if (data.error === "Session expired") {
                    window.location.href = data.redirectUrl;
                }
            });
        } else {
            return response.json().then(data => {
                // Handle the normal response
            });
        }
    });
    

    Alternative: Detect Session Expiration in fetch() Response

    If changing server behavior isn’t an option, another approach could be to return a custom error status code (e.g., 401 or 403) when the session expires instead of a 302 Redirect. Then your client-side JavaScript could detect the specific error response and redirect the user manually.

    Why XMLHttpRequest doesn’t work either

    XMLHttpRequest also follows redirects automatically and doesn’t expose any APIs to prevent this or retrieve the redirect URL without following it. The limitation lies in the browser security model for client-side JavaScript, which aims to prevent security issues like open redirects.

    Summary

    • fetch() and XMLHttpRequest do not allow you to retrieve the redirected URL after a 302 status easily due to browser security constraints.
    • You can handle this on the server by sending a custom status (e.g., 401) with a JSON response indicating a session expiration.
    • Manually redirect the user on the client side based on the server’s response.

    If you have control over the server code, this solution would provide a cleaner and more reliable way to handle session expirations in your application.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search