http requests will by default include user-agent
Massimo Melina committed
Apr 27, 2026 at 19:39 UTC
3449415b03965b67b69c630da8620e751a61780b
2 files changed
+8
-2
src/index.ts
+2
-1
@@ -19,7 +19,7 @@ import { adminApis } from './adminApis'
19
import { defineConfig, Version } from './config'
20
import { ok } from 'assert'
21
import _ from 'lodash'
22
-import { randomId } from './misc'
22
+import { httpStream, randomId } from './misc'
23
import { selfCheckMiddleware } from './selfCheck'
24
import { acmeMiddleware } from './acme'
25
import './geo'
@@ -37,6 +37,7 @@ if (new Version(process.versions.node).olderThan('18.15.0')) {
37
}
38
39
process.title = 'HFS ' + VERSION
40
+httpStream.defaultUA = 'HFS'
41
const keys = process.env.COOKIE_SIGN_KEYS?.split(',')
42
|| [randomId(30)] // randomness at start gives some extra security, btu also invalidates existing sessions
43
export const app = new Koa({ keys })
src/util-http.ts
+6
-1
@@ -32,13 +32,18 @@ export interface XRequestOptions extends https.RequestOptions {
32
httpThrow?: boolean
33
}
34
35
-export declare namespace httpStream { let defaultProxy: string | undefined }
35
+export declare namespace httpStream {
36
+ let defaultProxy: string | undefined
37
+ let defaultUA: string | undefined
38
+}
39
export function httpStream(url: string, { body, proxy, jar, noRedirect, httpThrow=true, ...options }: XRequestOptions ={}, redirected: string[]=[]) {
40
const controller = new AbortController()
41
options.signal ??= controller.signal
42
return Object.assign(new Promise<IncomingMessage>(async (resolve, reject) => {
43
proxy ??= httpStream.defaultProxy
44
options.headers ??= {}
45
+ if (httpStream.defaultUA && !Object.keys(options.headers).find(k => k.toLowerCase() === 'user-agent'))
46
+ options.headers['user-agent'] = httpStream.defaultUA
47
if (body) {
48
options.method ||= 'POST'
49
if (_.isPlainObject(body)) {