为了实现头部的灵活性,能够对头部进行修改是一个非常重要的能力。Headers 属于 HTTP首部的一份子,它是一个抽象的接口,利用它可以对 HTTP 的请求头和响应头做出添加、修改和删除的操作。

下面我们先看一下它具有哪些接口:

  1. typedef (sequence<sequence<ByteString>> or record<ByteString, ByteString>) HeadersInit;
  2. [Constructor(optional HeadersInit init),
  3. Exposed=(Window,Worker)]
  4. interface Headers {
  5. void append(ByteString name, ByteString value);
  6. void delete(ByteString name);
  7. ByteString? get(ByteString name);
  8. boolean has(ByteString name);
  9. void set(ByteString name, ByteString value);
  10. iterable<ByteString, ByteString>;
  11. };interface Headers {
  12. void append(ByteString name, ByteString value);
  13. void delete(ByteString name);
  14. ByteString? get(ByteString name);
  15. boolean has(ByteString name);
  16. void set(ByteString name, ByteString value);
  17. iterable<ByteString, ByteString>;
  18. };
  19. // 来自 https://fetch.spec.whatwg.org/#headers-class

规范中定义的接口我们可以对应着 MDN 进行查看,你可以点击这里更直观的看看看看它有哪些方法供我们使用。

这里我们对 Headers 的构造参数做个解释。首先参数类型为 HeadersInit,我们再看下这个类型支持哪些类型的值。我们从规范中可以看到的定义是:

  1. typedef (sequence<sequence<ByteString>> or record<ByteString, ByteString>) HeadersInit;

这里我们对应到 JavaScript 这门语言,意思就是说这个对象可以是数组或者是键值对(即对象)。关于如何初始化这些参数,我们可以看下规范中定义的流程

To fill a Headers object (headers) with a given object (object), run these steps:

  1. If object is a sequence, then for each header in object:

    1. If header does not contain exactly two items, then throw a TypeError.

    2. Append header’s first item/header’s second item to headers.

  2. Otherwise, object is a record, then for each key → value in object, append key/value to headers.

这里我需要对这个做个说明,后面对 fetch 的用法会涉及到一点以及我们看 polyfill 都会有所帮助。

  • 第一种:即数组,当数据每项如果不包含两项时,直接抛出错误。然后数组第一项是 header 名,第二项是值。,最后直接通过 append 方法添加。

  • 第二种:即键值对(这里指对象),我们通过循环直接取到键值对,然后通过 append 方法添加。

示例

示例代码地址:https://github.com/GoDotDotDot/fe9-fetch-demo/blob/master/views/headers.html#L17

打开浏览器输入:http://127.0.0.1:4000/headers

那么我们该如何使用它呢?首先我们需要通过 new Headers() 来实例化一个 Headers 对象,该对象返回的是一个空的列表。在有了对象实例后,我们就可以通过接口来完成我们想要的操作,我们来一起看看下面的示例:

  1. function printHeaders(headers) {
  2. let str = '';
  3. for (let header of headers.entries()) {
  4. str += `
  5. <li>${header[0]}: ${header[1]}</li>
  6. `;
  7. console.log(header[0] + ': ' + header[1]);
  8. }
  9. return `<ul>
  10. ${str}
  11. </ul>`;
  12. }
  13. const headers = new Headers();
  14. // 我们打印下看看是否返回的是一个空的列表
  15. const before = printHeaders(headers); // 发现这里没有任何输出
  16. document.getElementById('headers-before').innerHTML = before;
  17. // 我们添加一个请求头
  18. headers.append('Content-Type', 'text/plain');
  19. headers.append('Content-Type', 'text/html');
  20. headers.set('Content-Type', ['a', 'b']);
  21. const headers2 = new Headers({
  22. 'Content-Type': 'text/plain',
  23. 'X-Token': 'abcdefg',
  24. });
  25. const after = printHeaders(headers); // 输出:content-type:

如果你觉得每次都要 append 麻烦的话,你也可以通过在构造函数中传入指定的头部,例如:

  1. const headers2 = new Headers({
  2. 'Content-Type': 'text/plain',
  3. 'X-Token': 'abcdefg'
  4. });
  5. printHeaders(headers2);
  6. // 输出:
  7. // content-type: text/plain
  8. // x-token: abcdefg

这里我添加了一个自定义头部 X-Token,这在实际开发中很常见也很有实际意义。但是切记在 CORS 中需要满足相关规范,否则会产生跨域错误。

你可以通过appenddeletesetgethas 方法修改请求头。这里对 setappend 方法做个特殊的说明:

set: 如果对一个已经存在的头部进行操作的话,会将新值替换掉旧值,旧值将不会存在。如果头部不存在则直接添加这个新的头部。

append:如果已经存在该头部,则直接将新值追加到后面,还会保留旧值。

为了方便记忆,你只需要记住 set 会覆盖,而 append 会追加。

Guard

Guard 是 Headers 的一个特性,他是一个守卫者。它影响着一些方法(像 appendsetdelete)是否可以改变 header 头。

它可以有以下取值:immutablerequestrequest-no-corsresponsenone

这里你无需关心它,只是为你让你了解有这样个东西在影响着我们设置一些 Headers。你也无法去操作它,这是代理的事情。举个简单的例子,我们无法在 Response Headers 中插入一个 Set-Cookie

如果你想要了解更过的细节,具体的规范请参考 concept-headers-guardMDN Guard

注意