Proxy HTTP/1.1 có thể mang các khung HTTP/2 của đích bên trong CONNECT. Proxy không cần triển khai các khung bên trong đó, nhưng máy khách phải thực hiện các bước chuyển giao giao thức theo thứ tự.

Sau khi xác thực phản hồi CONNECT đầy đủ và giữ lại tunnelSocket, hãy thêm TLS của đích và giao luồng đã thiết lập cho 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 trả lại luồng TLS mà proxy đã mang thay vì mở một socket trực tiếp khác. servername của đích cung cấp SNI và danh tính chứng chỉ, với quá trình xác minh được bật. Kiểm tra ALPN từ chối đích không thương lượng h2.

failRoute phải dọn dẹp tuyến; useSession sở hữu các yêu cầu và việc đóng phiên. Áp dụng thời hạn kết nối và thao tác quanh đoạn này.

Bộ kết nối bên ngoài vẫn sở hữu việc nhắm mục tiêu CONNECT host:port, xác thực với proxy, xử lý từ chối và các byte được đệm sau phần đầu. Hoàn tất những việc đó trước khi giao socket cho TLS; phần mở đầu HTTP/2 gửi thẳng tới trình lắng nghe proxy HTTP/1.1 bắt đầu ở tầng sai.

Bài viết liên quan