使用 Fetch API 读取响应标头

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

我在具有

"*://*/*"
权限的 Google Chrome 扩展程序中,我正在尝试从 XMLHttpRequest 切换到 Fetch API

扩展存储用户输入的登录数据,以前直接放入 XHR 的 open() 调用中进行 HTTP Auth,但在 Fetch 下不能再直接用作参数。对于 HTTP Basic Auth,规避此限制是微不足道的,因为您可以手动设置授权标头:

fetch(url, {
  headers: new Headers({ 'Authorization': 'Basic ' + btoa(login + ':' + pass) })
  } });

HTTP Digest Auth 但是需要更多的交互性;您需要阅读服务器通过其 401 响应发送给您的参数,以制作有效的授权令牌。我尝试使用此代码段阅读

WWW-Authenticate
响应标头字段:

fetch(url).then(function(resp) {
  resp.headers.forEach(function(val, key) { console.log(key + ' -> ' + val); });
})

但我得到的只是这个输出:

content-type -> text/html; charset=iso-8859-1

这本身是正确的,但根据 Chrome 的开发者工具,这仍然缺少大约 6 个字段。如果我使用

resp.headers.get("WWW-Authenticate")
(或与此相关的任何其他字段),我只会得到
null
.

是否有机会使用 Fetch API 访问其他字段?

javascript google-chrome-extension
9个回答
158
投票

当您使用 Fetch API over CORS 时,访问响应标头有限制。由于此限制,您只能访问以下标准标头:

  • Cache-Control
  • Content-Language
  • Content-Type
  • Expires
  • Last-Modified
  • Pragma

当您为 Google Chrome 扩展程序编写代码时,您正在使用 CORS,因此您无法访问所有标头。如果你控制服务器,你可以在响应中返回自定义信息

body
而不是
headers

有关此限制的更多信息 - https://developers.google.com/web/updates/2015/03/introduction-to-fetch#response_types


82
投票

如果不是CORS:

Fetch 在调试时不显示标题,或者如果您

console.log(response.headers)
.

您必须使用以下方式访问标题。

fetch(url).then(resp=>{
    console.log(resp.headers.get('x-auth-token'));
})

// or
fetch(url).then(resp=>{
    console.log(...resp.headers);
})


33
投票

问题:

你可能认为这是一个前端问题。
这是一个后端问题。
浏览器将不允许公开 Authorization 标头,除非 Backend 告诉浏览器显式公开它。

如何解决:

这对我有用。
在后端(API)中,将其添加到响应标头中:

response.headers.add("Access-Control-Expose-Headers","Authorization")

为什么?

安全。
防止 XSS 攻击。
这个请求应该是从后端到后端。
后端将设置 httpOnly cookie 给前端。
因此,您网站上的任何第三方 JS 包都不应访问授权标头。
如果您认为让前端可以访问标头是安全的,那就去做吧。
但我建议服务器后端设置的HttpOnly Cookies 立即到您的浏览器。

参考:

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers


31
投票

来自MDN

您还可以通过访问条目 Iterator 来获取所有标题。

// Display the key/value pairs
for (var pair of res.headers.entries()) {
   console.log(pair[0]+ ': '+ pair[1]);
}

此外,请记住部分:

出于安全原因,某些标头只能由用户代理控制。这些标头包括禁止的标头名称和禁止的响应标头名称。


17
投票

为了与不支持 ES2015 迭代器(并且可能还需要 fetch/Promise polyfills)的浏览器向后兼容,Headers.forEach 函数是最好的选择:

r.headers.forEach(function(value, name) {
    console.log(name + ": " + value);
});

在 IE11 中使用 Bluebird 作为 Promise polyfill 和 whatwg-fetch 作为 fetch polyfill 进行了测试。 Headers.entries()、Headers.keys() 和 Headers.values() 不起作用。


7
投票

为了解决这个限制问题,添加公开的标头名称就足够了。

access-control-expose-headers: headername1, headername2, ...

设置此标头后,客户端脚本能够从响应中读取这些标头(headername1,headername2,...)。


1
投票

响应跨源请求,将

'Access-Control-Expose-Headers': '*'
添加到您的响应标头,以便所有标头都可以在您的客户端代码中读取。您还可以通过指定标头名称而不是通配符来指示要公开哪些标头。

请注意,根据 MDN 如果您访问的 URL 具有“凭据”,则“*”通配符将被视为文字。


-1
投票

如果您在 Program.cs 文件或 Startup.cs 中使用 .net,具体取决于 .net 版本,您必须执行以下操作:

builder.Services.AddCors(options =>
{
    options.AddPolicy(MyAllowSpecificOrigins,
    builder =>
    {
        builder
            .SetIsOriginAllowed(p => true)
            .WithOrigins("http://localhost:3000", "http://*:3000")
            .AllowCredentials()
            .WithExposedHeaders("X-Pagination") /*custom header*/
            .AllowAnyHeader()
            .AllowAnyMethod();
    });
});

}


-1
投票

我将从上面编译我的解决方案:

对于获取标题使用:

response.headers.get('ex-token')

为了让它工作,我们必须在后端 api exposeHeader('ex-token') 上设置`

有了 Java Spring 就变成了这样:

        configuration.addExposedHeader("ex-token");
© www.soinside.com 2019 - 2024. All rights reserved.