Skip to content

Commit c7cb2ba

Browse files
committed
fix: ignoring user-agent header in async detection
1 parent ae2c5f5 commit c7cb2ba

File tree

2 files changed

+33
-7
lines changed

2 files changed

+33
-7
lines changed

src/index.ts

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -442,9 +442,11 @@ export function getNodeVersion() {
442442
export async function asyncDetect(options?: {
443443
userAgent?: string
444444
hints?: UserAgentDataHints[]
445-
httpHeaders?: Record<string, string | undefined>
445+
httpHeaders?: RequestHeaders
446446
}) {
447-
const info = detect(options?.userAgent)
447+
const info = detect(
448+
options?.userAgent ?? options?.httpHeaders?.['user-agent'] ?? options?.httpHeaders?.['User-Agent'],
449+
)
448450
if (!info)
449451
return info
450452

@@ -517,6 +519,18 @@ export async function lookupClientUserAgentHints(hints?: UserAgentDataHints[]) {
517519
return await userAgentData.getHighEntropyValues(hints)
518520
}
519521

522+
type _HTTPHeaderName = 'Sec-CH-UA' | 'Sec-CH-UA-Mobile' | 'Sec-CH-UA-Platform' | 'Sec-CH-UA-Arch' | 'Sec-CH-UA-Bitness' | 'Sec-CH-UA-Model' | 'Sec-CH-UA-Platform-Version' | 'Sec-CH-UA-Full-Version-List'
523+
524+
export type HTTPHeaderName =
525+
| _HTTPHeaderName
526+
| Lowercase<_HTTPHeaderName>
527+
// eslint-disable-next-line @typescript-eslint/ban-types
528+
| (string & {})
529+
530+
export type RequestHeaders = Partial<
531+
Record<HTTPHeaderName, string | undefined>
532+
>
533+
520534
const uaAgentHints: Record<string, keyof UserAgentDataInfo> = {
521535
'Sec-CH-UA': 'brands',
522536
'Sec-CH-UA-Mobile': 'mobile',
@@ -528,7 +542,7 @@ const uaAgentHints: Record<string, keyof UserAgentDataInfo> = {
528542
'Sec-CH-UA-Full-Version-List': 'fullVersionList',
529543
}
530544

531-
const serverAcceptCHHeaders: Record<UserAgentDataHints, string> = {
545+
const serverAcceptCHHeaders: Record<UserAgentDataHints, HTTPHeaderName> = {
532546
architecture: 'Sec-CH-UA-Arch',
533547
bitness: 'Sec-CH-UA-Bitness',
534548
model: 'Sec-CH-UA-Model',
@@ -539,9 +553,9 @@ const serverAcceptCHHeaders: Record<UserAgentDataHints, string> = {
539553
/**
540554
* @see https://github.com/WICG/ua-client-hints
541555
*/
542-
export function lookupServerUserAgentHints(httpHeaders: Record<string, string | undefined>) {
556+
export function lookupServerUserAgentHints(httpHeaders: RequestHeaders) {
543557
return Object.entries(uaAgentHints).reduce((acc, [header, key]) => {
544-
const value = httpHeaders[header]
558+
const value = httpHeaders[header] ?? httpHeaders[header.toLowerCase()]
545559
if (value && value.length) {
546560
if (key === 'brands' || key === 'fullVersionList') {
547561
const parts = value.split(',')
@@ -582,7 +596,7 @@ export function serverResponseHeadersForUserAgentHints(
582596
.filter(([key]) => hints.includes(key as UserAgentDataHints))
583597
.map(([_, header]) => header)
584598

585-
return headers.length ? <Record<string, string>>{ 'Accept-CH': headers.join(', ') } : undefined
599+
return headers.length ? <RequestHeaders>{ 'Accept-CH': headers.join(', ') } : undefined
586600
}
587601

588602
export function getServerVersion() {

test/server.test.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,21 @@ describe('Server Detection', () => {
9999
'Sec-CH-UA-Mobile': '?0',
100100
})?.mobile).toBe(false)
101101
})
102-
test('Windows 11 server detection', async () => {
102+
test('Windows 11 server detection: userAgent option', async () => {
103103
const info = await asyncDetect({
104104
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36',
105+
httpHeaders: {
106+
'Sec-CH-UA-Platform': '"Windows"',
107+
'Sec-CH-UA-Platform-Version': '13.0.0',
108+
},
109+
})
110+
expect(info).toBeDefined()
111+
expect(info?.type).toBe('browser')
112+
expect(info?.name).toBe('chrome')
113+
expect(info?.os).toBe('Windows 11')
114+
})
115+
test('Windows 11 server detection: User-Agent header', async () => {
116+
const info = await asyncDetect({
105117
httpHeaders: {
106118
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36',
107119
'Sec-CH-UA-Platform': '"Windows"',

0 commit comments

Comments
 (0)