Skip to content

Commit bb0c9e8

Browse files
committed
http: add CONNECT method handling for default Host header when using proxy
1 parent bfb2fa7 commit bb0c9e8

2 files changed

Lines changed: 52 additions & 11 deletions

File tree

lib/_http_client.js

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -375,18 +375,22 @@ function ClientRequest(input, options, cb) {
375375
if (host && !this.getHeader('host') && setHost) {
376376
let hostHeader = host;
377377

378-
// For the Host header, ensure that IPv6 addresses are enclosed
379-
// in square brackets, as defined by URI formatting
380-
// https://tools.ietf.org/html/rfc3986#section-3.2.2
381-
const posColon = hostHeader.indexOf(':');
382-
if (posColon !== -1 &&
383-
hostHeader.includes(':', posColon + 1) &&
384-
hostHeader.charCodeAt(0) !== 91/* '[' */) {
385-
hostHeader = `[${hostHeader}]`;
386-
}
378+
if (method === 'CONNECT' && options.path) {
379+
hostHeader = String(this.path);
380+
} else {
381+
// For the Host header, ensure that IPv6 addresses are enclosed
382+
// in square brackets, as defined by URI formatting
383+
// https://tools.ietf.org/html/rfc3986#section-3.2.2
384+
const posColon = hostHeader.indexOf(':');
385+
if (posColon !== -1 &&
386+
hostHeader.includes(':', posColon + 1) &&
387+
hostHeader.charCodeAt(0) !== 91/* '[' */) {
388+
hostHeader = `[${hostHeader}]`;
389+
}
387390

388-
if (port && +port !== defaultPort) {
389-
hostHeader += ':' + port;
391+
if (port && +port !== defaultPort) {
392+
hostHeader += ':' + port;
393+
}
390394
}
391395
this.setHeader('Host', hostHeader);
392396
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const assert = require('assert');
5+
const http = require('http');
6+
const net = require('net');
7+
8+
const target = 'target.example.com:443';
9+
10+
const server = net.createServer(common.mustCall((socket) => {
11+
socket.once('data', common.mustCall((data) => {
12+
const rawRequest = data.toString();
13+
const requestLines = rawRequest.split('\r\n');
14+
15+
assert.strictEqual(requestLines[0], `CONNECT ${target} HTTP/1.1`);
16+
assert(requestLines.includes(`Host: ${target}`));
17+
18+
socket.end('HTTP/1.1 200 Connection established\r\n\r\n');
19+
}));
20+
}));
21+
22+
server.listen(0, common.localhostIPv4, common.mustCall(() => {
23+
const req = http.request({
24+
host: common.localhostIPv4,
25+
port: server.address().port,
26+
method: 'CONNECT',
27+
path: target,
28+
}, common.mustNotCall());
29+
30+
req.on('connect', common.mustCall((res, socket) => {
31+
assert.strictEqual(res.statusCode, 200);
32+
socket.destroy();
33+
server.close();
34+
}));
35+
36+
req.end();
37+
}));

0 commit comments

Comments
 (0)