Skip to content

Components

Creative controls for AI products. Play with them, then copy the React and Tailwind code.

Higher effort takes longer and uses more of your credit.

Lines 18–20
export default {
fetch: handle,
fetch: withRateLimit(handle),
};
Lines 4–5
const LIMIT = 10;
const LIMIT = 5;
const WINDOW_MS = 3_600_000;
Lines 42–44
if (hits >= LIMIT) {
return error(429, "Slow down");
}
0 of 3 reviewed

Add rate limiting to the invite form

  • fetch() routes POST /invite to handleInvite.

Invites are now limited to 5 an hour per IP, and all 12 tests pass. The first test run failed because I counted the hit after the insert.

src/lib/invites.tsts
import { error } from "./http";
const LIMIT = 5;
const WINDOW_MS = 60 * 60 * 1000;
/* One row per IP, per hour */
export async function checkRateLimit(db: D1Database, ip: string) {
const hour = Math.floor(Date.now() / WINDOW_MS);
const row = await db
.prepare("SELECT hits FROM rate_limits WHERE ip = ? AND hour = ?")
.bind(ip, hour)
.first<{ hits: number }>();
if ((row?.hits ?? 0) >= LIMIT) {
return error(429, "Slow down, try again in an hour");
}
await db
.prepare("INSERT INTO rate_limits VALUES (?, ?, 1) ON CONFLICT DO UPDATE SET hits = hits + 1")
.bind(ip, hour)
.run();
return null;
}

Add rate limiting to invites

  1. runningRead invite formread0.0s

    src/worker.ts, 142 lines

  2. pendingFind submit handlergrep

    handleInvite in src/lib/invites.ts

  3. pendingAdd rate_limits tableD1

    CREATE TABLE rate_limits (ip, hits)

  4. pendingLimit invites per IPedit

    src/lib/invites.ts +24 -3

  5. pendingRun testsbash

    pnpm test, 12 files

  6. pendingDeploy previewwrangler

    Cloudflare Workers, preview env

Step 1 of 6 · 0.0s · 0 calls