@sentry/core
Version:
Base implementation for all Sentry JavaScript SDKs
56 lines (53 loc) • 1.97 kB
JavaScript
import { safeDateNow } from './randomSafeContext.js';
const DEFAULT_RETRY_AFTER = 60 * 1e3;
function parseRetryAfterHeader(header, now = safeDateNow()) {
const headerDelay = parseInt(`${header}`, 10);
if (!isNaN(headerDelay)) {
return headerDelay * 1e3;
}
const headerDate = Date.parse(`${header}`);
if (!isNaN(headerDate)) {
return headerDate - now;
}
return DEFAULT_RETRY_AFTER;
}
function disabledUntil(limits, dataCategory) {
return limits[dataCategory] || limits.all || 0;
}
function isRateLimited(limits, dataCategory, now = safeDateNow()) {
return disabledUntil(limits, dataCategory) > now;
}
function updateRateLimits(limits, { statusCode, headers }, now = safeDateNow()) {
const updatedRateLimits = {
...limits
};
const rateLimitHeader = headers?.["x-sentry-rate-limits"];
const retryAfterHeader = headers?.["retry-after"];
if (rateLimitHeader) {
for (const limit of rateLimitHeader.trim().split(",")) {
const [retryAfter, categories, , , namespaces] = limit.split(":", 5);
const headerDelay = parseInt(retryAfter, 10);
const delay = (!isNaN(headerDelay) ? headerDelay : 60) * 1e3;
if (!categories) {
updatedRateLimits.all = now + delay;
} else {
for (const category of categories.split(";")) {
if (category === "metric_bucket") {
if (!namespaces || namespaces.split(";").includes("custom")) {
updatedRateLimits[category] = now + delay;
}
} else {
updatedRateLimits[category] = now + delay;
}
}
}
}
} else if (retryAfterHeader) {
updatedRateLimits.all = now + parseRetryAfterHeader(retryAfterHeader, now);
} else if (statusCode === 429) {
updatedRateLimits.all = now + 60 * 1e3;
}
return updatedRateLimits;
}
export { DEFAULT_RETRY_AFTER, disabledUntil, isRateLimited, parseRetryAfterHeader, updateRateLimits };
//# sourceMappingURL=ratelimit.js.map