UNPKG

express-useragent

Version:

JS Library & ExpressJS user-agent middleware exposing

72 lines (59 loc) 2.37 kB
import type { NextFunction, Request, Response } from 'express'; import type { IncomingHttpHeaders } from 'http'; import { UserAgent } from './express-useragent'; import type { AgentDetails } from './express-useragent'; export type { AgentDetails, HeadersLike, ClientHints, ClientHintBrand } from './express-useragent'; export { UserAgent } from './express-useragent'; // Declaration merging for Express Request // This allows TypeScript users to access req.useragent without type errors declare global { // eslint-disable-next-line @typescript-eslint/no-namespace namespace Express { interface Request { useragent?: AgentDetails; } } } export interface UserAgentAugmentedRequest extends Request { useragent?: ReturnType<UserAgent['parse']>; headers: IncomingHttpHeaders & Record<string, string | string[] | undefined>; } export const useragent = new UserAgent(); export type UserAgentMiddleware = (req: Request, res: Response, next: NextFunction) => void; export const express = (): UserAgentMiddleware => { return (req: UserAgentAugmentedRequest, res: Response, next: NextFunction) => { const headers = req.headers || {}; const resolveHeader = (value: string | string[] | undefined): string => { if (Array.isArray(value)) { return value.join(' '); } return value ?? ''; }; const uaHeader = resolveHeader(headers['user-agent']); const ucHeader = resolveHeader(headers['x-ucbrowser-ua']); const source = (ucHeader || uaHeader || 'unknown').trim() || 'unknown'; const parser = new UserAgent().hydrateFromHeaders(source, headers); parser.testNginxGeoIP(headers); // middleware duplicates tests to match legacy behaviour parser.testBot(); parser.testMobile(); parser.testAndroidTablet(); parser.testTablet(); parser.testCompatibilityMode(); parser.testSilk(); parser.testKindleFire(); parser.testWechat(); req.useragent = parser.Agent; res.locals.useragent = parser.Agent; next(); }; }; export const useragentMiddleware = express; // Export a default instance for easier usage // Also attach the express middleware and UserAgent class to the default export // to maintain compatibility with documented ESM usage (issue #177) const defaultExport = Object.assign(useragent, { express, UserAgent, }); export default defaultExport;