-
Notifications
You must be signed in to change notification settings - Fork 606
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: implement CookieStore
#1441
Conversation
how would this work in combination with fetch? |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1441 +/- ##
==========================================
+ Coverage 94.52% 94.82% +0.30%
==========================================
Files 49 54 +5
Lines 4271 4563 +292
==========================================
+ Hits 4037 4327 +290
- Misses 234 236 +2 ☔ View full report in Codecov by Sentry. |
Something along the lines of whatwg/fetch#1384 I think it has more 'substantial' use server-side though. import { createServer } from 'http'
const server = createServer(async (req, res) => {
const cookieStore = req.headers['set-cookie'] ? CookieStoreFrom(req.headers['set-cookie']) : null
if (cookieStore === null ) {
res.statusCode = 404
res.end('no cookies')
return
}
const sessionCookie = await cookieStore.get('sessionId')
if (sessionCookie && await matchesFromSomewhere(sessionCookie)) {
res.statusCode = 200
res.end('Welcome!')
return
}
// ...
}).listen(0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good work!
Could you add some test for fetch integration and docs? |
Fetch integration hasn't been done yet, I wasn't sure if it would be in scope for this PR. edit: and having a cookie store is not in the spec, but a proposal @jimmywarting made. I think I'll make an issue under the wintercg fetch repo and see how set-cookie should be handled. Actually, this seems to be done in wintercg/fetch#4 (or at least, could be solved by). A fetch implementation would be not combining |
I would restrain from adding this without further fetch() integration. |
That's fair, I'll convert it to a draft PR until there's more discussion with integrating into fetch or there's been more discussion about use cases or value this has in undici/node core. |
@KhafraDev I'm not sure if your example above would work with multiple cookies: const server = createServer(async (req, res) => {
// there might be multiple set-cookie headers, and req.headers['set-cookie'] currently does not properly return them
const cookieStore = req.headers['set-cookie'] ? CookieStoreFrom(req.headers['set-cookie']) : null
// instead what if `cookieStore` was just a property on the request?
const cookieStoreReq = req.cookieStore;
if (cookieStore === null ) {
res.statusCode = 404
res.end('no cookies')
return
}
const sessionCookie = await cookieStore.get('sessionId')
if (sessionCookie && await matchesFromSomewhere(sessionCookie)) {
res.statusCode = 200
res.end('Welcome!')
return
}
// ...
}).listen(0) |
What's weird is that you create a server and listen for incomming const server = createServer(async (req, res) => {
// there might be multiple set-cookie headers, and req.headers['set-cookie'] currently does not properly return them
const cookieStore = req.headers['set-cookie'] ? CookieStoreFrom(req.headers['set-cookie']) : null when clients makes request to a server then you are only sending cookies. // instead what if `cookieStore` was just a property on the request?
const cookieStoreReq = req.cookieStore; i like that, and it was what i proposed in my original feature request. it would always exist on the request (even if no cookie are being sent) it should only populate the newly created cookiestore with new values. so you don't even have to check if you would only have to do: const sessionCookie = await req.cookieStore.get('sessionId')
if (!sessionCookie) return res.end('not logged in') |
@blittle with this minimal example, all cookies are received: import { once } from 'events'
import { createServer } from 'http'
import { request } from 'undici'
const server = createServer((req, res) => {
console.log(req.headers['set-cookie'])
// [ 'a=b; Domain=example.com', 'c=d; Path=/account/' ]
res.end('goodbye')
}).listen(0)
await once(server, 'listening')
await request(`http://localhost:${server.address().port}`, {
headers: {
'set-cookie': 'a=b; Domain=example.com',
'SEt-CoOkIe': 'c=d; Path=/account/'
}
}) |
@KhafraDev oh yes, you are right. It's the node request object, not undici's |
Closes nodejs/node#42183
Implements:
CookieStore
*CookieChangeEvent
CookieStore
with 1 or moreset-cookie
headers while remaining spec compliant.set-cookie
header parsing *** I follow Chrome's behavior where it mismatches from the spec. This can be seen when setting & getting a cookie name with bom characters in it. Chrome ignores these (?), so likewise the behavior is the same here.
** Without header parsing,
CookieStore
is entirely useless in node. With it, I can see it getting used a fair bit for parsing cookies server-side.I haven't exposed it yet
and it needs more tests, but nyc wasn't giving me good coverage reports anymore.CookieStoreFrom
also needs a way to set a hostname to check for valid/invalid cookies (would solve the issue of node not having an origin).Things that need to be discussed: