Skip to content

Commit 18a8a1a

Browse files
committed
ref(browser): Use ratelimit utils in base transport
1 parent c946cf6 commit 18a8a1a

File tree

1 file changed

+18
-47
lines changed
  • packages/browser/src/transports

1 file changed

+18
-47
lines changed

packages/browser/src/transports/base.ts

Lines changed: 18 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,18 @@ import {
1919
} from '@sentry/types';
2020
import {
2121
createClientReportEnvelope,
22+
disabledUntil,
2223
dsnToString,
2324
eventStatusFromHttpCode,
2425
getGlobalObject,
2526
isDebugBuild,
27+
isRateLimited,
2628
logger,
2729
makePromiseBuffer,
28-
parseRetryAfterHeader,
2930
PromiseBuffer,
31+
RateLimits,
3032
serializeEnvelope,
33+
updateRateLimits,
3134
} from '@sentry/utils';
3235

3336
import { sendReport } from './utils';
@@ -53,7 +56,7 @@ export abstract class BaseTransport implements Transport {
5356
protected readonly _buffer: PromiseBuffer<SentryResponse> = makePromiseBuffer(30);
5457

5558
/** Locks transport after receiving rate limits in a response */
56-
protected readonly _rateLimits: Record<string, Date> = {};
59+
protected _rateLimits: RateLimits = {};
5760

5861
protected _outcomes: { [key: string]: number } = {};
5962

@@ -165,13 +168,12 @@ export abstract class BaseTransport implements Transport {
165168
reject: (reason?: unknown) => void;
166169
}): void {
167170
const status = eventStatusFromHttpCode(response.status);
168-
/**
169-
* "The name is case-insensitive."
170-
* https://developer.mozilla.org/en-US/docs/Web/API/Headers/get
171-
*/
172-
const limited = this._handleRateLimit(headers);
173-
if (limited && isDebugBuild()) {
174-
logger.warn(`Too many ${requestType} requests, backing off until: ${this._disabledUntil(requestType)}`);
171+
172+
this._rateLimits = updateRateLimits(this._rateLimits, headers);
173+
if (isRateLimited(this._rateLimits, requestType) && isDebugBuild()) {
174+
logger.warn(
175+
`Too many ${requestType} requests, backing off until: ${disabledUntil(this._rateLimits, requestType)}`,
176+
);
175177
}
176178

177179
if (status === 'success') {
@@ -184,52 +186,21 @@ export abstract class BaseTransport implements Transport {
184186

185187
/**
186188
* Gets the time that given category is disabled until for rate limiting
189+
*
190+
* @deprecated Please use `disabledUntil` from @sentry/utils
187191
*/
188-
protected _disabledUntil(requestType: SentryRequestType): Date {
192+
protected _disabledUntil(requestType: SentryRequestType): number {
189193
const category = requestTypeToCategory(requestType);
190-
return this._rateLimits[category] || this._rateLimits.all;
194+
return disabledUntil(this._rateLimits, category);
191195
}
192196

193197
/**
194198
* Checks if a category is rate limited
199+
*
200+
* @deprecated Please use `isRateLimited` from @sentry/utils
195201
*/
196202
protected _isRateLimited(requestType: SentryRequestType): boolean {
197-
return this._disabledUntil(requestType) > new Date(Date.now());
198-
}
199-
200-
/**
201-
* Sets internal _rateLimits from incoming headers. Returns true if headers contains a non-empty rate limiting header.
202-
*/
203-
protected _handleRateLimit(headers: Record<string, string | null>): boolean {
204-
const now = Date.now();
205-
const rlHeader = headers['x-sentry-rate-limits'];
206-
const raHeader = headers['retry-after'];
207-
208-
if (rlHeader) {
209-
// rate limit headers are of the form
210-
// <header>,<header>,..
211-
// where each <header> is of the form
212-
// <retry_after>: <categories>: <scope>: <reason_code>
213-
// where
214-
// <retry_after> is a delay in ms
215-
// <categories> is the event type(s) (error, transaction, etc) being rate limited and is of the form
216-
// <category>;<category>;...
217-
// <scope> is what's being limited (org, project, or key) - ignored by SDK
218-
// <reason_code> is an arbitrary string like "org_quota" - ignored by SDK
219-
for (const limit of rlHeader.trim().split(',')) {
220-
const parameters = limit.split(':', 2);
221-
const headerDelay = parseInt(parameters[0], 10);
222-
const delay = (!isNaN(headerDelay) ? headerDelay : 60) * 1000; // 60sec default
223-
for (const category of parameters[1].split(';')) {
224-
this._rateLimits[category || 'all'] = new Date(now + delay);
225-
}
226-
}
227-
return true;
228-
} else if (raHeader) {
229-
this._rateLimits.all = new Date(now + parseRetryAfterHeader(now, raHeader));
230-
return true;
231-
}
232-
return false;
203+
return isRateLimited(this._rateLimits, requestType);
233204
}
234205

235206
protected abstract _sendRequest(

0 commit comments

Comments
 (0)