node 中的 HTTP 模块会将所有的报文字段解析到 req.headers 上,那么 Cookie 就是 req.headers.cookie 。根据规范中的定义,Cookie 值的格式是 key=value; key2=value2 形式的,如果我们需要 Cookie,解析它也十分容易,如下所示:
- let parseCookie = (cookie) => {
- let cookies = {};
- if (!cookie) {
- return cookies;
- }
- let list = cookie.split(';');
- for (let i = 0; i < list.length; i++) {
- let pair = list[i].split('=');
- cookies[pair[0].trim()] = pair[1];
- }
- return cookies;
- };
-
- function handle (req, res) {
- req.cookies = parseCookie(req.headers.cookie);
- // 处理请求
- }
响应的 Cookie 值在 Set-Cookie 字段中。它的格式与请求中的格式不太相同,规范中对它的定义如下所示:
- Set-Cookie: name=value; Path=/; Expires=Sun, 23-Apr-23 09:01:35 GMT; Domain=.domain.com;
-
其中 name=value 是必须包含的部分,其余部分皆是可选参数。这些可选参数将会影响浏览器在后续将 Cookie 发送给服务器端的行为。以下为主要的几个选项。
知道 Cookie 在报文头中的具体格式后,下面我们将 Cookie 序列化成符合规范的字符串,相关代码如下:
- let serialize = function (name, val, opt) {
- let pairs = [`${name}=${val}`];
- opt = opt || {};
- if (opt.maxAge) pairs.push('Max-Age = ' + opt.maxAge);
- if (opt.domain) pairs.push('Domain=' + opt.domain);
- if (opt.path) pairs.push('Path=' + opt.path);
- if (opt.expires) pairs.push('Expires=' + opt.expires.toUTCString());
- if (opt.httpOnly) pairs.push('HttpOnly');
- if (opt.secure) pairs.push('Secure');
- return pairs.join('; ');
- };
客户端收到这个带 Set-Cookie 的响应后,在之后的请求时会在 Cookie 字段中带上这个值。
值得注意的是, Set-Cookie 是较少的,在报头中可能存在多个字段。为此 res.setHeader 的第二个参数可以是一个数组,如下所示:
- res.setHeader('Set-Cookie', [serialize('foo', 'bar'), serialize('baz')])
-
Cookie 的性能影响