createConnection을 사용한 HTTP CONNECT 경유 Node.js HTTP/2
CONNECT를 끝내고 h2로 대상 TLS를 협상한 다음, createConnection으로 http2.connect를 그 스트림 위에 유지하세요.
HTTP/1.1 프록시는 CONNECT 안에서 대상의 HTTP/2 프레임을 실어 나를 수 있습니다. 프록시가 그 내부 프레임을 구현할 필요는 없지만, 클라이언트는 프로토콜 인계를 순서대로 수행해야 합니다.
완전한 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/1.1 프록시 리스너로 곧장 보낸 HTTP/2 프리앰블은 잘못된 계층에서 시작합니다.