Skip to content
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

cookie no longer able to be set in the Headers API as of v5.2.0 #1463

Closed
erunion opened this issue May 20, 2022 · 12 comments · Fixed by #1469
Closed

cookie no longer able to be set in the Headers API as of v5.2.0 #1463

erunion opened this issue May 20, 2022 · 12 comments · Fixed by #1469
Labels
enhancement New feature or request fetch

Comments

@erunion
Copy link

erunion commented May 20, 2022

Bug Description

Upgrading Node from 18.1 to 18.2 we are no longer able to set the cookie header in the Headers API.

Seems this is a result of #1337

Reproducible By

const headers = new Headers();
headers.append('cookie', 'bar=baz; foo=bar');

fetch('https://httpbin.org/cookies', {
  headers,
})
  .then(res => res.json())
  .then(console.log);

Running the above code on Node 18.1:

{ cookies: { bar: 'baz', foo: 'bar' } }

On Node 18.2 (and undidi 5.2):

{ cookies: {} }

Curiously if I don't use the Headers API and set the cookie header directly it works:

fetch('https://httpbin.org/cookies', {
  headers: {
    cookie: 'bar=baz; foo=bar',
  },
})
  .then(res => res.json())
  .then(console.log);

// { cookies: { bar: 'baz', foo: 'bar' } }

Expected Behavior

Would expect to be able to still set the cookie header because we can't use document.cookie like you can use in browser environments.

Environment

  • OSX 11.6
  • Node 18.1 and Node 18.2 using nvm
@erunion erunion added the bug Something isn't working label May 20, 2022
@KhafraDev
Copy link
Member

This is expected - undici follows the fetch spec and not how other platforms behave. The fetch spec tells implementations to filter out set-cookie and set-cookie2 headers, so that's what occurs.

@erunion
Copy link
Author

erunion commented May 20, 2022

Ok and looks like undici doesn't support includeCredentials right now so it's unfortunate that this code of mine is broken until that's added.

@KhafraDev
Copy link
Member

That section of the code deals with setting cookies in a per-origin browser cookie jar, not getting/setting/sending set-cookie headers. See #1262

@KhafraDev KhafraDev added enhancement New feature or request fetch and removed bug Something isn't working labels May 21, 2022
@aeharding
Copy link

Hello! I'm confused. I was using nodejs v18.0 fetch and I could get the Set-Cookie header just fine.

However now I cannot when I upgraded to nodejs v18.2. I see it when doing a console.log() of response.headers, but response.headers.get('set-cookie') doesn't work.

I understand that that's the fetch API standard, but that standards seems like it was designed for a browser, and not Node.

(BTW, my use case is proxying a CouchDB POST to _session.)

So I guess the fetch API is simply not compatible with my use case and I must use a third party library?

@KhafraDev
Copy link
Member

KhafraDev commented May 23, 2022

I understand that that's the fetch API standard, but that standards seems like it was designed for a browser, and not Node

Yes, you are entirely correct. The fetch spec was developed with browsers in mind - not so much a server environment. This causes a few problems with deciding how features should behave when the spec is subpar for a node.js use-case. Some decisions were made to branch away from the spec, however, those decisions were made before the creation of the WinterCG so now it has been decided to wait for a cross-platform solution/"spec", rather than introducing our own.

See: #1262 (comment) Re-reading it, if you put in the work, it seems as though a PR will be accepted. Unsure of that though, you can always make a PR for yourself, or wait for me to do it 😛.

So I guess the fetch API is simply not compatible with my use case and I must use a third party library?

Until a decision is made, unfortunately you will. I checked undici.request, but that also does not accept sending set-cookie headers. 😦

@aeharding
Copy link

Thanks for the quick response! That sounds good.

In case anyone else is reading and has the same issue, node-fetch allows accessing the Set-Cookie header on the response. A workaround with a similar API in the meantime. :)

https://www.npmjs.com/package/node-fetch

@mcollina
Copy link
Member

mcollina commented May 23, 2022

I checked undici.request, but that also does not accept sending set-cookie headers.

Could you open a fresh issue? That should definitely be possible. BTW, I think set-cookie is received, not sent.

@KhafraDev
Copy link
Member

You can actually send set-cookie headers with undici.request - the example was wrong in the original post.

import { request } from 'undici'
import { createServer } from 'http';
import { once } from 'events';

const server = createServer((req, res) => {
  console.log(req.headers['set-cookie'])
  res.end('goodbye')
}).listen(0)

await once(server, 'listening')

await request(`http:https://localhost:${server.address().port}`, {
  headers: {
    'set-cookie': 'bar=baz; foo=bar'
  }
})

server.close()

Outputs:

[ 'bar=baz; foo=bar' ]

@aeharding if you don't mind switching from fetch, undici.request has a great api with less restrictions.

@wmertens
Copy link

I'm seeing something related in 5.2.0 and 5.3.0 - I was using Headers to pass the headers, and with older versions that allowed me to authenticate but it broke other things.

I upgraded to 5.2 and I could no longer authenticate. However, when I change the headers to a plain object with Object.fromEntries(headers.entries()), it works.

So there is still an issue with Headers and cookies, somehow.

@issuefiler
Copy link

@erunion: Ok and looks like undici doesn't support includeCredentials right now so it's unfortunate that this code of mine is broken until that's added.

@KhafraDev: That section of the code deals with setting cookies in a per-origin browser cookie jar, not getting/setting/sending set-cookie headers. See #1262


Okay, hold on.

Do you understand what set-cookie is? If you don’t, this is my excerpt from MDN for you:

The Set-Cookie HTTP response header is used to send a cookie from the server to the user agent, so that the user agent can send it back to the server later.

How would you set cookies according to the set-header if you’re unable to read it? The browser does it automatically; does Node.js do it?


In the first place, what’s the point of bringing unnecessary constraints to this? What’s the point of being so obsessed with all the security features that are only meaningful to web browsers? “Because the spec says so?” The specification is intended for browsers. And what is this, a headless browser? It is not feasible at all to imitate what the browser does on Node.js to begin with.

Look, this is globalThis.fetch on Node.js. Stop saying “We just do what the spec says, problem?” and stop promoting third-party package, Undici, that does the same thing as fetch. Why are you guys making the first-ever dependency-less built-in Promise-based requestor function of Node.js so pointless? If I need to use other packages on NPM to make requests, then what is the point of globalThis.fetch?

Node.js’ fetch still can be compatible with the browser’s, without those unnecessary constraints for browsers.

Please, double please, reconsider the direction of globalThis.fetch’s implementation.

@mcollina
Copy link
Member

I have opened wintercg/fetch#7 to discuss with the WinterCG team.

@benjamingr
Copy link
Member

Hey, @issuefiler.

Node landed an experimental implementation of fetch given some semantics people think make sense. Part of the fact it's experimental is because we are explicitly looking for feedback and to see how people think fetch should behave.

Please be mindful of how you phrase yourself. Your comment comes off (to me) as harsh whereas this sort of feedback (the technical bits) are welcome. There are many people using Node.js with different requirements, preferences and ideas about what APIs should do and Node.js is happy to listen to those users in good faith and reconsider API choices.

Your comment makes this a bit hard given the tone. If you want effective discourse I recommend you consider a different approach/tone towards the volunteers working on new features for the platform.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request fetch
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants