← 中文资源

简体中文版本

Cookie 请求头解析

把 Cookie 请求头解析为无原型对象,处理引号值、重复名称与 RFC 6265 的忽略规则。

阅读英文原文

功能说明

parseCookieHeader 把浏览器发送的 Cookie 头解析为键值对象,适用于服务端读取会话标识、偏好设置和实验分组。实现遵循 RFC 6265 的常见约定:按分号切分、忽略没有等号的片段、跳过以美元符号开头的旧式属性、同名 Cookie 保留最先出现的值。返回无原型对象,避免 proto 等键污染原型链。

关键代码

每个片段以第一个等号分隔名称与值,名称和值都会去除首尾空白。若值被双引号包裹则去掉引号,并还原反斜杠转义的引号与反斜杠。重复名称只在对象中不存在时写入,因此先出现的值优先。序列化辅助函数为值加上引号并转义内部引号,便于写入 Set-Cookie 的值部分。空头或非字符串输入返回空对象。

使用注意

Cookie 值可能包含编码后的内容,本函数不做百分号解码,避免把加号误当空格。不要直接把解析结果合并进普通对象或配置,以免原型污染;本实现使用 Object.create(null),但调用方仍应校验键名。请求头可能被伪造,Cookie 只能作为会话线索,不能当作可信身份。解析器不处理 Set-Cookie 的属性,也不验证签名。

验证方式

测试 a=1; b=2、带空格、带等号的值、空值、无等号片段与结尾分号。验证重复名称保留首个值,$Version 等属性被忽略。构造带引号与反斜杠的值,确认去引号与反转义正确。再测试空字符串、非字符串输入、proto 键不会污染 Object.prototype,并检查序列化函数对引号和反斜杠的转义。

代码示例

export function parseCookieHeader(header) {
  const cookies = Object.create(null);
  if (typeof header !== "string" || header.length === 0) return cookies;
  for (const part of header.split(";")) {
    const separator = part.indexOf("=");
    if (separator < 0) continue;
    const name = part.slice(0, separator).trim();
    if (!name || name.startsWith("$")) continue;
    let value = part.slice(separator + 1).trim();
    if (value.length >= 2 && value.startsWith('"') && value.endsWith('"')) {
      value = value.slice(1, -1).replace(/\\(["\\])/g, "$1");
    }
    if (!(name in cookies)) cookies[name] = value;
  }
  return cookies;
}

export function serializeCookieValue(value) {
  return '"' + String(value).replace(/["\\]/g, "\\$&") + '"';
}