Repository: nodejs/undici

Issue #1262: Undici strips out set-cookie headers, even when "credentials: 'include'" is set
Created: 2022-03-04T01:19:47Z
Bug 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

Duplicate issue #1262: Undici strips out set-cookie headers, even when "credentials: 'include'" is set
Created: 2022-03-04T01:19:47Z
Bug 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

Closing comment (2022-05-19T17:53:16Z): I'm ok with following cloudflare and deno. But if we land this change I would like that:

A WinterCG issue.
It's clear in the code that all related logic is outside of spec and a reference motivating it. Possibly an issue in the WinterCG repo?
Clearly added to the README.
Investigate what exactly deno, node-fetch and cloudflare does so that we don't introduce another variant with slight differences.

I think a clear motivation is what was primarly missing from the PR. Similar to #1262 (comment).