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

.getSetCookie() and .get('set-cookie') methods are both broken on headers() #54033

Closed
1 task done
controversial opened this issue Aug 14, 2023 · 6 comments · Fixed by vercel/edge-runtime#540
Closed
1 task done
Labels
bug Issue was opened via the bug report template. linear: next Confirmed issue that is tracked by the Next.js team. locked Runtime Related to Node.js or Edge Runtime with Next.js. TypeScript Related to types with Next.js.

Comments

@controversial
Copy link
Contributor

controversial commented Aug 14, 2023

Verify canary release

  • I verified that the issue exists in the latest Next.js canary release

Provide environment information

Operating System:
      Platform: darwin
      Arch: arm64
      Version: Darwin Kernel Version 23.0.0: Tue Aug  1 03:25:51 PDT 2023; root:xnu-10002.0.242.0.6~31/RELEASE_ARM64_T6000
    Binaries:
      Node: 20.2.0
      npm: 9.8.1
      Yarn: N/A
      pnpm: N/A
    Relevant Packages:
      next: 13.4.15
      eslint-config-next: 13.4.15
      react: 18.2.0
      react-dom: 18.2.0
      typescript: 5.1.6
    Next.js Config:
      output: N/A

Which area(s) of Next.js are affected? (leave empty if unsure)

App Router, Middleware / Edge (API routes, runtime), TypeScript (plugin, built-in types)

Link to the code that reproduces this issue or a replay of the bug

https://codesandbox.io/p/sandbox/fervent-bird-ylrc3x?file=/app/page.tsx

To Reproduce

  1. Set multiple cookies on the response, e.g. in middleware
  2. Read headers().get('set-cookie') in a React Server Component.
  3. Call headers().getSetCookie() (which can be called, even though its TypeScript definition is missing from Next.js)
    • Observe that an empty array is returned, even though headers.get('set-cookie') returns a value (albeit incorrect) for the Set-Cookie header.

Describe the Bug

  • The headers().get('set-cookie') method concatenates multiple values into a single comma-separated string, which is incorrect behavior and explicitly violates the HTTP specification:

    Origin servers SHOULD NOT fold multiple Set-Cookie header fields into a single header field. The usual mechanism for folding HTTP headers fields (i.e., as defined in [RFC2616]) might change the semantics of the Set-Cookie header field because the %x2C (",") character is used by Set-Cookie in a way that conflicts with such folding.

  • The headers().getSetCookie() method returns an empty array when headers().get('set-cookie') does not

  • TypeScript definitions for headers().getSetCookie() are missing

This blocks applications from reading cookies that are updated by middleware as part of the same request, which is a common flow for use cases such as token refreshing (see discussions like #50374, #38650)

Expected Behavior

  • The headers().get('set-cookie') method should not concatenate multiple values into a single comma-separated string
  • The headers().getSetCookie() method (spec) should return a non-empty array, containing the separate values of the multiple Set-Cookie headers

Which browser are you using? (if relevant)

N/A

How are you deploying your application? (if relevant)

N/A

NEXT-1523

@controversial controversial added the bug Issue was opened via the bug report template. label Aug 14, 2023
@github-actions github-actions bot added Runtime Related to Node.js or Edge Runtime with Next.js. TypeScript Related to types with Next.js. labels Aug 14, 2023
@controversial controversial changed the title .getSetCookie() method missing from headers(), and .get('set-cookie') is broken .getSetCookie() and .get('set-cookie') methods are both broken on headers() Aug 15, 2023
@viktorlarsson
Copy link

viktorlarsson commented Aug 16, 2023

Great find, currently blocking a major release for us. Related: nextauthjs/next-auth#7443 (comment)

@balazsorban44
Copy link
Member

balazsorban44 commented Aug 17, 2023

The headers().get('set-cookie') method should not concatenate multiple values into a single comma-separated string

Although the HTTP spec says so, the Headers spec says the opposite for .get():

https://fetch.spec.whatwg.org/#dom-headers-get

Hence the introduction of .getSetCookie() in the first place. The bug here is that the implementation for it might be wrong.

As for TypeScript, it's still missing from the official types microsoft/TypeScript#55270 but we can probably extend it via edge-runtime (what Next.js is using) where we can guarantee the existence of this property.

Related: vercel/edge-runtime#536

Also note, Headers.getAll is non-spec and should not be relied on. It was a platform-specific implementation before the getSetCookie spec existed (whatwg/fetch#973)

To sum it up, it looks like we have to make sure .getSetCookie() works as expected. The rest looks good to me.

@balazsorban44 balazsorban44 added the linear: next Confirmed issue that is tracked by the Next.js team. label Aug 17, 2023
@balazsorban44
Copy link
Member

Upon some further investigation, it turns out that the only (new) issue here is the missing typings for getSetCookie. The fact that headers().get('set-cookie') returns something, in this case, is a bug.

You are setting response headers in your middleware, and headers() is supposed to read request headers. There is already an open issue for it at #52564

@balazsorban44
Copy link
Member

So the type is actually out in [email protected] microsoft/TypeScript#55270 (comment) just have to wait until it gets to latest. For now, the workaround is @ts-expect-error

@controversial
Copy link
Contributor Author

Thanks for looking into it @balazsorban44!

@github-actions
Copy link
Contributor

github-actions bot commented Sep 2, 2023

This closed issue has been automatically locked because it had no new activity for 2 weeks. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.

@github-actions github-actions bot added the locked label Sep 2, 2023
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Sep 2, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Issue was opened via the bug report template. linear: next Confirmed issue that is tracked by the Next.js team. locked Runtime Related to Node.js or Edge Runtime with Next.js. TypeScript Related to types with Next.js.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants