@sentry/utils
Version:
Utilities for all Sentry JavaScript SDKs
99 lines (86 loc) • 3.12 kB
JavaScript
Object.defineProperty(exports, '__esModule', { value: true });
// Intentionally keeping the key broad, as we don't know for sure what rate limit headers get returned from backend
var DEFAULT_RETRY_AFTER = 60 * 1000; // 60 seconds
/**
* Extracts Retry-After value from the request header or returns default value
* @param header string representation of 'Retry-After' header
* @param now current unix timestamp
*
*/
function parseRetryAfterHeader(header, now = Date.now()) {
var headerDelay = parseInt(`${header}`, 10);
if (!isNaN(headerDelay)) {
return headerDelay * 1000;
}
var headerDate = Date.parse(`${header}`);
if (!isNaN(headerDate)) {
return headerDate - now;
}
return DEFAULT_RETRY_AFTER;
}
/**
* Gets the time that given category is disabled until for rate limiting
*/
function disabledUntil(limits, category) {
return limits[category] || limits.all || 0;
}
/**
* Checks if a category is rate limited
*/
function isRateLimited(limits, category, now = Date.now()) {
return disabledUntil(limits, category) > now;
}
/**
* Update ratelimits from incoming headers.
* Returns true if headers contains a non-empty rate limiting header.
*/
function updateRateLimits(
limits,
{ statusCode, headers },
now = Date.now(),
) {
var updatedRateLimits = {
...limits,
};
// "The name is case-insensitive."
// https://developer.mozilla.org/en-US/docs/Web/API/Headers/get
var rateLimitHeader = headers && headers['x-sentry-rate-limits'];
var retryAfterHeader = headers && headers['retry-after'];
if (rateLimitHeader) {
/**
* rate limit headers are of the form
* <header>,<header>,..
* where each <header> is of the form
* <retry_after>: <categories>: <scope>: <reason_code>
* where
* <retry_after> is a delay in seconds
* <categories> is the event type(s) (error, transaction, etc) being rate limited and is of the form
* <category>;<category>;...
* <scope> is what's being limited (org, project, or key) - ignored by SDK
* <reason_code> is an arbitrary string like "org_quota" - ignored by SDK
*/
for (var limit of rateLimitHeader.trim().split(',')) {
const [retryAfter, categories] = limit.split(':', 2);
var headerDelay = parseInt(retryAfter, 10);
var delay = (!isNaN(headerDelay) ? headerDelay : 60) * 1000; // 60sec default
if (!categories) {
updatedRateLimits.all = now + delay;
} else {
for (var category of categories.split(';')) {
updatedRateLimits[category] = now + delay;
}
}
}
} else if (retryAfterHeader) {
updatedRateLimits.all = now + parseRetryAfterHeader(retryAfterHeader, now);
} else if (statusCode === 429) {
updatedRateLimits.all = now + 60 * 1000;
}
return updatedRateLimits;
}
exports.DEFAULT_RETRY_AFTER = DEFAULT_RETRY_AFTER;
exports.disabledUntil = disabledUntil;
exports.isRateLimited = isRateLimited;
exports.parseRetryAfterHeader = parseRetryAfterHeader;
exports.updateRateLimits = updateRateLimits;
//# sourceMappingURL=ratelimit.js.map