Node.js HTTP/2 via HTTP CONNECT avec createConnection
Terminez CONNECT, négociez le TLS de destination avec h2, puis utilisez createConnection pour garder http2.connect sur ce flux.
Un proxy HTTP/1.1 peut transporter les trames HTTP/2 de la destination à l'intérieur de CONNECT. Le proxy n'a pas besoin d'implémenter ces trames internes, mais le client doit effectuer les passages de protocole dans l'ordre.
Après avoir validé la réponse CONNECT complète et conservé son tunnelSocket, ajoutez le TLS de destination et confiez le flux établi à 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 renvoie le flux TLS déjà porté par le proxy au lieu d'ouvrir un autre socket direct. Le servername de destination fournit le SNI et l'identité du certificat, la vérification étant activée. Le contrôle ALPN rejette une destination qui n'a pas négocié h2.
failRoute doit nettoyer la route ; useSession possède les requêtes et la fermeture de session. Appliquez des délais de connexion et d'opération autour de ce fragment.
Le connecteur externe reste responsable du ciblage CONNECT host:port, de l'authentification auprès du proxy, du traitement des rejets et des octets mis en tampon après les en-têtes. Terminez-les avant de confier le socket à TLS ; une préface HTTP/2 envoyée directement à un écouteur proxy HTTP/1.1 commence à la mauvaise couche.