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

Add special handling of set-cookie to Headers #1346

Merged
merged 16 commits into from
Feb 8, 2023

Conversation

lucacasonato
Copy link
Member

@lucacasonato lucacasonato commented Oct 29, 2021

fetch.bs Outdated Show resolved Hide resolved
Co-authored-by: Steven <[email protected]>
fetch.bs Outdated Show resolved Hide resolved
fetch.bs Outdated Show resolved Hide resolved
fetch.bs Outdated Show resolved Hide resolved
fetch.bs Outdated Show resolved Hide resolved
fetch.bs Show resolved Hide resolved
fetch.bs Outdated Show resolved Hide resolved
@annevk
Copy link
Member

annevk commented Nov 1, 2021

Thanks for working on this, this looks quite promising to me. @yutakahirano @ricea @youennf thoughts?

lucacasonato and others added 6 commits November 1, 2021 11:27
fetch.bs Outdated Show resolved Hide resolved
Co-authored-by: Andreu Botella <[email protected]>
@lucacasonato
Copy link
Member Author

@jasnell @kentonv thoughts?

Copy link
Member

@yutakahirano yutakahirano left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

fetch.bs Outdated Show resolved Hide resolved
fetch.bs Outdated Show resolved Hide resolved
fetch.bs Outdated Show resolved Hide resolved
Copy link

@jasnell jasnell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. For Workers we do currently take a different approach using getAll() that we'll need to maintain for a while but there's nothing here that should interfere with us being able to support this as well.

@kentonv
Copy link

kentonv commented Nov 4, 2021

I'm fine with this.

I have a weak opinion that, for server-side vendors, getAll() is slightly more flexible: If we have some big customer come along and say "We really need to access this legacy API, but it has a header that misuses commas, which we can't change," we can easily say "No problem, we'll just add your special weird header to the getAll() allow list." On the server side, implementing special requests for high-paying customers are not uncommon. Obviously, on the browser side, such special requests would be complete nonsense, since web sites don't get to choose which browser is used to open them.

But I have seen no evidence that any such headers exist in the wild, so it seems unlikely we'll ever get this exact sort of special request. So, whatever. :)

@annevk
Copy link
Member

annevk commented Nov 5, 2021

It's more flexible, but it would also violate HTTP, as would any header that needs it (with the exception of Set-Cookie).

@jimmywarting
Copy link

I'm not opposed to adding this into node-fetch either. I will only be glad that we can unite on one unified api that works the same across all platform

jasnell added a commit to cloudflare/workerd that referenced this pull request Feb 13, 2023
webkit-early-warning-system pushed a commit to andreubotella/WebKit that referenced this pull request Feb 20, 2023
https://bugs.webkit.org/show_bug.cgi?id=251194

Reviewed by Youenn Fablet.

This change implements the `getSetCookie` method of the fetch spec's
`Headers` interface. This change allows storing `Set-Cookie` headers as
a list of values, and retrieving the separate values, rather than their
combined representation, which is ambiguous. This change also makes it
so iterating through `Headers` objects will yield `Set-Cookie` headers
separately rather than combined, which is part of the same change in the
fetch spec.

Given that `Set-Cookie` is a forbidden header name in both requests and
responses, this will not be useful for any uses of `Headers` related to
fetch. It does allows some non-fetch use cases, however, and enables
further compatibility with server-side runtimes that do allow this
header.

Rather than refactoring `HTTPHeaderMap` to not combine (all) headers,
this implementation makes use of the fact that `Set-Cookie` is forbidden
for both requests and responses, to store the `Set-Cookie` values in a
vector of strings directly in `FetchHeaders` instead. This needed such
header name to be special-cased in almost every operation of this class.
And in order to have `Set-Cookie` headers properly appear in their right
order in the pair iterator, `m_keys` has been changed to be a pair where
the second element is an index into the `Set-Cookie` values vector,
which is ignored for other header names.

Fetch spec PR: whatwg/fetch#1346

This commit also imports the corresponding WPT tests from
web-platform-tests/wpt#31442, and adds some
additional tests.

