Проксі 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, починається на неправильному рівні.

Схожі статті