`Set-Cookie` headers should not be combined / Support `Headers.getSetCookie()` method
ezzatron opened this issue · comments
The Fetch Standard defines special behaviour for Set-Cookie
headers:
To sort and combine a header list list, run these steps. They return a header list.
- Let headers be a header list.
- Let names be the result of convert header names to a sorted-lowercase set with all the names of the headers in list.
- For each name of names:
- If name is `
set-cookie
`, then:- Otherwise:
- Return headers.
This is because the values of set-cookie
headers can contain commas, such as in the case of a cookie with an expiry time (e.g. cookie-name=cookie-value; Path=/; Expires=Thu, 21 Sep 2023 06:12:39 GMT; Secure
). Combining them with commas can change their semantics.
This library currently seems to ignore this part of the spec, and combine set-cookie
values. For example, this is the current behaviour of whatwg-fetch
:
const { Headers } = require("whatwg-fetch");
const headers = new Headers();
headers.append("Set-Cookie", "x=x");
headers.append("Set-Cookie", "y=y");
console.log(JSON.stringify([...headers.entries()])); // outputs [["set-cookie","x=x, y=y"]]
In comparison, Chrome and Firefox follow the spec (Safari doesn't):
![Chrome output Chrome output](https://private-user-images.githubusercontent.com/100152/269492221-5950e719-4836-4aad-a96c-bdb0ec47ea7d.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjMwMDE2MjksIm5iZiI6MTcyMzAwMTMyOSwicGF0aCI6Ii8xMDAxNTIvMjY5NDkyMjIxLTU5NTBlNzE5LTQ4MzYtNGFhZC1hOTZjLWJkYjBlYzQ3ZWE3ZC5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjQwODA3JTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI0MDgwN1QwMzI4NDlaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT1mNTJmMjg0YWVjYzYxOTU5ZGYzNWRlYzgxODI2ZDljZmY2ZjQ4MGU0NmIxNGNiNmZhMjAxMGE5YWVmNzVjMzIxJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCZhY3Rvcl9pZD0wJmtleV9pZD0wJnJlcG9faWQ9MCJ9.JM0LOuAp4AEfVupdKjgwrxJn_BHqjBrT8NVrF2Igpd4)
![Firefox output Firefox output](https://private-user-images.githubusercontent.com/100152/269492393-aae866ec-5377-4769-a51e-83a74563c2da.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjMwMDE2MjksIm5iZiI6MTcyMzAwMTMyOSwicGF0aCI6Ii8xMDAxNTIvMjY5NDkyMzkzLWFhZTg2NmVjLTUzNzctNDc2OS1hNTFlLTgzYTc0NTYzYzJkYS5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjQwODA3JTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI0MDgwN1QwMzI4NDlaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT0wOTZhM2FmZjM4Mzc5MzYxNGZhN2U2YTFiMDNlNTA5Njc4ZjdiMDc2MWE2YzNiZDY3NjYxMDI5NjE2OGQxY2FiJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCZhY3Rvcl9pZD0wJmtleV9pZD0wJnJlcG9faWQ9MCJ9.dVnJCD4PDk3sCRrZl5SUKt56ur8kpaajg05-0EGBwwk)
This seems to be a pretty recent addition to the spec (2021ish). There's also a new method Headers: getSetCookie() method added around the same time which is missing from whatwg-fetch
:
![Chrome getSetCookie output Chrome getSetCookie output](https://private-user-images.githubusercontent.com/100152/269497112-436a49fd-a5bd-4e3d-9edc-9656b155f532.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjMwMDE2MjksIm5iZiI6MTcyMzAwMTMyOSwicGF0aCI6Ii8xMDAxNTIvMjY5NDk3MTEyLTQzNmE0OWZkLWE1YmQtNGUzZC05ZWRjLTk2NTZiMTU1ZjUzMi5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjQwODA3JTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI0MDgwN1QwMzI4NDlaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT1mMmFjNjVkYWIyODM5MTBmNjk2YmYxYWE0NDg2Y2M2NTZhMzYzMTFkYWNlY2M2YTk0ZjY0NWNkN2JiNDc2NmU0JlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCZhY3Rvcl9pZD0wJmtleV9pZD0wJnJlcG9faWQ9MCJ9.s8eZij7DShUDZ-LYKmk9mfbfTaUlz9vXyZfcJLmEX_k)
For context, I'm using whatwg-fetch
as a polyfill for running Jest tests that use Mock Service Worker (MSW), similar to this example over in the MSW project. I noticed this issue because I was setting multiple cookies with different options, and the combining of the cookie values was causing strange behaviour in my tests.