يمكن لوكيل 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 الطلبات وإغلاق الجلسة. طبّق مهلات الاتصال والتشغيل حول هذا المقطع.

لا يزال الموصل الخارجي مسؤولًا عن استهداف CONNECT بالمضيف:المنفذ، ومصادقة الوكيل، ومعالجة الرفض، والبايتات المخزّنة بعد الترويسات. أنهِ ذلك قبل تسليم المقبس إلى TLS؛ فمقدمة HTTP/2 المرسلة مباشرة إلى مستمع وكيل HTTP/1.1 تبدأ في الطبقة الخطأ.

مقالات ذات صلة