[engine.io-client] The Node.js cookie jar lets Expires override Max-Age
维护者通常 2 天内回复
还没有人认领这个 Issue。
评估
- 难度
- 2/5
- 预计耗时
- 1-3 小时
- 新手友好度
- 88/100
- Issue 类型
- 缺陷
- 描述清晰度
- 描述清楚
- 活跃度
- 活跃
- 技术栈
- node.js, typescript
- 领域
- backend, networking
调研方向
从 packages/engine.io-client/lib/globals.node.ts 中的 parse() 和 packages/engine.io-client/test/node.js 中的 “should parse a complex set-cookie header” 测试开始。检查 Expires 和 Max-Age 同时出现时的处理方式,然后更新测试,覆盖两种头部属性顺序及预期的优先级。当 Max-Age 无论属性顺序如何都决定 cookie 的过期时间,且现有解析测试通过时,任务即完成。
由索引模型根据 Issue 内容生成。
描述
Describe the bug
With withCredentials: true in Node.js, the cookie jar of engine.io-client applies the Expires and Max-Age attributes in the order they appear in the Set-Cookie header, so whichever comes last wins. According to RFC 6265 (section 5.3, step 3) and MDN, Max-Age takes precedence over Expires when both are present.
Two consequences:
- A cookie like
sid=abc; Max-Age=3600; Path=/; Expires=<date>(which is what Express sends forres.cookie("sid", "abc", { maxAge: 3600000 })) is dropped right away when the client clock is ahead of the server clock by more than the max age, because theExpiresdate is already in the past for the client. WithMax-Agetaking precedence, the cookie would be kept for one hour. - A deletion like
sid=abc; Max-Age=0; Expires=<future date>is ignored, and the cookie keeps being sent.
The existing test "should parse a complex set-cookie header" in packages/engine.io-client/test/node.js also expects the Expires date for a header that carries Max-Age=1000 before Expires.
To Reproduce
Engine.IO server version: 6.6.11
Engine.IO client version: 6.6.8 (also reproduced on main at e94e021)
Server and client
const { createServer } = require("http");
const { attach } = require("engine.io");
const { Socket } = require("engine.io-client");
const setCookie = process.argv[2];
const httpServer = createServer();
const engine = attach(httpServer);
httpServer.prependListener("request", (req) => {
if (req.url.includes("sid=")) {
console.log("cookie header on a later request:", req.headers.cookie);
}
});
engine.on("initial_headers", (headers) => {
headers["set-cookie"] = [setCookie];
});
httpServer.listen(3000, () => {
const socket = new Socket("http://localhost:3000", {
transports: ["polling"],
withCredentials: true,
});
socket.on("open", () => {
setTimeout(() => {
socket.close();
engine.close();
httpServer.close();
}, 200);
});
});
Results:
Set-Cookie sent with the handshake |
cookie header on the next request |
|---|---|
sid=abc; Max-Age=3600; Path=/ |
sid=abc |
sid=abc; Max-Age=3600; Path=/; Expires=<one minute ago> |
none |
sid=abc; Max-Age=0; Path=/; Expires=Fri, 01 Jan 2100 00:00:00 GMT |
sid=abc |
Expected behavior
When a Set-Cookie header has both attributes, the expiry comes from Max-Age, whatever their order: the second cookie is kept for one hour and the third one is removed.
Platform:
- Device: desktop
- OS: Windows, Node.js 24.22.1 (the cookie jar is only used in Node.js)
Additional context
The parsing happens in parse() in packages/engine.io-client/lib/globals.node.ts. I'm happy to send a PR with a test.
AI-assisted: found and reproduced with an AI coding agent; the example above was run locally.
- 主要语言
- TypeScript
- 星标
- 63.2k
- 派生
- 10.2k
- 平均合并
- 6 天 4 小时
- 30 天内合并 PR
- 6
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
socketio/socket.io 的其他 Issue
-
Raise Engine.IO minimum to 6.6.10 for published security fixes可能已有人在做 @harshit-exe-dev 于 27 天前认领。 未关闭
难度 1/5 1-3 小时 新手友好度 78/100
维护者通常 2 天内回复
-
Can't set response headers in Server.handleUpgrade可能已有人在做 @MsfPablo 于 89 天前认领。 未关闭question
难度 2/5 1-3 小时 新手友好度 72/100
socketio/socket.io#5497 · 2 条评论 ·
维护者通常 2 天内回复
-
WebTransport ignores query parameters in URL可能已有人在做 @cyphercodes 于 177 天前认领。 未关闭needs major release question
难度 2/5 1-3 小时 新手友好度 68/100
socketio/socket.io#5496 · 3 条评论 ·
维护者通常 2 天内回复
-
cleanupEmptyChildNamespaces releases a child namespace while a socket is in its middleware, and the cleanup unregisters a newer namespace by name可能已有人在做 @Jeremiah-D 于 5 天前认领。 未关闭
难度 3/5 1-2 天 新手友好度 54/100
维护者通常 2 天内回复
-
enhancement
难度 5/5 一周以上 新手友好度 20/100
维护者通常 2 天内回复
查看 socketio/socket.io 的全部 Issue
相似的 Issue
-
Bug: Cloudflare Pages static _redirects identity rule causes RSC Flight to reload as HTML可能已有人在做 @Donvero 今天认领。 未关闭
难度 2/5 1-3 小时 新手友好度 78/100
Mantitup-Org/vista#210 ·
-
难度 2/5 1-3 小时 新手友好度 78/100
simstudioai/sim#9831 ·
维护者通常 1 天内回复
-
status: waiting for maintainer
难度 2/5 1-3 小时 新手友好度 88/100
mui/material-ui#49751 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 76/100
diplodoc-platform/transform#1184 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 78/100
JonasKruckenberg/imagetools#973 ·
维护者通常 1 天内回复