diff options
| author | Adam Soltys <[email protected]> | 2026-07-10 22:56:12 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-07-10 22:56:12 -0700 |
| commit | fa029437a162088ff79f36872110fa4087011530 (patch) | |
| tree | 2d7f8a0e7e19962511bfea2644ef0415d854807d | |
| parent | 4d97101726276543384c10f11a72a70f99336afb (diff) | |
| download | coinos-server-fa029437a162088ff79f36872110fa4087011530.tar.gz coinos-server-fa029437a162088ff79f36872110fa4087011530.zip | |
invoices: rate-limit invoice create and update per IP
Add a per-IP rate limit (30/10s) to POST /invoice and POST /invoice/:id,
matching the existing GET /invoice/:id limit, to throttle automated
invoice-creation floods.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
| -rw-r--r-- | index.ts | 4 |
1 files changed, 2 insertions, 2 deletions
@@ -48,8 +48,8 @@ app.get("/locations", locations.list); app.get("/invoice/:id", { config: { rateLimit: { max: 30, timeWindow: 10000, keyGenerator: (req) => { const ip = (req.headers["cf-connecting-ip"] as string) || req.ip; const token = (req.headers.authorization || "").slice(0, 50); return token ? `invoice:${token}` : `invoice:${ip}`; } } } }, invoices.get); app.get("/invoices", auth, invoices.list); -app.post("/invoice", optional, invoices.create); -app.post("/invoice/:id", optional, invoices.update); +app.post("/invoice", { ...optional, config: { rateLimit: { max: 30, timeWindow: 10000, keyGenerator: (req) => `invoicecreate:${(req.headers["cf-connecting-ip"] as string) || req.ip}` } } }, invoices.create); +app.post("/invoice/:id", { ...optional, config: { rateLimit: { max: 30, timeWindow: 10000, keyGenerator: (req) => `invoiceupdate:${(req.headers["cf-connecting-ip"] as string) || req.ip}` } } }, invoices.update); app.post("/sign", auth, invoices.sign); app.get("/assetlinks.json", (_, res) => res.sendFile("assetlinks.json")); |
