Skip to content

Commit 2e4783a

Browse files
committed
fix: preserve non-default port in HTTP Host header
1 parent 2ee6779 commit 2e4783a

7 files changed

Lines changed: 54 additions & 14 deletions

File tree

src/frontEnd/src/utils/httpRequestParser/formatters/httpFormatter.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,10 @@ export function toRawHttpRequest(request: ParsedHttpRequest): string {
3232
// 请求行
3333
lines.push(`${request.method} ${request.path} HTTP/1.1`)
3434

35-
// 确保Host头存在
35+
// 确保Host头存在(使用带端口的host,如存在非默认端口)
3636
const headers = { ...request.headers }
3737
if (!headers['Host'] && !headers['host']) {
38-
headers['Host'] = request.host
38+
headers['Host'] = request.hostWithPort || request.host
3939
}
4040

4141
// Headers

src/frontEnd/src/utils/httpRequestParser/parsers/curlParser.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,14 @@ function parseCurlWithLib(normalizedInput: string): ParsedHttpRequest | null {
7373
// 库在解析包含引号的 body 时有 bug,需要自己重新提取
7474
const body = extractBody(normalizedInput)
7575

76-
const { host, path, protocol } = parseUrl(result.url)
76+
const { host, hostWithPort, port, path, protocol } = parseUrl(result.url)
7777

7878
return {
7979
method,
8080
url: result.url,
8181
host,
82+
hostWithPort,
83+
port,
8284
path,
8385
headers,
8486
body,

src/frontEnd/src/utils/httpRequestParser/parsers/fetchParser.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,12 +311,14 @@ export function parseFetch(input: string): ParsedHttpRequest | null {
311311
body = extractBody(optionsStr)
312312
}
313313

314-
const { host, path, protocol } = parseUrl(url)
314+
const { host, hostWithPort, port, path, protocol } = parseUrl(url)
315315

316316
return {
317317
method,
318318
url,
319319
host,
320+
hostWithPort,
321+
port,
320322
path,
321323
headers,
322324
body,

src/frontEnd/src/utils/httpRequestParser/parsers/powershellParser.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,12 +191,14 @@ export function parsePowerShell(input: string): ParsedHttpRequest | null {
191191
// 如果有 body 但没有明确指定方法,默认为 POST
192192
const finalMethod = (body && !hasExplicitMethod) ? 'POST' : method
193193

194-
const { host, path, protocol } = parseUrl(url)
194+
const { host, hostWithPort, port, path, protocol } = parseUrl(url)
195195

196196
return {
197197
method: finalMethod,
198198
url,
199199
host,
200+
hostWithPort,
201+
port,
200202
path,
201203
headers,
202204
body,

src/frontEnd/src/utils/httpRequestParser/parsers/rawHttpParser.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,19 +128,26 @@ export function parseRawHttp(input: string): ParsedHttpRequest | null {
128128
body = lines.slice(bodyStartIndex).join('\n')
129129
}
130130

131-
// 从Host header提取host
132-
const host = extractHost(headers)
131+
// 从Host header提取host(可能包含端口)
132+
const hostWithPort = extractHost(headers)
133+
134+
// 分离host和端口
135+
const hostParts = hostWithPort.split(':')
136+
const host = hostParts[0] || ''
137+
const port = hostParts[1] || ''
133138

134139
// 协议默认http(无法从原始报文中确定)
135140
const protocol = 'http'
136141

137142
// 构建URL
138-
const url = host ? `${protocol}://${host}${path}` : path
143+
const url = host ? `${protocol}://${hostWithPort}${path}` : path
139144

140145
return {
141146
method,
142147
url,
143148
host,
149+
hostWithPort,
150+
port,
144151
path,
145152
headers,
146153
body,

src/frontEnd/src/utils/httpRequestParser/types.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ export interface ParsedHttpRequest {
1414
url: string
1515
/** 主机名(不含端口) */
1616
host: string
17+
/** 主机名(含端口,如存在非默认端口) */
18+
hostWithPort: string
19+
/** 端口号 */
20+
port: string
1721
/** 请求路径(包含查询字符串和hash) */
1822
path: string
1923
/** HTTP头部 */

src/frontEnd/src/utils/httpRequestParser/urlParser.ts

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
export interface UrlParseResult {
88
/** 主机名(不含端口) */
99
host: string
10+
/** 主机名(含端口,如存在非默认端口) */
11+
hostWithPort: string
12+
/** 端口号 */
13+
port: string
1014
/** 请求路径 */
1115
path: string
1216
/** 协议 */
@@ -25,7 +29,7 @@ export interface UrlParseResult {
2529
*/
2630
export function parseUrl(urlStr: string): UrlParseResult {
2731
// 默认返回值
28-
const defaultResult: UrlParseResult = { host: '', path: '/', protocol: 'http' }
32+
const defaultResult: UrlParseResult = { host: '', hostWithPort: '', port: '', path: '/', protocol: 'http' }
2933

3034
if (!urlStr || typeof urlStr !== 'string') {
3135
return defaultResult
@@ -36,8 +40,14 @@ export function parseUrl(urlStr: string): UrlParseResult {
3640
const url = new URL(urlStr)
3741
const path = url.pathname + url.search + url.hash
3842

43+
// 判断是否为默认端口
44+
const isDefaultPort = (url.protocol === 'http:' && url.port === '80') ||
45+
(url.protocol === 'https:' && url.port === '443')
46+
3947
return {
40-
host: url.hostname, // 使用 hostname 而不是 host,不包含端口
48+
host: url.hostname,
49+
hostWithPort: isDefaultPort ? url.hostname : (url.host || url.hostname),
50+
port: url.port || (url.protocol === 'https:' ? '443' : '80'),
4151
path: path || '/',
4252
protocol: url.protocol.replace(':', '')
4353
}
@@ -51,16 +61,29 @@ export function parseUrl(urlStr: string): UrlParseResult {
5161
* 手动解析URL(当原生URL API失败时的备选方案)
5262
*/
5363
function parseUrlManually(urlStr: string): UrlParseResult | null {
54-
const match = urlStr.match(/^(https?):\/\/([^\/:]+)(?::\d+)?(\/.*)?$/)
64+
const match = urlStr.match(/^(https?):\/\/([^\/:]+)(?::(\d+))?(\/.*)?$/)
5565

5666
if (!match) {
5767
return null
5868
}
5969

70+
const protocol = match[1] || 'http'
71+
const hostname = match[2] || ''
72+
const port = match[3]
73+
const path = match[4] || '/'
74+
75+
// 判断是否为默认端口
76+
const isDefaultPort = (protocol === 'http' && port === '80') ||
77+
(protocol === 'https' && port === '443')
78+
79+
const hostWithPort = port && !isDefaultPort ? `${hostname}:${port}` : hostname
80+
6081
return {
61-
protocol: match[1] || 'http',
62-
host: match[2] || '', // 只取主机名,不含端口
63-
path: match[3] || '/'
82+
protocol,
83+
host: hostname,
84+
hostWithPort,
85+
port: port || (protocol === 'https' ? '443' : '80'),
86+
path
6487
}
6588
}
6689

0 commit comments

Comments
 (0)