~ knotless Search/
↑↓ move↵ open⇧↵ all results

chadtmiller.com/pds.js

An atproto PDS in JavaScript, for Cloudflare Workers and Node

0
0
main
68 lines · 2.1 KB Raw History
/**
 * 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;
}