Skip to content

Commit 7b8ad85

Browse files
committed
fix(webapp): fail open when the webhook ingress rate limiter backend is down
The per-IP ingress limiter is an async Express middleware, and Express 4 does not catch a rejected promise from a handler. If the rate-limiter backend is unreachable, ipLimiter.limit() rejects, next() is never called, and the request hangs until the client times out. Wrap the check in try/catch and let the request through on a limiter error (the per-endpoint limiter is the real protection), matching the OTLP ingress limiter.
1 parent 99edcb2 commit 7b8ad85

1 file changed

Lines changed: 9 additions & 4 deletions

File tree

apps/webapp/app/services/webhookIngressIpRateLimit.server.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { RequestHandler } from "express";
22
import { Ratelimit } from "@upstash/ratelimit";
33
import { env } from "~/env.server";
4+
import { logger } from "./logger.server";
45
import { RateLimiter, type Duration } from "./rateLimiter.server";
56

67
const ipLimiter = new RateLimiter({
@@ -17,10 +18,14 @@ export const webhookIngressIpRateLimiter: RequestHandler = async (req, res, next
1718
if (!req.path.startsWith("/webhooks/v1/ingest/")) return next();
1819
const ip =
1920
(req.headers["x-forwarded-for"] as string)?.split(",")[0]?.trim() || req.ip || "unknown";
20-
const { success } = await ipLimiter.limit(ip);
21-
if (!success) {
22-
res.status(429).json({ error: "Too many requests" });
23-
return;
21+
try {
22+
const { success } = await ipLimiter.limit(ip);
23+
if (!success) {
24+
res.status(429).json({ error: "Too many requests" });
25+
return;
26+
}
27+
} catch (error) {
28+
logger.warn("webhookIngressIpRateLimiter: limiter error, allowing request", { error });
2429
}
2530
next();
2631
};

0 commit comments

Comments
 (0)