undici icon indicating copy to clipboard operation
undici copied to clipboard

Set-Cookie header gets concatenated in fetch if an interceptor is in place

Open hexchain opened this issue 5 months ago • 5 comments

Bug Description

If the dispatcher contains an interceptor, even a dummy one, the Set-Cookie headers will be concatenated together.

Reproducible By

const http = require('node:http')
const {Agent} = require('undici');

const dispatcher = new Agent().compose((dispatch) => dispatch)

const server = http.createServer((req, res) => {
    res.writeHead(200, [['set-cookie', 'a=1'], ['set-cookie', 'b=2'], ['set-cookie', 'c=3']])
    res.end("ok")
})
server.listen({port: 3002}, () => {
    Promise.all([fetch('http://localhost:3002'), fetch('http://localhost:3002', {dispatcher})])
        .then(([r1, r2]) => {
            console.log(r1.headers.getSetCookie())
            console.log(r2.headers.getSetCookie())
        })
        .then(() => server.close())
});

The output will be:

[ 'a=1', 'b=2', 'c=3' ]
[ 'a=1,b=2,c=3' ]

Expected Behavior

The two outputs should be identical.

Environment

Nodejs 24.4.1 Undici 7.13.0

hexchain avatar Aug 06 '25 09:08 hexchain

I took a stab at this by changing WrapHandler. Another possible fix is to modify httpNetworkFetch->dispatch->onHeaders instead. Please let me know if that is preferred.

hexchain avatar Aug 06 '25 10:08 hexchain

The concatenation is something that only seems to happen on fetch, attempting the same with undici#request does lead to the expected result of an array instead of a concatenated string.

Don't believe we should change something but open to chat about it.

cc: @KhafraDev

Note, there is a slight variance between using a composed dispatcher and a non-composed one in the resulted string, but they are essentially the same

metcoder95 avatar Oct 19 '25 11:10 metcoder95

If receiving an array is expected, #4390 is fine. If it isn't, I think it'd be more beneficial to align the dispatcher header behavior (in general, since it seems like a recurring issue).

KhafraDev avatar Oct 19 '25 14:10 KhafraDev

I'd say we could align to always expect an array when it comes to multiple-value headers, pairing a bit with what's the expectation of node:http#request.

metcoder95 avatar Oct 20 '25 06:10 metcoder95

Arrays are fine for "parsed" headers of type Record<string, string | string[]>, but maybe not for "raw" header. This issue happens because an array appeared in a "raw" header, e.g.:

[key: Buffer, value: Buffer, ...] -> [key: Buffer, value: Buffer[], ...]

This is also not valid according to the type of onHeaders, which expects a Array<Buffer>, not Array<Buffer | Buffer[]>.

hexchain avatar Oct 20 '25 07:10 hexchain