响应标头不可用于带有“重定向:手动”的获取请求

问题描述 投票:0回答:2

我在做

        console.log("navigating");
        var rsp = await fetch(params.url, {
            credentials: "include", redirect: "manual", mode: "cors"
        });
        console.log(rsp);
        rsp.headers.forEach(console.log);

        console.log(rsp.headers.get('Location'));
        console.log(rsp.headers.get('location'));

以及来自 chrome 开发工具的响应标头:

Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://localhost:4400
Access-Control-Expose-Headers: Location
Cache-Control: no-cache
Connection: keep-alive
Content-Length: 0
Date: Fri, 05 Oct 2018 12:48:21 GMT
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Location: http://localhost/test

给予

Response 
body: (...)
bodyUsed: falseheaders: 
Headers {}
ok: false
redirected: false
status: 0
statusText: ""
type: "opaqueredirect"
url: "..."

index.ts:161 null
index.ts:162 null

是否无法在重定向响应中获取响应标头?

javascript fetch-api
2个回答
18
投票

是否无法在重定向响应中获取响应标头?

不,这是不可能的。 Fetch 规范中的要求阻止了它。

问题显示的是

manual
重定向模式的预期内容:暴露给前端JS的标头对象在响应
redirect: "manual"
请求时预计为空。

当请求设置

manual
重定向模式时,响应类型为
opaqueredirect
。有关其影响的信息位于 https://developer.mozilla.org/en-US/docs/Web/API/Response/type:

opaqueredirect
:使用
redirect: "manual"
发出获取请求。响应的状态为 0,headers 为空,body 为 null,trailer 为空。


MDN 文章中的这些详细信息直接基于 Fetch 规范的以下部分:

https://fetch.spec.whatwg.org/#concept-request-redirect-mode

请求具有关联的重定向模式,即

"follow"
"error"
"manual"

……
“手动”:当请求遇到重定向时检索不透明重定向过滤响应,以便可以手动遵循重定向。

https://fetch.spec.whatwg.org/#concept-filtered-response-opaque-redirect

opaque-redirect过滤响应是一个过滤响应,其类型为

"opaqueredirect"
,状态为
0
,状态消息为空字节序列,头列表为空,正文为空
……
不透明过滤响应和不透明重定向过滤响应与网络错误几乎无法区分


0
投票

这是一个老问题,但我认为答案可以扩展,并且可以帮助某人节省一些时间。

基本上值得指出的是,fetch() 在浏览器环境和 NodeJS 等后端环境中的行为不同(因为没有 CORS 机制)。

redirect: 'manual'

在浏览器中: 总会给你“opaqueredirect”,这是一个空的响应。因此,无论如何,都不可能在第一个 URL 处停止并从浏览器中的标头中获取重定向 URL。

在 NodeJS 中: 它将在重定向处停止,并会给您完整的响应。可以说,在后端,它的工作原理正如许多人所期望的那样。

因此,如果您正在开发一个完整的堆栈应用程序,并且只想从外部 API 获取重定向URL - 只需将负责它的代码移至您的后端即可。

我在 NodeJS 中的代码示例:

    fetch('https://api.example/php/search.php?X=78994&Y=158&date=20240509', {
    method: 'HEAD',
    redirect: 'manual'
})
  .then(response => {
    if (response.status >= 300 && response.status < 400) {
      console.log('Redirect status:', response.status);
      console.log('Redirect location:', response.headers.get('location'));
    } else {
      console.log('Response status:', response.status);
      console.log('Response did not redirect:', response);
    }
  })
  .catch(error => {
    console.error('Error during fetch:', error);
  });

日志:

Redirect status: 301
Redirect location: ./new_page.php?date=20240509&param1=324&param2=43242
© www.soinside.com 2019 - 2024. All rights reserved.