Node HTTP2 request with remote proxy
Asked Answered
K

1

1

I'm trying to run the following example in Node. It runs properly with HTTP/1.1 but fails with HTTP2:

// Get an HTTP/1.1 tunnel:
const req = http.request({
  method: 'CONNECT',
  host: proxy.host, // This is a remote proxy which works properly with http/1.1
  port: proxy.port,
  path: 'example.com'
});
req.end();

const tunnelledSocket = await new Promise((resolve) => {
  req.on('connect', (_res, socket) => resolve(socket));
});

// We can now read/write to our raw TCP socket to example.com:
const client = http2.connect('https://example.com', {
  // Tunnel this request through the HTTP/1.1 tunnel:
  createConnection: () => tunnelledSocket
});

// Until here all is good, the problem comes when trying to load the url.
const proxiedRequest = client.request({
  ':path': '/test'
});

I'm getting the following unhelpful error from node:

Error [ERR_HTTP2_ERROR]: Protocol error
    at new NghttpError (node:internal/http2/util:550:5)
    at Http2Session.onSessionInternalError (node:internal/http2/core:776:26) {
  code: 'ERR_HTTP2_ERROR',
  errno: -505
}

I couldn't find any clear answer on how to solve it.

Kiddush answered 16/1, 2021 at 18:46 Comment(0)
K
1

So I found a possible answer.

When creating the connection, you need to connect HTTP2 with tls as it's an HTTPS request, but you need to ignore the certificate errors as otherwise, tls will complain that you are connecting to a domain where you don't own a certificate. At least that is the only way I managed to do it.

I'm open to hear better solutions.

const client = http2.connect('https://example.com', {
  createConnection: () =>
    tls.connect({
      socket: tunnelledSocket,
      rejectUnauthorized: false,
      ALPNProtocols: ['h2'],
    }),
});
Kiddush answered 16/1, 2021 at 19:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.