fix: deprecation warning with node 24
Massimo Melina committed
Feb 14, 2026 at 19:03 UTC
35ddebc36f971667e221fe687c3dddfb7dbee00d
2 files changed
+21
-7
src/outboundProxy.ts
+3
-3
@@ -1,13 +1,13 @@
1
import { configReady, defineConfig } from './config'
2
-import { parse } from 'node:url'
3
-import { httpStream, httpString } from './util-http'
2
+import { httpStream, httpString, parseHttpUrl } from './util-http'
3
import { reg } from './util-os'
4
import { IS_WINDOWS } from './const'
5
import { CFG, prefix } from './cross'
6
7
const outboundProxy = defineConfig(CFG.outbound_proxy, '', v => {
8
+ if (!v) return
9
try {
10
- parse(v) // just validate
10
+ parseHttpUrl(v) // just validate
11
httpStream.defaultProxy = v
12
if (!v || process.env.HFS_SKIP_PROXY_TEST) return
13
const test = 'https://google.com'
src/util-http.ts
+18
-4
@@ -1,12 +1,13 @@
1
// This file is part of HFS - Copyright 2021-2023, Massimo Melina <a@rejetto.com> - License https://www.gnu.org/licenses/gpl-3.0.txt
2
3
-import { parse } from 'node:url'
3
+import { urlToHttpOptions } from 'node:url'
4
import https from 'node:https'
5
import http, { IncomingMessage } from 'node:http'
6
import { Readable } from 'node:stream'
7
import _ from 'lodash'
8
import { text as stream2string, buffer } from 'node:stream/consumers'
9
import * as tls from 'node:tls'
10
+import { enforceStarting } from './cross'
11
export { stream2string }
12
13
export async function httpString(url: string, options?: XRequestOptions): Promise<string> {
@@ -47,13 +48,13 @@ export function httpStream(url: string, { body, proxy, jar, noRedirect, httpThro
48
if (!(body instanceof Readable))
49
options.headers['content-length'] ??= Buffer.byteLength(body)
50
}
50
- const { auth, ...parsed } = parse(url)
51
+ const { auth, ...parsed } = parseHttpUrl(url)
52
const hostJar = jar && (jar[parsed.hostname || ''] ||= {})
53
if (hostJar) {
54
options.headers.cookie = _.map(hostJar, (v,k) => `${k}=${v}; `).join('')
55
+ (options.headers.cookie || '') // preserve parameter
56
}
56
- const proxyParsed = proxy ? parse(proxy) : null
57
+ const proxyParsed = proxy ? parseHttpUrl(proxy) : null
58
Object.assign(options, _.pick(proxyParsed || parsed, ['hostname', 'port', 'path', 'protocol']))
59
if (auth) {
60
options.auth = auth
@@ -62,7 +63,7 @@ export function httpStream(url: string, { body, proxy, jar, noRedirect, httpThro
63
}
64
if (proxy) {
65
options.path = url // full url as path
65
- options.headers.host ??= parse(url).host || undefined // keep original host header
66
+ options.headers.host ??= parsed.host || undefined // keep original host header
67
}
68
// this needs the prefix "proxy-"
69
const proxyAuth = proxyParsed?.auth ? { 'proxy-authorization': `Basic ${Buffer.from(proxyParsed.auth, 'utf8').toString('base64')}` } : undefined
@@ -136,3 +137,16 @@ export function httpStream(url: string, { body, proxy, jar, noRedirect, httpThro
137
abort() { controller.abort() }
138
})
139
}
140
+
141
+// works the same way as the now deprecated url.parse()
142
+export function parseHttpUrl(url: string) {
143
+ const parsed = new URL(url)
144
+ const options = urlToHttpOptions(parsed)
145
+ const withoutHash = url.split('#', 1)[0]!
146
+ const authority = /^[a-z][a-z\d+.-]*:\/\/[^/?#]*/i.exec(withoutHash)?.[0]
147
+ return {
148
+ ...options,
149
+ host: parsed.host,
150
+ path: !authority ? '/' : enforceStarting('/', withoutHash.slice(authority.length)), // unresolved paths are useful in our tests
151
+ }
152
+}