Проксі HTTP/1.1 можа пераносіць кадры HTTP/2 прызначэння ўнутры CONNECT. Проксі не абавязаны рэалізоўваць гэтыя ўнутраныя кадры, але кліент павінен выконваць перадачу пратаколаў па парадку.

Пасля праверкі поўнага адказу CONNECT і захавання tunnelSocket дадайце TLS прызначэння і перадайце ўсталяваны паток у HTTP/2:

import tls from 'node:tls';
import http2 from 'node:http2';

const secureSocket = tls.connect({
  socket: tunnelSocket,
  servername: 'api.example',
  ALPNProtocols: ['h2'],
});
secureSocket.once('error', failRoute);
secureSocket.once('secureConnect', () => {
  if (secureSocket.alpnProtocol !== 'h2') {
    secureSocket.destroy();
    failRoute(new Error('Destination did not negotiate h2'));
    return;
  }
  const session = http2.connect('https://api.example', {
    createConnection: () => secureSocket,
  });
  session.on('error', failRoute);
  useSession(session);
});

createConnection вяртае паток TLS, які ўжо пераносіць проксі, замест адкрыцця чарговага прамога сокета. servername прызначэння дае SNI і ідэнтычнасць сертыфіката пры ўключанай праверцы. Праверка ALPN адхіляе прызначэнне, якое не ўзгадніла h2.

failRoute павінен ачысціць маршрут; useSession валодае запытамі і закрыццём сесіі. Ужывайце тэрміны злучэння і аперацый вакол гэтага фрагмента.

Знешні канэктар па-ранейшаму адказвае за мэтавы host:port CONNECT, аўтэнтыфікацыю проксі, апрацоўку адмоў і байты, буфераваныя пасля загалоўкаў. Завяршыце гэта перад перадачай сокета ў TLS; прэамбула HTTP/2, адпраўленая проста ў слухач проксі HTTP/1.1, пачынаецца на няправільным узроўні.

Падобныя артыкулы