Skip to content

Commit 2982208

Browse files
committed
Fix handling default ports from URL
Close #1488
1 parent 67febcc commit 2982208

3 files changed

Lines changed: 54 additions & 10 deletions

File tree

src/http.ts

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,42 @@ export interface IAttachment {
2323
body: NodeJS.ReadableStream;
2424
}
2525

26-
function getPortFromUrl(url: URL): string {
27-
if (url.port) return url.port;
28-
if (url.protocol.toLowerCase() === 'https:') return '443';
29-
if (url.protocol.toLowerCase() === 'http:') return '80';
30-
return '';
26+
// The URL API normalizes away default ports (:80 on http, :443 on https),
27+
// so parse the port from the raw URL string to preserve ports.
28+
function getPortFromUrl(url: string): string {
29+
// Capture the authority section (everything between :// and the first /?#)
30+
const authorityMatch = /^[a-z][a-z0-9+.-]*:\/\/([^/?#]+)/i.exec(url);
31+
if (!authorityMatch) {
32+
return '';
33+
}
34+
35+
const hostPort = authorityMatch[1];
36+
37+
// IPv6 address: [::1] or [::1]:port
38+
if (hostPort.startsWith('[')) {
39+
const bracketEnd = hostPort.indexOf(']');
40+
if (bracketEnd !== -1 && hostPort[bracketEnd + 1] === ':') {
41+
const port = hostPort.slice(bracketEnd + 2);
42+
return /^\d+$/.test(port) ? port : '';
43+
}
44+
return '';
45+
}
46+
47+
// IPv4 / hostname: host or host:port
48+
const colonIndex = hostPort.lastIndexOf(':');
49+
if (colonIndex === -1) {
50+
return '';
51+
}
52+
const port = hostPort.slice(colonIndex + 1);
53+
return /^\d+$/.test(port) ? port : '';
54+
}
55+
56+
// Add brackets to IPv6 addresses
57+
function bracketIPv6(hostname: string): string {
58+
if (hostname.startsWith('[') || hostname.indexOf(':') === -1) {
59+
return hostname;
60+
}
61+
return `[${hostname}]`;
3162
}
3263

3364
/**
@@ -59,16 +90,15 @@ export class HttpClient implements IHttpClient {
5990
const curl = new URL(rurl);
6091
const method = data ? 'POST' : 'GET';
6192

62-
const host = curl.hostname;
63-
64-
const port = getPortFromUrl(curl);
93+
const port = getPortFromUrl(rurl);
94+
const host = port ? `${bracketIPv6(curl.hostname)}:${port}` : curl.host || curl.hostname;
6595
const headers: IHeaders = {
6696
'User-Agent': 'node-soap/' + version,
6797
'Accept': 'text/html,application/xhtml+xml,application/xml,text/xml;q=0.9,*/*;q=0.8',
6898
'Accept-Encoding': 'none',
6999
'Accept-Charset': 'utf-8',
70100
...(exoptions.forever && { Connection: 'keep-alive' }),
71-
'Host': host + (port ? ':' + port : ''),
101+
'Host': host,
72102
};
73103
const mergeOptions = ['headers'];
74104

test/client-customHttp-test.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,3 +116,16 @@ it('should allow customization of httpClient and the wsdl file download should p
116116
done();
117117
});
118118
});
119+
120+
it('should not append default ports to Host header', function () {
121+
var client = new httpClient();
122+
123+
var httpsReq = client.buildRequest('https://example.com/service?wsdl', null);
124+
assert.equal(httpsReq.headers.Host, 'example.com');
125+
126+
var httpReq = client.buildRequest('http://example.com/service?wsdl', null);
127+
assert.equal(httpReq.headers.Host, 'example.com');
128+
129+
var explicitPortReq = client.buildRequest('https://example.com:8443/service?wsdl', null);
130+
assert.equal(explicitPortReq.headers.Host, 'example.com:8443');
131+
});

tsconfig.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
"sourceMap": true,
1010
"declaration": true,
1111
"stripInternal": true,
12-
"skipLibCheck": true
12+
"skipLibCheck": true,
13+
"types": ["node"]
1314
},
1415
"include": ["src", "./eslint.config.mjs"],
1516
"exclude": ["node_modules"]

0 commit comments

Comments
 (0)