为了实现头部的灵活性,能够对头部进行修改是一个非常重要的能力。Headers 属于 HTTP 中首部的一份子,它是一个抽象的接口,利用它可以对 HTTP 的请求头和响应头做出添加、修改和删除的操作。
下面我们先看一下它具有哪些接口:
typedef (sequence<sequence<ByteString>> or record<ByteString, ByteString>) HeadersInit;
[Constructor(optional HeadersInit init),
Exposed=(Window,Worker)]
interface Headers {
void append(ByteString name, ByteString value);
void delete(ByteString name);
ByteString? get(ByteString name);
boolean has(ByteString name);
void set(ByteString name, ByteString value);
iterable<ByteString, ByteString>;
};interface Headers {
void append(ByteString name, ByteString value);
void delete(ByteString name);
ByteString? get(ByteString name);
boolean has(ByteString name);
void set(ByteString name, ByteString value);
iterable<ByteString, ByteString>;
};
// 来自 https://fetch.spec.whatwg.org/#headers-class
规范中定义的接口我们可以对应着 MDN 进行查看,你可以点击这里更直观的看看看看它有哪些方法供我们使用。
这里我们对 Headers
的构造参数做个解释。首先参数类型为 HeadersInit
,我们再看下这个类型支持哪些类型的值。我们从规范中可以看到的定义是:
typedef (sequence<sequence<ByteString>> or record<ByteString, ByteString>) HeadersInit;
这里我们对应到 JavaScript
这门语言,意思就是说这个对象可以是数组或者是键值对(即对象)。关于如何初始化这些参数,我们可以看下规范中定义的流程。
To fill a
Headers
object (headers) with a given object (object), run these steps:
这里我需要对这个做个说明,后面对 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 对象,该对象返回的是一个空的列表。在有了对象实例后,我们就可以通过接口来完成我们想要的操作,我们来一起看看下面的示例:
function printHeaders(headers) {
let str = '';
for (let header of headers.entries()) {
str += `
<li>${header[0]}: ${header[1]}</li>
`;
console.log(header[0] + ': ' + header[1]);
}
return `<ul>
${str}
</ul>`;
}
const headers = new Headers();
// 我们打印下看看是否返回的是一个空的列表
const before = printHeaders(headers); // 发现这里没有任何输出
document.getElementById('headers-before').innerHTML = before;
// 我们添加一个请求头
headers.append('Content-Type', 'text/plain');
headers.append('Content-Type', 'text/html');
headers.set('Content-Type', ['a', 'b']);
const headers2 = new Headers({
'Content-Type': 'text/plain',
'X-Token': 'abcdefg',
});
const after = printHeaders(headers); // 输出:content-type:
如果你觉得每次都要 append
麻烦的话,你也可以通过在构造函数中传入指定的头部,例如:
const headers2 = new Headers({
'Content-Type': 'text/plain',
'X-Token': 'abcdefg'
});
printHeaders(headers2);
// 输出:
// content-type: text/plain
// x-token: abcdefg
这里我添加了一个自定义头部 X-Token
,这在实际开发中很常见也很有实际意义。但是切记在 CORS 中需要满足相关规范,否则会产生跨域错误。
你可以通过append
、 delete
、set
、get
和has
方法修改请求头。这里对 set
和 append
方法做个特殊的说明:
set
: 如果对一个已经存在的头部进行操作的话,会将新值替换掉旧值,旧值将不会存在。如果头部不存在则直接添加这个新的头部。
append
:如果已经存在该头部,则直接将新值追加到后面,还会保留旧值。
为了方便记忆,你只需要记住 set
会覆盖,而 append
会追加。
Guard
Guard 是 Headers 的一个特性,他是一个守卫者。它影响着一些方法(像 append
、 set
、delete
)是否可以改变 header 头。
它可以有以下取值:immutable
、request
、request-no-cors
、response
或 none
。
这里你无需关心它,只是为你让你了解有这样个东西在影响着我们设置一些 Headers。你也无法去操作它,这是代理的事情。举个简单的例子,我们无法在 Response Headers 中插入一个 Set-Cookie
。
如果你想要了解更过的细节,具体的规范请参考 concept-headers-guard 和 MDN Guard
注意
- 我们在给头部赋值的时候需要满足可接受的首部字段集合否则将会报
TypeError
。