diff --git a/.changeset/spotty-cooks-trade.md b/.changeset/spotty-cooks-trade.md new file mode 100644 index 000000000..c74c17533 --- /dev/null +++ b/.changeset/spotty-cooks-trade.md @@ -0,0 +1,5 @@ +--- +"@solidjs/start": patch +--- + +delete expired cookies in Single-Flight requests diff --git a/packages/start/package.json b/packages/start/package.json index 095ba2e68..2cef2dc18 100644 --- a/packages/start/package.json +++ b/packages/start/package.json @@ -69,6 +69,7 @@ "@tanstack/server-functions-plugin": "1.121.21", "@vinxi/plugin-directives": "^0.5.0", "@vinxi/server-components": "^0.5.0", + "cookie-es": "^2.0.0", "defu": "^6.1.2", "error-stack-parser": "^2.1.4", "html-to-image": "^1.11.11", diff --git a/packages/start/src/runtime/server-handler.ts b/packages/start/src/runtime/server-handler.ts index 46e1603c5..74ded0de7 100644 --- a/packages/start/src/runtime/server-handler.ts +++ b/packages/start/src/runtime/server-handler.ts @@ -1,4 +1,5 @@ /// +import { parseSetCookie } from "cookie-es"; import { crossSerializeStream, fromJSON, getCrossReferenceHeader } from "seroval"; // @ts-ignore import { @@ -322,9 +323,16 @@ function createSingleFlightHeaders(sourceEvent: FetchEvent) { } SetCookies.forEach(cookie => { if (!cookie) return; - const keyValue = cookie.split(";")[0]!; - const [key, value] = keyValue.split("="); - key && value && (cookies[key] = value); + const { maxAge, expires, name, value } = parseSetCookie(cookie); + if (maxAge != null && maxAge <= 0) { + delete cookies[name]; + return; + } + if (expires != null && expires.getTime() <= Date.now()) { + delete cookies[name]; + return; + } + cookies[name] = value; }); Object.entries(cookies).forEach(([key, value]) => { headers.append("cookie", `${key}=${value}`); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fd417aa00..1e81ea679 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -99,6 +99,9 @@ importers: '@vinxi/server-components': specifier: ^0.5.0 version: 0.5.0(vinxi@0.5.7(@types/node@24.3.0)(better-sqlite3@11.8.1)(db0@0.3.2(better-sqlite3@11.8.1)(drizzle-orm@0.31.4(@opentelemetry/api@1.9.0)(@prisma/client@5.22.0(prisma@5.22.0))(@types/better-sqlite3@7.6.12)(better-sqlite3@11.8.1)(prisma@5.22.0)))(drizzle-orm@0.31.4(@opentelemetry/api@1.9.0)(@prisma/client@5.22.0(prisma@5.22.0))(@types/better-sqlite3@7.6.12)(better-sqlite3@11.8.1)(prisma@5.22.0))(ioredis@5.6.1)(jiti@2.4.2)(lightningcss@1.27.0)(terser@5.43.1)(tsx@4.19.2)(yaml@2.6.0)) + cookie-es: + specifier: ^2.0.0 + version: 2.0.0 defu: specifier: ^6.1.2 version: 6.1.4 @@ -8218,7 +8221,7 @@ snapshots: '@babel/preset-env': 7.26.0(@babel/core@7.26.9) babel-loader: 9.2.1(@babel/core@7.26.9)(webpack@5.97.1) bluebird: 3.7.1 - debug: 4.4.0 + debug: 4.4.1 lodash: 4.17.21 webpack: 5.97.1 transitivePeerDependencies: @@ -11810,7 +11813,7 @@ snapshots: istanbul-lib-instrument@4.0.3: dependencies: - '@babel/core': 7.26.9 + '@babel/core': 7.27.4 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 semver: 6.3.1 @@ -11834,7 +11837,7 @@ snapshots: istanbul-lib-source-maps@4.0.1: dependencies: - debug: 4.4.0 + debug: 4.4.1 istanbul-lib-coverage: 3.2.2 source-map: 0.6.1 transitivePeerDependencies: @@ -12145,7 +12148,7 @@ snapshots: make-dir@4.0.0: dependencies: - semver: 7.7.1 + semver: 7.7.2 math-intrinsics@1.1.0: {}