express-useragent
Version:
JS Library & ExpressJS user-agent middleware exposing
166 lines (162 loc) • 5.3 kB
TypeScript
import { Request, Response, NextFunction } from 'express';
import { IncomingHttpHeaders } from 'http';
/**
* Represents a single brand entry from User-Agent Client Hints
* @see https://wicg.github.io/ua-client-hints/
*/
interface ClientHintBrand {
brand: string;
version: string;
}
/**
* Parsed User-Agent Client Hints data from HTTP headers
* Maps to the NavigatorUAData interface exposed by browsers
*/
interface ClientHints {
brands: ClientHintBrand[];
mobile: boolean;
platform: string;
platformVersion: string;
architecture: string;
bitness: string;
model: string;
fullVersionList: ClientHintBrand[];
}
interface AgentDetails extends Record<string, unknown> {
isYaBrowser: boolean;
isAuthoritative: boolean;
isMobile: boolean;
isMobileNative: boolean;
isTablet: boolean;
isiPad: boolean;
isiPod: boolean;
isiPhone: boolean;
isiPhoneNative: boolean;
isAndroid: boolean;
isAndroidNative: boolean;
isBlackberry: boolean;
isOpera: boolean;
isIE: boolean;
isEdge: boolean;
isIECompatibilityMode: boolean;
isSafari: boolean;
isFirefox: boolean;
isWebkit: boolean;
isChrome: boolean;
isKonqueror: boolean;
isOmniWeb: boolean;
isSeaMonkey: boolean;
isFlock: boolean;
isAmaya: boolean;
isPhantomJS: boolean;
isEpiphany: boolean;
isDesktop: boolean;
isWindows: boolean;
isLinux: boolean;
isLinux64: boolean;
isMac: boolean;
isChromeOS: boolean;
isBada: boolean;
isSamsung: boolean;
isRaspberry: boolean;
isBot: boolean;
botName: string;
isCurl: boolean;
isAndroidTablet: boolean;
isWinJs: boolean;
isKindleFire: boolean;
isSilk: boolean;
isCaptive: boolean;
isSmartTV: boolean;
isUC: boolean;
isFacebook: boolean;
isAlamoFire: boolean;
isElectron: boolean;
silkAccelerated: boolean;
browser: string;
version: string | number;
os: string;
platform: string;
geoIp: Record<string, string | string[]>;
source: string;
isWechat: boolean;
isWindowsPhone: boolean;
electronVersion: string;
SilkAccelerated?: boolean;
/** DuckDuckGo browser detected via Client Hints brand or WebKit UA pattern */
isDuckDuckGo: boolean;
/** Parsed User-Agent Client Hints when available */
clientHints: ClientHints | null;
}
type HeadersLike = Partial<Record<string, string | string[] | undefined>>;
declare class UserAgent {
private readonly versions;
private readonly browsers;
private readonly os;
private readonly platform;
Agent: AgentDetails;
constructor();
reset(): this;
testNginxGeoIP(headers: HeadersLike | IncomingHttpHeaders): this;
/** Maximum header length to process (prevents DoS from oversized headers) */
private static readonly MAX_HEADER_LENGTH;
/** Maximum number of brands to parse from a brand list */
private static readonly MAX_BRAND_COUNT;
/**
* Parse User-Agent Client Hints from HTTP headers
* @see https://wicg.github.io/ua-client-hints/
*/
parseClientHints(headers: HeadersLike | IncomingHttpHeaders): ClientHints | null;
/**
* Test for DuckDuckGo browser using both Client Hints and UA string patterns
* - Chromium platforms (Android, Windows): Sec-CH-UA brand "DuckDuckGo"
* - WebKit platforms (iOS, macOS): UA string ends with " Ddg/X.Y.Z"
*/
testDuckDuckGo(): void;
testBot(): void;
testSmartTV(): void;
testMobile(): void;
testAndroidTablet(): void;
testTablet(): void;
testCompatibilityMode(): void;
testSilk(): string | false;
testKindleFire(): string | false;
testCaptiveNetwork(): string | false;
testWebkit(): void;
testWechat(): void;
parse(source: string): AgentDetails;
/**
* Hydrate agent from UA string and HTTP headers (including Client Hints)
* This method should be preferred when headers are available as it enables
* detection of browsers that use Client Hints (e.g., DuckDuckGo on Chromium)
*/
hydrateFromHeaders(source: string, headers: HeadersLike | IncomingHttpHeaders): this;
hydrate(source: string): this;
private getBrowser;
private getBrowserVersion;
private getWechatVersion;
private getDuckDuckGoVersion;
private getElectronVersion;
private getOS;
private getPlatform;
}
declare global {
namespace Express {
interface Request {
useragent?: AgentDetails;
}
}
}
interface UserAgentAugmentedRequest extends Request {
useragent?: ReturnType<UserAgent['parse']>;
headers: IncomingHttpHeaders & Record<string, string | string[] | undefined>;
}
declare const useragent: UserAgent;
type UserAgentMiddleware = (req: Request, res: Response, next: NextFunction) => void;
declare const express: () => UserAgentMiddleware;
declare const useragentMiddleware: () => UserAgentMiddleware;
declare const defaultExport: UserAgent & {
express: () => UserAgentMiddleware;
UserAgent: typeof UserAgent;
};
export { type AgentDetails, type ClientHintBrand, type ClientHints, type HeadersLike, UserAgent, type UserAgentAugmentedRequest, type UserAgentMiddleware, defaultExport as default, express, useragent, useragentMiddleware };