3
3
4
4
using Microsoft . Extensions . Configuration ;
5
5
using Microsoft . DevProxy . Abstractions ;
6
- using Microsoft . DevProxy . Plugins . MockResponses ;
7
6
using System . Net ;
8
7
using System . Text . Json ;
9
8
using System . Text . RegularExpressions ;
@@ -35,7 +34,6 @@ public class RateLimitConfiguration
35
34
public int ResetTimeWindowSeconds { get ; set ; } = 60 ;
36
35
public int WarningThresholdPercent { get ; set ; } = 80 ;
37
36
public int RateLimit { get ; set ; } = 120 ;
38
- public int RetryAfterSeconds { get ; set ; } = 5 ;
39
37
public RateLimitResponseWhenLimitExceeded WhenLimitExceeded { get ; set ; } = RateLimitResponseWhenLimitExceeded . Throttle ;
40
38
public string CustomResponseFile { get ; set ; } = "rate-limit-response.json" ;
41
39
public MockResponseResponse ? CustomResponse { get ; set ; }
@@ -54,7 +52,7 @@ public class RateLimitingPlugin : BaseProxyPlugin
54
52
private ThrottlingInfo ShouldThrottle ( Request request , string throttlingKey )
55
53
{
56
54
var throttleKeyForRequest = BuildThrottleKey ( request ) ;
57
- return new ThrottlingInfo ( throttleKeyForRequest == throttlingKey ? _configuration . RetryAfterSeconds : 0 , _configuration . HeaderRetryAfter ) ;
55
+ return new ThrottlingInfo ( throttleKeyForRequest == throttlingKey ? ( int ) ( _resetTime - DateTime . Now ) . TotalSeconds : 0 , _configuration . HeaderRetryAfter ) ;
58
56
}
59
57
60
58
private void ThrottleResponse ( ProxyRequestArgs e ) => UpdateProxyResponse ( e , HttpStatusCode . TooManyRequests ) ;
@@ -89,7 +87,7 @@ private void UpdateProxyResponse(ProxyHttpEventArgsBase e, HttpStatusCode errorS
89
87
) ;
90
88
}
91
89
92
- headers . Add ( new ( _configuration . HeaderRetryAfter , _configuration . RetryAfterSeconds . ToString ( ) ) ) ;
90
+ headers . Add ( new ( _configuration . HeaderRetryAfter , ( ( int ) ( _resetTime - DateTime . Now ) . TotalSeconds ) . ToString ( ) ) ) ;
93
91
94
92
e . Session . GenericResponse ( body ?? string . Empty , errorStatus , headers . Select ( h => new HttpHeader ( h . Name , h . Value ) ) . ToArray ( ) ) ;
95
93
return ;
@@ -193,7 +191,7 @@ _urlsToWatch is null ||
193
191
e . ThrottledRequests . Add ( new ThrottlerInfo (
194
192
BuildThrottleKey ( request ) ,
195
193
ShouldThrottle ,
196
- DateTime . Now . AddSeconds ( _configuration . RetryAfterSeconds )
194
+ _resetTime
197
195
) ) ;
198
196
ThrottleResponse ( e ) ;
199
197
state . HasBeenSet = true ;
@@ -202,9 +200,18 @@ _urlsToWatch is null ||
202
200
{
203
201
if ( _configuration . CustomResponse is not null )
204
202
{
205
- var headers = _configuration . CustomResponse . Headers is not null ?
206
- _configuration . CustomResponse . Headers . Select ( h => new HttpHeader ( h . Name , h . Value ) ) . ToArray ( ) :
207
- Array . Empty < HttpHeader > ( ) ;
203
+ var headersList = _configuration . CustomResponse . Headers is not null ?
204
+ _configuration . CustomResponse . Headers . Select ( h => new HttpHeader ( h . Name , h . Value ) ) . ToList ( ) :
205
+ new List < HttpHeader > ( ) ;
206
+
207
+ var retryAfterHeader = headersList . FirstOrDefault ( h => h . Name . Equals ( _configuration . HeaderRetryAfter , StringComparison . OrdinalIgnoreCase ) ) ;
208
+ if ( retryAfterHeader is not null && retryAfterHeader . Value == "@dynamic" )
209
+ {
210
+ headersList . Add ( new HttpHeader ( _configuration . HeaderRetryAfter , ( ( int ) ( _resetTime - DateTime . Now ) . TotalSeconds ) . ToString ( ) ) ) ;
211
+ headersList . Remove ( retryAfterHeader ) ;
212
+ }
213
+
214
+ var headers = headersList . ToArray ( ) ;
208
215
209
216
// allow custom throttling response
210
217
var responseCode = ( HttpStatusCode ) ( _configuration . CustomResponse . StatusCode ?? 200 ) ;
@@ -213,7 +220,7 @@ _urlsToWatch is null ||
213
220
e . ThrottledRequests . Add ( new ThrottlerInfo (
214
221
BuildThrottleKey ( request ) ,
215
222
ShouldThrottle ,
216
- DateTime . Now . AddSeconds ( _configuration . RetryAfterSeconds )
223
+ _resetTime
217
224
) ) ;
218
225
}
219
226
0 commit comments