* Source/WebCore/Modules/fetch/FetchHeaders.cpp:
(WebCore::appendToHeaderMap):
(WebCore::fillHeaderMap):
(WebCore::FetchHeaders::create):
(WebCore::FetchHeaders::fill):
(WebCore::FetchHeaders::append):
(WebCore::FetchHeaders::remove):
(WebCore::FetchHeaders::get const):
(WebCore::FetchHeaders::getSetCookie const):
(WebCore::FetchHeaders::has const):
(WebCore::FetchHeaders::set):
(WebCore::FetchHeaders::Iterator::next):
* Source/WebCore/Modules/fetch/FetchHeaders.h:
(WebCore::FetchHeaders::create):
(WebCore::FetchHeaders::fastGet const):
(WebCore::FetchHeaders::fastHas const):
(WebCore::FetchHeaders::fastSet):
(WebCore::FetchHeaders::FetchHeaders):
* Source/WebCore/Modules/fetch/FetchHeaders.idl:
* Source/WebCore/platform/network/ResourceResponseBase.cpp:
(WebCore::ResourceResponseBase::httpHeaderField const):

Canonical link: https://commits.webkit.org/260533@main
moz-v2v-gh pushed a commit to mozilla/gecko-dev that referenced this pull request Feb 20, 2023
…rs, a=testonly

Automatic update from web-platform-tests
Fetch: the Set-Cookie header, and Header's getSetCookie()

For whatwg/fetch#1346.

Co-authored-by: Andreu Botella <[email protected]>
Co-authored-by: Andreu Botella <[email protected]>
Co-authored-by: Anne van Kesteren <[email protected]>
--

wpt-commits: 14151646ae4684a32638d73187381fc0ed86e2c8
wpt-pr: 31442
jamienicol pushed a commit to jamienicol/gecko that referenced this pull request Feb 23, 2023
…rs, a=testonly

Automatic update from web-platform-tests
Fetch: the Set-Cookie header, and Header's getSetCookie()

For whatwg/fetch#1346.

Co-authored-by: Andreu Botella <[email protected]>
Co-authored-by: Andreu Botella <[email protected]>
Co-authored-by: Anne van Kesteren <[email protected]>
--

wpt-commits: 14151646ae4684a32638d73187381fc0ed86e2c8
wpt-pr: 31442
nfriedly added a commit to nfriedly/set-cookie-parser that referenced this pull request Mar 18, 2023
nfriedly added a commit to nfriedly/set-cookie-parser that referenced this pull request Mar 18, 2023
marcoscaceres pushed a commit to web-platform-tests/wpt that referenced this pull request Mar 28, 2023
For whatwg/fetch#1346.

Co-authored-by: Andreu Botella <[email protected]>
Co-authored-by: Andreu Botella <[email protected]>
Co-authored-by: Anne van Kesteren <[email protected]>
timneutkens pushed a commit to vercel/next.js that referenced this pull request Mar 31, 2023
## What

This fix serves to address issues where multiple `Set-Cookie` headers
were combined in some runtimes.

## Why

This is because `set-cookie` behaves differently than other headers in
some cases.

Eg. when iterating on a `Headers` instance, multiple set-cookie headers
are folded. To set them correctly, we need to split them. But it'd not
be enough to naively split on the first occurrence, because `,` is a
valid cookie value when for example it's used in `Expires` in a date
string.

So we use a method to correctly detect where to split the cookie.

This should fix all runtimes.

Note, the spec now has `Headers#getSetCookie` which should be preferred
if it's present. whatwg/fetch#1346. We are using
the [`edge-runtime`](https://github.com/vercel/edge-runtime), so this
should be fixed upstream and then reused in Next.js in the future.

## How

Wherever we can, we reuse the `fromNodeHeaders` and `toNodeHeaders`
methods that have the correct implementation. This should be preferred
in the future in other parts of the codebase. We fixed some related TS
issues as well.

Fixes #46579, supersedes #40579
fix NEXT-735 ([link](https://linear.app/vercel/issue/NEXT-735))

---------

Co-authored-by: Balázs Orbán <[email protected]>
bartlomieju added a commit to denoland/deno that referenced this pull request Jul 2, 2023
Spec change: whatwg/fetch#1346
Tests: web-platform-tests/wpt#31442 (ran against
this PR and they all pass)

---------

Co-authored-by: Bartek Iwańczuk <[email protected]>
@lucacasonato lucacasonato deleted the special_headers_handling branch August 17, 2023 10:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.