From c310fb257bbf1096225c802a411cd068a960eb59 Mon Sep 17 00:00:00 2001 From: RoomWithOutRoof <166608075+Jah-yee@users.noreply.github.com> Date: Tue, 14 Apr 2026 06:16:46 +0800 Subject: [PATCH] Normalize usernames to lowercase in all API endpoints GitHub usernames are case-insensitive, but the API endpoints did not normalize casing. This caused cache fragmentation: - fetchUserContributions already lowercases for its cache key - The frontend (app.js) already lowercases all input - But SVG/PNG/OG cache keys used raw casing from query params So ?users=Karpathy and ?users=karpathy would generate separate cache entries for identical data, wasting KV storage and causing redundant SVG renders. Normalize to lowercase in parseChartParams, handleApi, and handlePageWithOgTags to match the existing behavior in github.ts and the frontend. Made-with: Cursor --- src/index.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/index.ts b/src/index.ts index 3ffdd1c..d1140ff 100644 --- a/src/index.ts +++ b/src/index.ts @@ -49,13 +49,13 @@ function parseChartParams(url: URL) { const usernames = usersParam .split(",") - .map((u) => u.trim()) + .map((u) => u.trim().toLowerCase()) .filter(Boolean) .slice(0, MAX_USERS); if (usernames.length === 0) return { error: "No usernames provided" }; - return { usernames, range: rangeParam as TimeRange, selfUser, theme }; + return { usernames, range: rangeParam as TimeRange, selfUser: selfUser.toLowerCase(), theme }; } /** Generate SVG string for given params (shared by /api/svg and /api/png). */ @@ -204,7 +204,7 @@ async function handleApi( const usernames = usersParam .split(",") - .map((u) => u.trim()) + .map((u) => u.trim().toLowerCase()) .filter(Boolean) .slice(0, MAX_USERS); @@ -238,7 +238,7 @@ async function handlePageWithOgTags( const url = new URL(request.url); // Parse user params from either new or legacy format - const selfUser = url.searchParams.get("user") || ""; + const selfUser = (url.searchParams.get("user") || "").toLowerCase(); const targetsParam = url.searchParams.get("targets") || ""; const usersParam = url.searchParams.get("users") || ""; const range = url.searchParams.get("range") || "3m"; @@ -247,10 +247,10 @@ async function handlePageWithOgTags( let targets: string[]; if (targetsParam) { - targets = targetsParam.split(",").map(u => u.trim()).filter(Boolean); + targets = targetsParam.split(",").map(u => u.trim().toLowerCase()).filter(Boolean); allUsers = [selfUser, ...targets].filter(Boolean); } else if (usersParam) { - allUsers = usersParam.split(",").map(u => u.trim()).filter(Boolean); + allUsers = usersParam.split(",").map(u => u.trim().toLowerCase()).filter(Boolean); targets = selfUser ? allUsers.filter(u => u !== selfUser) : allUsers; } else { // No chart params — serve static page as-is