11cb0ef41Sopenharmony_ci'use strict'; 21cb0ef41Sopenharmony_ci 31cb0ef41Sopenharmony_ciconst common = require('../common'); 41cb0ef41Sopenharmony_ciif (!common.hasCrypto) 51cb0ef41Sopenharmony_ci common.skip('missing crypto'); 61cb0ef41Sopenharmony_ciconst assert = require('assert'); 71cb0ef41Sopenharmony_ciconst net = require('net'); 81cb0ef41Sopenharmony_ciconst http2 = require('http2'); 91cb0ef41Sopenharmony_ci 101cb0ef41Sopenharmony_ciconst { 111cb0ef41Sopenharmony_ci HTTP2_HEADER_METHOD, 121cb0ef41Sopenharmony_ci HTTP2_HEADER_AUTHORITY, 131cb0ef41Sopenharmony_ci HTTP2_HEADER_SCHEME, 141cb0ef41Sopenharmony_ci HTTP2_HEADER_PATH, 151cb0ef41Sopenharmony_ci NGHTTP2_CONNECT_ERROR, 161cb0ef41Sopenharmony_ci NGHTTP2_REFUSED_STREAM 171cb0ef41Sopenharmony_ci} = http2.constants; 181cb0ef41Sopenharmony_ci 191cb0ef41Sopenharmony_ciconst server = net.createServer(common.mustCall((socket) => { 201cb0ef41Sopenharmony_ci let data = ''; 211cb0ef41Sopenharmony_ci socket.setEncoding('utf8'); 221cb0ef41Sopenharmony_ci socket.on('data', (chunk) => data += chunk); 231cb0ef41Sopenharmony_ci socket.on('end', common.mustCall(() => { 241cb0ef41Sopenharmony_ci assert.strictEqual(data, 'hello'); 251cb0ef41Sopenharmony_ci })); 261cb0ef41Sopenharmony_ci socket.on('close', common.mustCall()); 271cb0ef41Sopenharmony_ci socket.end('hello'); 281cb0ef41Sopenharmony_ci})); 291cb0ef41Sopenharmony_ci 301cb0ef41Sopenharmony_ciserver.listen(0, common.mustCall(() => { 311cb0ef41Sopenharmony_ci 321cb0ef41Sopenharmony_ci const port = server.address().port; 331cb0ef41Sopenharmony_ci 341cb0ef41Sopenharmony_ci const proxy = http2.createServer(); 351cb0ef41Sopenharmony_ci proxy.on('stream', common.mustCall((stream, headers) => { 361cb0ef41Sopenharmony_ci if (headers[HTTP2_HEADER_METHOD] !== 'CONNECT') { 371cb0ef41Sopenharmony_ci stream.close(NGHTTP2_REFUSED_STREAM); 381cb0ef41Sopenharmony_ci return; 391cb0ef41Sopenharmony_ci } 401cb0ef41Sopenharmony_ci const auth = new URL(`tcp://${headers[HTTP2_HEADER_AUTHORITY]}`); 411cb0ef41Sopenharmony_ci assert.strictEqual(auth.hostname, 'localhost'); 421cb0ef41Sopenharmony_ci assert.strictEqual(+auth.port, port); 431cb0ef41Sopenharmony_ci const socket = net.connect(auth.port, auth.hostname, () => { 441cb0ef41Sopenharmony_ci stream.respond(); 451cb0ef41Sopenharmony_ci socket.pipe(stream); 461cb0ef41Sopenharmony_ci stream.pipe(socket); 471cb0ef41Sopenharmony_ci }); 481cb0ef41Sopenharmony_ci socket.on('close', common.mustCall()); 491cb0ef41Sopenharmony_ci socket.on('error', (error) => { 501cb0ef41Sopenharmony_ci stream.close(NGHTTP2_CONNECT_ERROR); 511cb0ef41Sopenharmony_ci }); 521cb0ef41Sopenharmony_ci })); 531cb0ef41Sopenharmony_ci 541cb0ef41Sopenharmony_ci proxy.listen(0, () => { 551cb0ef41Sopenharmony_ci const client = http2.connect(`http://localhost:${proxy.address().port}`); 561cb0ef41Sopenharmony_ci 571cb0ef41Sopenharmony_ci // Confirm that :authority is required and :scheme & :path are forbidden 581cb0ef41Sopenharmony_ci assert.throws( 591cb0ef41Sopenharmony_ci () => client.request({ 601cb0ef41Sopenharmony_ci [HTTP2_HEADER_METHOD]: 'CONNECT' 611cb0ef41Sopenharmony_ci }), 621cb0ef41Sopenharmony_ci { 631cb0ef41Sopenharmony_ci code: 'ERR_HTTP2_CONNECT_AUTHORITY', 641cb0ef41Sopenharmony_ci message: ':authority header is required for CONNECT requests' 651cb0ef41Sopenharmony_ci } 661cb0ef41Sopenharmony_ci ); 671cb0ef41Sopenharmony_ci assert.throws( 681cb0ef41Sopenharmony_ci () => client.request({ 691cb0ef41Sopenharmony_ci [HTTP2_HEADER_METHOD]: 'CONNECT', 701cb0ef41Sopenharmony_ci [HTTP2_HEADER_AUTHORITY]: `localhost:${port}`, 711cb0ef41Sopenharmony_ci [HTTP2_HEADER_SCHEME]: 'http' 721cb0ef41Sopenharmony_ci }), 731cb0ef41Sopenharmony_ci { 741cb0ef41Sopenharmony_ci code: 'ERR_HTTP2_CONNECT_SCHEME', 751cb0ef41Sopenharmony_ci message: 'The :scheme header is forbidden for CONNECT requests' 761cb0ef41Sopenharmony_ci } 771cb0ef41Sopenharmony_ci ); 781cb0ef41Sopenharmony_ci assert.throws( 791cb0ef41Sopenharmony_ci () => client.request({ 801cb0ef41Sopenharmony_ci [HTTP2_HEADER_METHOD]: 'CONNECT', 811cb0ef41Sopenharmony_ci [HTTP2_HEADER_AUTHORITY]: `localhost:${port}`, 821cb0ef41Sopenharmony_ci [HTTP2_HEADER_PATH]: '/' 831cb0ef41Sopenharmony_ci }), 841cb0ef41Sopenharmony_ci { 851cb0ef41Sopenharmony_ci code: 'ERR_HTTP2_CONNECT_PATH', 861cb0ef41Sopenharmony_ci message: 'The :path header is forbidden for CONNECT requests' 871cb0ef41Sopenharmony_ci } 881cb0ef41Sopenharmony_ci ); 891cb0ef41Sopenharmony_ci 901cb0ef41Sopenharmony_ci // valid CONNECT request 911cb0ef41Sopenharmony_ci const req = client.request({ 921cb0ef41Sopenharmony_ci [HTTP2_HEADER_METHOD]: 'CONNECT', 931cb0ef41Sopenharmony_ci [HTTP2_HEADER_AUTHORITY]: `localhost:${port}`, 941cb0ef41Sopenharmony_ci }); 951cb0ef41Sopenharmony_ci 961cb0ef41Sopenharmony_ci req.on('response', common.mustCall()); 971cb0ef41Sopenharmony_ci let data = ''; 981cb0ef41Sopenharmony_ci req.setEncoding('utf8'); 991cb0ef41Sopenharmony_ci req.on('data', (chunk) => data += chunk); 1001cb0ef41Sopenharmony_ci req.on('end', common.mustCall(() => { 1011cb0ef41Sopenharmony_ci assert.strictEqual(data, 'hello'); 1021cb0ef41Sopenharmony_ci client.close(); 1031cb0ef41Sopenharmony_ci proxy.close(); 1041cb0ef41Sopenharmony_ci server.close(); 1051cb0ef41Sopenharmony_ci })); 1061cb0ef41Sopenharmony_ci req.end('hello'); 1071cb0ef41Sopenharmony_ci }); 1081cb0ef41Sopenharmony_ci})); 109