chadtmiller.com/pds.js
An atproto PDS in JavaScript, for Cloudflare Workers and Node
0
0
/**
* Turn a User-Agent string into a short "Browser · OS" label, so two sessions
* of the same app can be told apart. Falls back to a trimmed raw value when it
* can't be parsed, and null when there's nothing to show.
* @param {string|null|undefined} ua
* @returns {string|null}
*/
export function formatUserAgent(ua) {
if (!ua) return null;
const browser = /\bEdg\//.test(ua)
? 'Edge'
: /\bOPR\/|\bOpera\b/.test(ua)
? 'Opera'
: /\bChrome\//.test(ua)
? 'Chrome'
: /\bFirefox\//.test(ua)
? 'Firefox'
: /\bVersion\/.*\bSafari\//.test(ua)
? 'Safari'
: null;
const os = /\bAndroid\b/.test(ua)
? 'Android'
: /\biPhone\b/.test(ua)
? 'iPhone'
: /\biPad\b/.test(ua)
? 'iPad'
: /\bMac OS X\b|\bMacintosh\b/.test(ua)
? 'macOS'
: /\bWindows\b/.test(ua)
? 'Windows'
: /\bLinux\b/.test(ua)
? 'Linux'
: null;
if (browser && os) return `${browser} · ${os}`;
if (browser) return browser;
// Not a browser: name the HTTP client behind the login (a script, a mobile
// app's networking library) rather than showing a raw token, so it reads as
// cleanly as a browser does. Unknown agents keep the trimmed raw fallback.
const client = detectClient(ua);
if (client) return client;
if (os) return os;
return ua.length > 40 ? `${ua.slice(0, 40)}…` : ua;
}
/**
* The common non-browser HTTP clients, matched on their User-Agent token.
* @param {string} ua
* @returns {string|null}
*/
function detectClient(ua) {
if (/\bcurl\//i.test(ua)) return 'curl';
if (/\bWget\b/i.test(ua)) return 'Wget';
if (/\bokhttp\//i.test(ua)) return 'OkHttp';
if (/\bpython-requests\/|\bPython-urllib\/|\bPython\//i.test(ua))
return 'Python';
if (/\bGo-http-client\//i.test(ua)) return 'Go';
if (/\baxios\//i.test(ua)) return 'axios';
if (/\bundici\b|\bnode-fetch\b|^node\b/i.test(ua)) return 'Node.js';
if (/\bDeno\//i.test(ua)) return 'Deno';
if (/\bBun\//i.test(ua)) return 'Bun';
if (/\bPostmanRuntime\//i.test(ua)) return 'Postman';
return null;
}