Skip to content

Conversation

@tinovyatkin
Copy link
Member

@tinovyatkin tinovyatkin commented May 24, 2020

What is the purpose of this pull request?

  • Other, please explain:

This is an almost complete rewrite of the Headers module (so, diff is looking crazy - it's better just to read new code completely).

The current implementation of Headers is somewhere painful to read (particularly iterator implementation). It's nowhere close to being lightweight too with inventing some wheels and avoiding modern language features.

What changes did you make? (provide an overview)

The only change to test file is the replacement of originally broken test for createHeadersLenient - it was testing for falseness properties on Headers object that was always false.
Change for other files is renaming of internal methods createHeadersLenient (to fromRawHeaders) and exportNodeCompatibleHeaders (to build-in symbol).

The approach used in this refactoring is to take advantage of the fact, that there is almost completely identical by shape built-in object in Node >= 10.0 - URLSearchParams (I do believe it was copied from Headers when introduced browser-side, so, now we can reuse it back). We extend here URLSearchParams attending minor differences in functionality (case insensitivity, parameters validation, and keys iteration) via lightweight Proxy, and major functionality differences (get and values iteration) as overloaded methods.

I'd moved exportNodeCompatibleHeaders export into Node.JS built-in symbol, so, it also now serves for everyone secret debug powerhouses - console.log(response.headers)

I've replaced createHeadersLenient and creating Headers from rawHeaders, that fixes #783.

With the use of Proxy, constructor return value and generator functions in the source is also a fun weekend reading for everybody who loves modern JavaScript 😄

Is there anything you'd like reviewers to know?

This PR purposely doesn't touch any tests to showcase that module is in equal functionality, however, there are some points to discuss:

  1. Headers now, by side effect, exposing getAll method (as it exists on URLSearchParams) that was removed from client-side spec due to security concern and then removed from node-fetch too, then raw was introduced when we realized than on the server-side, indeed, we need to be able to get all values.
    It's easy to hide this method completely (or make non-enumerable), or leave it undocumented (all other modules as Request and Response are exposing some non-spec methods and we have raw here anyway) or to document it. I do believe it's an extremely useful server-side and better fit for Cookies than raw. So @node-fetch/core probably should decide here.
    See: Use case for Headers getAll whatwg/fetch#973 (comment)

  2. There is no current test for new Headers(null) and it passes in both new and original versions of Headers. However, it throws at Chrome. Should behavior be adjusted and test added?

3. There is a subtle difference in how headers are returned concatenated - node-fetch is using , to join them while browsers use just coma. Should it be adjusted?

  1. Proxies are fast in v8: https://v8.dev/blog/optimizing-proxies

@tinovyatkin tinovyatkin changed the title revamp-headers revamp Headers module May 24, 2020
@tinovyatkin tinovyatkin requested review from bitinn and xxczaki May 24, 2020 16:59
@xxczaki xxczaki requested review from Richienb, gr2m and jimmywarting May 24, 2020 17:22
Copy link
Member

@NotMoni NotMoni left a comment

Choose a reason for hiding this comment

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

Lgtm

Copy link
Member

@xxczaki xxczaki left a comment

Choose a reason for hiding this comment

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

👍

@tinovyatkin
Copy link
Member Author

Screenshot 2020-05-25 at 03 04 04
🎉 💪

Copy link
Member

@LinusU LinusU left a comment

Choose a reason for hiding this comment

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

Neat! 👍

@xxczaki
Copy link
Member

xxczaki commented May 25, 2020

Before merging this, I think we should discuss the last points from the PR description.

Here are my thoughts:

  1. I think we can expose getAll, while this was removed from the specification, I agree that it fits Node.js server environment better than raw and certainly helps in a lot of use cases.
  2. What's the behavior in other browsers? Is it defined in the Fetch standard?
  3. If it's something, that is described in the Fetch standard, we should adjust it.

cc @node-fetch/core @tinovyatkin

@xxczaki xxczaki mentioned this pull request May 25, 2020
4 tasks
@tinovyatkin
Copy link
Member Author

tinovyatkin commented May 25, 2020

My personal thoughts:

  1. I'm 👍🏻 for exposing and documenting getAll. We get it for free with this implementation and from the hard-voice comment Use case for Headers getAll whatwg/fetch#973 (comment) I do believe that WHATWG doesn't care about fetch standard interoperability, so, an extension that makes sense for runtime environment will not hurt.
    I'm seeing raw both, badly named (because it's not exposing anything raw actually - all processed and lowercased) and not very useful if getAll will be available. So, we can remove it in 3.0.
    I would be inviting @kentonv or whatever person that @cloudflare seems appropriate to join @node-fetch/core and participate in such decisions.

  2. Both, Firefox and Chrome throws on new Headers(null)

  3. I don't remember how this topic get here, our functionality here is equal to browsers.

@tinovyatkin
Copy link
Member Author

@xxczaki I believe with 5 approvals and no opposing comments this PR can be merged and nuances 1 and 2 attended/discussed in separate PRs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

doesn't correctly handle multiple content-type values

6 participants