remix: Headers polyfill is missing properties and incorrectly adds getAll

What version of Remix are you using?

1.19.2

Are all your remix dependencies & dev-dependencies using the same version?

  • Yes

Steps to Reproduce

const headers = new Headers()
headers.getSetCookie // not defined, should be.

~~The typings aren’t there for it in TypeScript either. I’ve opened an issue about that: https://github.com/microsoft/TypeScript/issues/55270~~ (this has been fixed)

Also, there are properties in URLSearchParams that aren’t on Headers:

  • getAll
  • sort
  • size
  • toString (should just be [object Headers]

Expected Behavior

Headers should follow the standard

Actual Behavior

It is missing a property and adds some properties that aren’t in the spec.

About this issue

  • Original URL
  • State: open
  • Created a year ago
  • Reactions: 6
  • Comments: 16 (12 by maintainers)

Commits related to this issue

Most upvoted comments

@brophdawg11

@remix-run/web-fetch is missing getSetCookie in Response (used by handleDocumentRequestRR)

I don’t know if it is still mandatory to use it in entry.server.tsx but it breaks HonoJS integration.

Ref: https://github.com/honojs/node-server/issues/58

PR: https://github.com/mswjs/headers-polyfill/pull/68

With this, the entire Remix test suite passed when we used headers-polyfill directly in @remix-run/web-fetch (https://github.com/remix-run/web-std-io/pull/50)

Awesome - yeah I would choose the MSW polyfill over undici as well. Let me play around with this a bit and see what it looks like if we switch to the MSW Headers polyfill in @remix-run/web-fetch. The goal of our polyfill was to align as close as possible to the spec - so assuming the MSW polyfill has the same goals (which I believe it does), I think it could be a good fit 😃

It’s also worth noting that in Remix v2 we’ll no longer install our polyfill automatically, and leave it up to the user to install so they can use native fetch directly if they prefer.

To my best knowledge, headers-polyfill should be fully compatible with the latest state of the Headers class in JavaScript. We’ve just recently added a new getSetCookie method and are actively maintaining the project otherwise. We don’t re-implement everything from scratch but rather keep a simple internal Map of headers to ease header references and support case insensitivity, and employ third-party packages, like set-cookie-parser for header parsing heavy-lifting because we’d rather use a battle-tested third-party.

If you are looking for a complete from-scratch zero-dependency polyfill of Headerrs, then you’re better off with something else. If you’re looking for a drop-in replacement for Headers, then this is what we’ve been using in MSW for years now.

That being said, consider undici as well. Undici is the official Fetch API implementation that Node.js uses, and they expose the Headers class as well. This is the best option in terms of compatibility because it’s literally what’s being used in Node.js. I’ll leave it to your judgment to decide whether you want to rely on experimental API though.

The types have been updated in TypeScript

With TypeScript v5.2.2, this causes type checking to fail

node_modules/@remix-run/web-fetch/dist/src/headers.d.ts:19:22 - error TS2420: Class 'import("/Users/andrew/cerbos/spitfire/ui/node_modules/@remix-run/web-fetch/dist/src/headers").default' incorrectly implements interface 'Headers'.
  Property 'getSetCookie' is missing in type 'import("/Users/andrew/cerbos/spitfire/ui/node_modules/@remix-run/web-fetch/dist/src/headers").default' but required in type 'Headers'.

19 export default class Headers extends URLSearchParams implements globalThis.Headers {
                        ~~~~~~~

  node_modules/typescript/lib/lib.dom.d.ts:13447:5
    13447     getSetCookie(): string[];
              ~~~~~~~~~~~~~~~~~~~~~~~~~
    'getSetCookie' is declared here.