redirect: "manual" in fetch redirects to the request URL instead of redirecting to header location in response
Asked Answered
S

1

1

I have the below code which am using to get the response header location.

 let callAuthorize = async() => {
        try {
        const authorizeResponse = await fetch(requesturl,
{redirect: "manual", mode:'cors',
        headers: {
          "Cache-Control": "no-store",
          "Accept-Charset": "UTF-8",
          "Access-Control-Expose-Headers": "location"
        }
      });
      if (authorizeResponse.type === "opaqueredirect") {
          window.location.href = authorizeResponse.url;
      }
      }
      catch (e) {
        console.log(e)
      } 

but it redirects to the requesturl instead of redirecting to header location in response.

with normal fetch call am unable to grab the response header, because of CORS issue.

Shoa answered 6/6, 2023 at 8:26 Comment(0)
M
0

You can't read the redirect location directly. As a workaround, you can navigate the browser to the opaqueredirect response, if you store it in a cache and use a service worker to replay the response. See an example below with one same-origin redirect followed by two cross-origin redirects.

index.html:

<!DOCTYPE html>
<html lang="en">
  <head><title>Navigate to opaqueredirect</title></head>
  <body>
    <button id=button disabled>Navigate to opaqueredirect</button>
  </body>
  <script>
    navigator.serviceWorker.register('sw.js');
    navigator.serviceWorker.ready.then(() => {
        button.disabled = false;
        button.onclick = () => {
            fetch('/redirect1', { redirect: 'manual' }).then(
                (response) => {
                    if (response.type === 'opaqueredirect') {
                        const urlToCache = new URL(response.url);
                        const uuid = crypto.randomUUID();
                        urlToCache.searchParams.set('cacheId', uuid);
                        const requestToCache = new Request(urlToCache);
                        caches.open('cacheId').then((cache) => {
                            cache.put(requestToCache, response).then(() => {
                                window.location.assign(urlToCache);
                            }).catch(console.error);
                        }).catch(console.error);
                    }
                },
            ).catch(console.error);
        };
    });
  </script>
</html>

serve.json:

{
  "redirects": [
      {
          "source": "/redirect1",
          "destination": "/redirect2",
          "type": 302
      },
      {
          "source": "/redirect2",
          "destination": "https://mock.httpstatus.io/307",
          "type": 302
      }
  ]
}

sw.js:

self.addEventListener('fetch', (event) => {
  if (new URL(event.request.url).searchParams.get('cacheId')) {
    event.respondWith(caches.open('cacheId').then(async (cache) => {
      const cacheMatch = await cache.match(event.request);
      if (cacheMatch) {
        cache.delete(event.request).then(() => { }).catch(console.error);
        return cacheMatch;
      }
      return fetch(event.request);
    }));
  }
});

Run npx -y serve in a directory containing the above files, then open localhost:3000 in your browser. Then click the button and the redirect will be followed to https://mock.httpstatus.io/200.

Monecious answered 20/3 at 10:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.