使用Fetch API读取响应标头


71

我在一个具有权限的Google Chrome扩展程序中,"*://*/*"并且试图将XMLHttpRequest切换到Fetch API

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

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进入这些其他字段吗?

Answers:


100

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

  • 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


22
@jules对CORS的此限制会尊重access-control-expose-headers-或可能access-control-allow-headers(我们将二者都放入)中的值。
jacob

14
access-control-expose-headers从服务器返回的标头对我有用-然后可以通过获取响应标头对象使用标头。并access-control-allow-headers用于允许服务器上的Request标头(或者我会从服务器收到错误消息)
标本

10
愚蠢的是,使用Fetch无法做到这一点,但是可以使用XmlHttpRequest完成。如果仍可以通过变通办法来实现,那么安全优势是什么?
sebas '18

2
@sebas看起来像Chrome(可能还有其他浏览器)对施加了相同的限制XmlHttpRequest
Benjineer '18

7
设置Access-Control-Allow-Headers允许头部从客户端传递到服务器(例如,当If-Match)。设置Access-Control-Expose-Headers允许头部传递从服务器返回给客户端(例如,当ETag)。
戴夫·史蒂文斯


13

MDN

您还可以通过访问条目Iterator获得所有标头。

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

另外,请记住这一部分:

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


2
使用迭代器呈现相同的输出;仅内容类型字段。并且禁止的标头名称列表似乎仅适用于修改,但WWW-Authenticate均未列出。
jules

9

为了与不支持ES2015迭代器的浏览器向后兼容(可能还需要获取/承诺polyfill),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()不起作用。


2

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

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

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


0

还请记住.then()res.headers.get()如果您解析了响应,则可能需要将其传递给next 。我一直忘了那个...

var link
const loop = () => {
  fetch(options)
    .then(res => { 
      link = res.headers.get('link')
      return res.json()
    })
    .then(body => {
      for (let e of body.stuff) console.log(e)
      if (link) setTimeout(loop, 100)
    })
    .catch(e => {
      throw Error(e)
    })
}
loop()
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.