Undici strips out set-cookie headers, even when "credentials: 'include'" is set
See original GitHub issueBug Description
Undici strips out set-cookie
headers, which is expected per the fetch
API spec. What is not expected though is that the set-cookie
headers are stripped out in the presence of { credentials: 'include' }
in a fetch
request. Here is the relevant portion of the fetch
API spec:
https://fetch.spec.whatwg.org/#example-cors-with-credentials
Reproducible By
server.js
const express = require('express')
const app = express()
app.get('/', (req, res) => {
res.set({
abc: '123',
'set-cookie': 'hello=world',
});
res.send('Hello World!');
})
app.listen(3333, () => {
console.log(`Example app listening on port ${port}`)
})
client.js
const { fetch } = require('undici');
async function get() {
const headers = await fetch('http://localhost:3333/', { credentials: 'include' })
.then(async res => {
for await (const chunk of res.body) {}
return res.headers
});
console.log(`abc: ${headers.get('abc')}`);
console.log(`set-cookie: ${headers.get('set-cookie')}`);
}
get();
With the server script running, the client script returns:
abc: 123
set-cookie: null
Expected Behavior
In the presence of { credentials: 'include' }
I would expect set-cookie
headers to not be stripped from the response. The expected output of the client script should be:
abc: 123
set-cookie: hello=world
Environment
Mac OS 12.2.1 Node v16.13.1
Additional context
There is a TODO
in Undici’s fetch
code where this behavior should be implemented:
https://github.com/nodejs/undici/blob/main/lib/fetch/index.js#L1369-L1375
Issue Analytics
- State:
- Created 2 years ago
- Reactions:4
- Comments:16 (11 by maintainers)
Top Results From Across the Web
Set cookies for cross origin requests - Stack Overflow
I am setting request and response headers now like crazy now, making sure that they are present in both the request and the...
Read more >Fetch Standard
The ` Set-Cookie ` header is semantically a response header, so it is not useful on requests. Because ` Set-Cookie ` headers cannot...
Read more >draft-ietf-httpstate-cookie-10
This document may contain material from IETF Documents or IETF ... To store state, the origin server includes a Set-Cookie header in an...
Read more >axios samesite=none | The AI Search Engine You Control
The Set-cookie had to have been set with "Same Site=None" to enable ... I reached out to Stripe because I was getting this...
Read more >Cookies: HTTP State Management Mechanism
Although cookies have many historical infelicities that degrade their security and privacy, the Cookie and Set-Cookie header fields are ...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
#1454 was reverted following @ronag’s comment:
I don’t think there is a spec to follow here though. The spec (referring to 4.7.17.3 of the fetch standard, which leads us 5.2 of RFC 6265) is clearly written for browsers; it assumes that the user agent has a cookie store, which obviously makes no sense for a server that can handle requests from multiple users.
I gather from @KhafraDev that there’s a proposal to add
cookieStore
options toRequest
andResponse
constructors (though the comment doesn’t link to the proposal, just to the proposedCookieStore
spec?), and that could be a good solution one day. In the meantime though, being unable to read cookies from requests means that Undici is untenable for many real-world applications. (SvelteKit would like to use Node’s built-infetch
when applications are deployed as Node servers, but for the time being we’re reliant onnode-fetch
even with Node 18.)Other implementations have chosen differently. This URL returns a
set-cookie: hello=world
header — if wefetch
it with different implementations, this is what we see:headers.get('set-cookie')
hello=world
hello=world
hello=world
null
In the absence of a usable spec, I would argue that following the behaviour that a majority of implementations have agreed upon (and that users expect, as evidenced by the Miniflare issue among others) is the prudent course of action. (Even though
headers.get('set-cookie')
is problematic because it can smush together multiple headers, this is easily solved in userland with popular packages like set-cookie-parser.)I believe this is a bug that has nothing to do with cookie parsing (etc.) and #1454 presents a valid solution, just need to see what ronag thinks now. 😄