Skip to content

chore: http2 support (WIP)#796

Closed
xxczaki wants to merge 8 commits intomasterfrom
http2
Closed

chore: http2 support (WIP)#796
xxczaki wants to merge 8 commits intomasterfrom
http2

Conversation

@xxczaki
Copy link
Copy Markdown
Member

@xxczaki xxczaki commented May 9, 2020

Do not merge yet!

Fixes #342


I've decided to try and implement http2 support in node-fetch. I ended up using the http2-client module, which makes it easy to support https/1.1 and http/2.0 protocols without doing any changes at all.

The current implementation does not support unencrypted http2, due to test issues.

Now, I'm not sure whether this approach is correct. I will try to experiment more in the upcoming days.

const options = getNodeRequestOptions(request);

const send = (options.protocol === 'https:' ? https : http).request;
const send = (options.protocol === 'https:' ? http2 : http.request);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

this could in theory support h2c

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

@devsnek Yes, I tried replacing both https & http modules with just http2-client, but some tests are failing then (mainly these related to error handling and form-data). I'm not sure about the form-data, but in terms of error handling - we would probably need to change the way we capture fetch errors in order to make it work:

  207 passing (13s)
  7 failing

  1) node-fetch
       should reject with error on network failure:
     Uncaught Error: connect ECONNREFUSED 127.0.0.1:50000
      at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1141:16)

  2) node-fetch
       system error is extracted from failed requests:
     Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves. (/home/akepinski/dev/node-fetch/test/main.js)
      at listOnTimeout (internal/timers.js:549:17)
      at processTimers (internal/timers.js:492:7)

  3) node-fetch
       should handle DNS-error response:
     Uncaught Error: getaddrinfo ENOTFOUND domain.invalid
      at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:64:26)

  4) node-fetch
       should allow POST request with form-data as body:
     FetchError: request to http://localhost:30001/multipart failed, reason: socket hang up
      at ClientRequest.<anonymous> (src/index.js:107:11)
      at Socket.socketOnEnd (_http_client.js:453:9)
      at endReadableNT (_stream_readable.js:1187:12)
      at processTicksAndRejections (internal/process/task_queues.js:84:21)

  5) node-fetch
       should allow POST request with form-data using stream as body:
     Uncaught Error: Message underflow.
      at Parser._error (node_modules/parted/lib/multipart.js:317:7)
      at Parser.end (node_modules/parted/lib/multipart.js:89:17)
      at IncomingMessage.onend (_stream_readable.js:660:10)
      at endReadableNT (_stream_readable.js:1187:12)
      at processTicksAndRejections (internal/process/task_queues.js:84:21)

  6) node-fetch
       should allow POST request with form-data using stream as body:
     FetchError: request to http://localhost:30001/multipart failed, reason: socket hang up (and Mocha's done() called multiple times)
      at ClientRequest.<anonymous> (src/index.js:107:11)
      at Socket.socketOnEnd (_http_client.js:453:9)
      at endReadableNT (_stream_readable.js:1187:12)
      at processTicksAndRejections (internal/process/task_queues.js:84:21)

  7) node-fetch
       should allow POST request with form-data as body and custom headers:
     FetchError: request to http://localhost:30001/multipart failed, reason: socket hang up
      at ClientRequest.<anonymous> (src/index.js:107:11)
      at Socket.socketOnEnd (_http_client.js:453:9)
      at endReadableNT (_stream_readable.js:1187:12)
      at processTicksAndRejections (internal/process/task_queues.js:84:21)

@Richienb Richienb marked this pull request as draft May 10, 2020 01:36
@xxczaki xxczaki mentioned this pull request May 17, 2020
35 tasks
@tinovyatkin
Copy link
Copy Markdown
Member

I'm strongly 👎 over this approach: not sure as for everybody else, but at least for me personally, node-fetch is a reference and lightweight implementation of HTTP client operation over Node.JS built-in API, not a wrapper of an external wrapping client.
If we will outsource such an important core part of this functionality as ALPNP negotiation to a way less popular and less maintained library then we will end-up as request or lodash, who blown themselves.
ALPN is core functionality of this library and should be within node-fetch with slim and well-tested code. Contrary we can just create two lines wrapper around fetch-h2 and go home.

@xxczaki
Copy link
Copy Markdown
Member Author

xxczaki commented May 21, 2020

@tinovyatkin I agree, I tried using http2-client and http2-wrapper to see whether they would instantly enable HTTP/2 support or an additional configuration will be needed. Using the built-in http2 module is definitely the way to go, but considering the amount of work it would require and previous discussions, I feel like this change should not be included in 3.0.0, but rather in 3.1.0.

@xxczaki xxczaki closed this May 21, 2020
@tinovyatkin tinovyatkin deleted the http2 branch May 21, 2020 19:19
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.

Support HTTP/2

3 participants