mirror of
https://github.com/DayuanJiang/next-ai-draw-io.git
synced 2026-10-07 10:17:47 +08:00
feat(api): count the quota by the CDN's client IP and refuse direct calls
Two optional settings for deployments behind a CDN such as Cloudflare. CLIENT_IP_HEADER names the header that holds the visitor's real IP (cf-connecting-ip on Cloudflare). The per-IP daily quota used the first X-Forwarded-For entry, which visitors can set to anything, so a made-up IP on every request got a fresh quota. ORIGIN_SECRET makes proxy.ts refuse /api requests whose X-Origin-Secret header does not match. The CDN adds the header, so a call that skips the CDN, and could fake the IP header, gets 403. Pages are not checked, which keeps health checks on / working. Both are unset by default, and nothing changes then.
This commit is contained in:
+11
-2
@@ -2,10 +2,19 @@
|
||||
* Generate a userId from request for tracking purposes.
|
||||
* Uses base64url encoding of IP for URL-safe identifier.
|
||||
* Note: base64 is reversible - this is NOT privacy protection.
|
||||
*
|
||||
* The first X-Forwarded-For entry is whatever the visitor sent, so behind a
|
||||
* CDN set CLIENT_IP_HEADER to the header it fills with the real IP (e.g.
|
||||
* cf-connecting-ip), and ORIGIN_SECRET so requests that skip the CDN are
|
||||
* refused (see proxy.ts).
|
||||
*/
|
||||
export function getUserIdFromRequest(req: Request): string {
|
||||
const forwardedFor = req.headers.get("x-forwarded-for")
|
||||
const rawIp = forwardedFor?.split(",")[0]?.trim() || "anonymous"
|
||||
const ipHeader = process.env.CLIENT_IP_HEADER
|
||||
const rawIp =
|
||||
(ipHeader
|
||||
? req.headers.get(ipHeader)?.trim()
|
||||
: req.headers.get("x-forwarded-for")?.split(",")[0]?.trim()) ||
|
||||
"anonymous"
|
||||
return rawIp === "anonymous"
|
||||
? rawIp
|
||||
: `user-${Buffer.from(rawIp).toString("base64url")}`
|
||||
|
||||
Reference in New Issue
Block a user