@@ -19,15 +19,18 @@ import {
19
19
} from '@sentry/types' ;
20
20
import {
21
21
createClientReportEnvelope ,
22
+ disabledUntil ,
22
23
dsnToString ,
23
24
eventStatusFromHttpCode ,
24
25
getGlobalObject ,
25
26
isDebugBuild ,
27
+ isRateLimited ,
26
28
logger ,
27
29
makePromiseBuffer ,
28
- parseRetryAfterHeader ,
29
30
PromiseBuffer ,
31
+ RateLimits ,
30
32
serializeEnvelope ,
33
+ updateRateLimits ,
31
34
} from '@sentry/utils' ;
32
35
33
36
import { sendReport } from './utils' ;
@@ -53,7 +56,7 @@ export abstract class BaseTransport implements Transport {
53
56
protected readonly _buffer : PromiseBuffer < SentryResponse > = makePromiseBuffer ( 30 ) ;
54
57
55
58
/** Locks transport after receiving rate limits in a response */
56
- protected readonly _rateLimits : Record < string , Date > = { } ;
59
+ protected _rateLimits : RateLimits = { } ;
57
60
58
61
protected _outcomes : { [ key : string ] : number } = { } ;
59
62
@@ -165,13 +168,12 @@ export abstract class BaseTransport implements Transport {
165
168
reject : ( reason ?: unknown ) => void ;
166
169
} ) : void {
167
170
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
+ ) ;
175
177
}
176
178
177
179
if ( status === 'success' ) {
@@ -184,52 +186,21 @@ export abstract class BaseTransport implements Transport {
184
186
185
187
/**
186
188
* Gets the time that given category is disabled until for rate limiting
189
+ *
190
+ * @deprecated Please use `disabledUntil` from @sentry/utils
187
191
*/
188
- protected _disabledUntil ( requestType : SentryRequestType ) : Date {
192
+ protected _disabledUntil ( requestType : SentryRequestType ) : number {
189
193
const category = requestTypeToCategory ( requestType ) ;
190
- return this . _rateLimits [ category ] || this . _rateLimits . all ;
194
+ return disabledUntil ( this . _rateLimits , category ) ;
191
195
}
192
196
193
197
/**
194
198
* Checks if a category is rate limited
199
+ *
200
+ * @deprecated Please use `isRateLimited` from @sentry/utils
195
201
*/
196
202
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 ) ;
233
204
}
234
205
235
206
protected abstract _sendRequest (
0 commit comments