mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-04-22 06:42:50 +08:00
refactor code
This commit is contained in:
parent
659d124780
commit
2fa6e66dd4
@ -117,12 +117,8 @@ namespace Ocelot.Configuration.Creator
|
|||||||
rateLimitOption = new RateLimitOptions(enableRateLimiting, globalConfiguration.RateLimitOptions.ClientIdHeader,
|
rateLimitOption = new RateLimitOptions(enableRateLimiting, globalConfiguration.RateLimitOptions.ClientIdHeader,
|
||||||
fileReRoute.RateLimitOptions.ClientWhitelist, globalConfiguration.RateLimitOptions.DisableRateLimitHeaders,
|
fileReRoute.RateLimitOptions.ClientWhitelist, globalConfiguration.RateLimitOptions.DisableRateLimitHeaders,
|
||||||
globalConfiguration.RateLimitOptions.QuotaExceededMessage, globalConfiguration.RateLimitOptions.RateLimitCounterPrefix,
|
globalConfiguration.RateLimitOptions.QuotaExceededMessage, globalConfiguration.RateLimitOptions.RateLimitCounterPrefix,
|
||||||
new RateLimitRule()
|
new RateLimitRule(fileReRoute.RateLimitOptions.Period, TimeSpan.FromSeconds(fileReRoute.RateLimitOptions.PeriodTimespan), fileReRoute.RateLimitOptions.Limit)
|
||||||
{
|
, globalConfiguration.RateLimitOptions.HttpStatusCode);
|
||||||
Limit = fileReRoute.RateLimitOptions.Limit,
|
|
||||||
Period = fileReRoute.RateLimitOptions.Period,
|
|
||||||
PeriodTimespan = TimeSpan.FromSeconds(fileReRoute.RateLimitOptions.PeriodTimespan)
|
|
||||||
}, globalConfiguration.RateLimitOptions.HttpStatusCode);
|
|
||||||
}
|
}
|
||||||
var serviceProviderPort = globalConfiguration?.ServiceDiscoveryProvider?.Port ?? 0;
|
var serviceProviderPort = globalConfiguration?.ServiceDiscoveryProvider?.Port ?? 0;
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ namespace Ocelot.Configuration.File
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the HTTP Status code returned when rate limiting occurs, by default value is set to 429 (Too Many Requests)
|
/// Gets or sets the HTTP Status code returned when rate limiting occurs, by default value is set to 429 (Too Many Requests)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int HttpStatusCode { get; private set; } = 429;
|
public int HttpStatusCode { get; set; } = 429;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ namespace Ocelot.Configuration.File
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string Period { get; set; }
|
public string Period { get; set; }
|
||||||
|
|
||||||
public int PeriodTimespan { get; set; }
|
public double PeriodTimespan { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Maximum number of requests that a client can make in a defined period
|
/// Maximum number of requests that a client can make in a defined period
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -15,7 +15,7 @@ namespace Ocelot.Configuration
|
|||||||
{
|
{
|
||||||
EnableRateLimiting = enbleRateLimiting;
|
EnableRateLimiting = enbleRateLimiting;
|
||||||
ClientIdHeader = clientIdHeader;
|
ClientIdHeader = clientIdHeader;
|
||||||
ClientWhitelist = clientWhitelist;
|
ClientWhitelist = clientWhitelist?? new List<string>();
|
||||||
DisableRateLimitHeaders = disableRateLimitHeaders;
|
DisableRateLimitHeaders = disableRateLimitHeaders;
|
||||||
QuotaExceededMessage = quotaExceededMessage;
|
QuotaExceededMessage = quotaExceededMessage;
|
||||||
RateLimitCounterPrefix = rateLimitCounterPrefix;
|
RateLimitCounterPrefix = rateLimitCounterPrefix;
|
||||||
@ -62,15 +62,22 @@ namespace Ocelot.Configuration
|
|||||||
|
|
||||||
public class RateLimitRule
|
public class RateLimitRule
|
||||||
{
|
{
|
||||||
/// <summary>
|
public RateLimitRule(string period, TimeSpan periodTimespan, long limit)
|
||||||
/// Rate limit period as in 1s, 1m, 1h
|
{
|
||||||
/// </summary>
|
Period = period;
|
||||||
public string Period { get; set; }
|
PeriodTimespan = periodTimespan;
|
||||||
|
Limit = limit;
|
||||||
|
}
|
||||||
|
|
||||||
public TimeSpan? PeriodTimespan { get; set; }
|
/// <summary>
|
||||||
|
/// Rate limit period as in 1s, 1m, 1h,1d
|
||||||
|
/// </summary>
|
||||||
|
public string Period { get; private set; }
|
||||||
|
|
||||||
|
public TimeSpan PeriodTimespan { get; private set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Maximum number of requests that a client can make in a defined period
|
/// Maximum number of requests that a client can make in a defined period
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public long Limit { get; set; }
|
public long Limit { get; private set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,7 @@ namespace Ocelot.DependencyInjection
|
|||||||
// could maybe use a scoped data repository
|
// could maybe use a scoped data repository
|
||||||
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
||||||
services.AddScoped<IRequestScopedDataRepository, HttpDataRepository>();
|
services.AddScoped<IRequestScopedDataRepository, HttpDataRepository>();
|
||||||
|
services.AddMemoryCache();
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using Ocelot.Configuration;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Ocelot.Configuration;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@ -27,9 +28,9 @@ namespace Ocelot.RateLimit
|
|||||||
return _core.RetryAfterFrom(timestamp, rule);
|
return _core.RetryAfterFrom(timestamp, rule);
|
||||||
}
|
}
|
||||||
|
|
||||||
public RateLimitHeaders GetRateLimitHeaders(ClientRequestIdentity requestIdentity, RateLimitOptions option)
|
public RateLimitHeaders GetRateLimitHeaders(HttpContext context, ClientRequestIdentity requestIdentity, RateLimitOptions option)
|
||||||
{
|
{
|
||||||
return _core.GetRateLimitHeaders(requestIdentity, option);
|
return _core.GetRateLimitHeaders(context, requestIdentity, option);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,10 +2,17 @@
|
|||||||
{
|
{
|
||||||
public class ClientRequestIdentity
|
public class ClientRequestIdentity
|
||||||
{
|
{
|
||||||
public string ClientId { get; set; }
|
public ClientRequestIdentity(string clientId, string path, string httpverb)
|
||||||
|
{
|
||||||
|
ClientId = clientId;
|
||||||
|
Path = path;
|
||||||
|
HttpVerb = httpverb;
|
||||||
|
}
|
||||||
|
|
||||||
public string Path { get; set; }
|
public string ClientId { get; private set; }
|
||||||
|
|
||||||
public string HttpVerb { get; set; }
|
public string Path { get; private set; }
|
||||||
|
|
||||||
|
public string HttpVerb { get; private set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -72,9 +72,7 @@ namespace Ocelot.RateLimit.Middleware
|
|||||||
//set X-Rate-Limit headers for the longest period
|
//set X-Rate-Limit headers for the longest period
|
||||||
if (!options.DisableRateLimitHeaders)
|
if (!options.DisableRateLimitHeaders)
|
||||||
{
|
{
|
||||||
var headers = _processor.GetRateLimitHeaders(identity, options);
|
var headers = _processor.GetRateLimitHeaders( context,identity, options);
|
||||||
headers.Context = context;
|
|
||||||
|
|
||||||
context.Response.OnStarting(SetRateLimitHeaders, state: headers);
|
context.Response.OnStarting(SetRateLimitHeaders, state: headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,21 +87,19 @@ namespace Ocelot.RateLimit.Middleware
|
|||||||
clientId = httpContext.Request.Headers[option.ClientIdHeader].First();
|
clientId = httpContext.Request.Headers[option.ClientIdHeader].First();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ClientRequestIdentity
|
return new ClientRequestIdentity(
|
||||||
{
|
clientId,
|
||||||
Path = httpContext.Request.Path.ToString().ToLowerInvariant(),
|
httpContext.Request.Path.ToString().ToLowerInvariant(),
|
||||||
HttpVerb = httpContext.Request.Method.ToLowerInvariant(),
|
httpContext.Request.Method.ToLowerInvariant()
|
||||||
ClientId = clientId,
|
);
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsWhitelisted(ClientRequestIdentity requestIdentity, RateLimitOptions option)
|
public bool IsWhitelisted(ClientRequestIdentity requestIdentity, RateLimitOptions option)
|
||||||
{
|
{
|
||||||
if (option.ClientWhitelist != null && option.ClientWhitelist.Contains(requestIdentity.ClientId))
|
if (option.ClientWhitelist.Contains(requestIdentity.ClientId))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
using Ocelot.Configuration;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Ocelot.Configuration;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Ocelot.RateLimit
|
namespace Ocelot.RateLimit
|
||||||
@ -19,11 +22,7 @@ namespace Ocelot.RateLimit
|
|||||||
|
|
||||||
public RateLimitCounter ProcessRequest(ClientRequestIdentity requestIdentity, RateLimitOptions option)
|
public RateLimitCounter ProcessRequest(ClientRequestIdentity requestIdentity, RateLimitOptions option)
|
||||||
{
|
{
|
||||||
var counter = new RateLimitCounter
|
RateLimitCounter counter = new RateLimitCounter(DateTime.UtcNow, 1);
|
||||||
{
|
|
||||||
Timestamp = DateTime.UtcNow,
|
|
||||||
TotalRequests = 1
|
|
||||||
};
|
|
||||||
var rule = option.RateLimitRule;
|
var rule = option.RateLimitRule;
|
||||||
|
|
||||||
var counterId = ComputeCounterKey(requestIdentity, option);
|
var counterId = ComputeCounterKey(requestIdentity, option);
|
||||||
@ -35,59 +34,57 @@ namespace Ocelot.RateLimit
|
|||||||
if (entry.HasValue)
|
if (entry.HasValue)
|
||||||
{
|
{
|
||||||
// entry has not expired
|
// entry has not expired
|
||||||
if (entry.Value.Timestamp + rule.PeriodTimespan.Value >= DateTime.UtcNow)
|
if (entry.Value.Timestamp + rule.PeriodTimespan >= DateTime.UtcNow)
|
||||||
{
|
{
|
||||||
// increment request count
|
// increment request count
|
||||||
var totalRequests = entry.Value.TotalRequests + 1;
|
var totalRequests = entry.Value.TotalRequests + 1;
|
||||||
|
|
||||||
// deep copy
|
// deep copy
|
||||||
counter = new RateLimitCounter
|
counter = new RateLimitCounter(entry.Value.Timestamp, totalRequests);
|
||||||
{
|
|
||||||
Timestamp = entry.Value.Timestamp,
|
|
||||||
TotalRequests = totalRequests
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
// stores: id (string) - timestamp (datetime) - total_requests (long)
|
// stores: id (string) - timestamp (datetime) - total_requests (long)
|
||||||
_counterHandler.Set(counterId, counter, rule.PeriodTimespan.Value);
|
_counterHandler.Set(counterId, counter, rule.PeriodTimespan);
|
||||||
}
|
}
|
||||||
|
|
||||||
return counter;
|
return counter;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RateLimitHeaders GetRateLimitHeaders(ClientRequestIdentity requestIdentity, RateLimitOptions option)
|
public RateLimitHeaders GetRateLimitHeaders(HttpContext context, ClientRequestIdentity requestIdentity, RateLimitOptions option)
|
||||||
{
|
{
|
||||||
var rule = option.RateLimitRule;
|
var rule = option.RateLimitRule;
|
||||||
var headers = new RateLimitHeaders();
|
RateLimitHeaders headers = null;
|
||||||
var counterId = ComputeCounterKey(requestIdentity, option);
|
var counterId = ComputeCounterKey(requestIdentity, option);
|
||||||
var entry = _counterHandler.Get(counterId);
|
var entry = _counterHandler.Get(counterId);
|
||||||
if (entry.HasValue)
|
if (entry.HasValue)
|
||||||
{
|
{
|
||||||
headers.Reset = (entry.Value.Timestamp + ConvertToTimeSpan(rule.Period)).ToUniversalTime().ToString("o", DateTimeFormatInfo.InvariantInfo);
|
headers = new RateLimitHeaders(context, rule.Period,
|
||||||
headers.Limit = rule.Period;
|
(rule.Limit - entry.Value.TotalRequests).ToString(),
|
||||||
headers.Remaining = (rule.Limit - entry.Value.TotalRequests).ToString();
|
(entry.Value.Timestamp + ConvertToTimeSpan(rule.Period)).ToUniversalTime().ToString("o", DateTimeFormatInfo.InvariantInfo)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
headers.Reset = (DateTime.UtcNow + ConvertToTimeSpan(rule.Period)).ToUniversalTime().ToString("o", DateTimeFormatInfo.InvariantInfo);
|
headers = new RateLimitHeaders(context,
|
||||||
headers.Limit = rule.Period;
|
rule.Period,
|
||||||
headers.Remaining = rule.Limit.ToString();
|
rule.Limit.ToString(),
|
||||||
|
(DateTime.UtcNow + ConvertToTimeSpan(rule.Period)).ToUniversalTime().ToString("o", DateTimeFormatInfo.InvariantInfo));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return headers;
|
return headers;
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string ComputeCounterKey(ClientRequestIdentity requestIdentity, RateLimitOptions option)
|
public string ComputeCounterKey(ClientRequestIdentity requestIdentity, RateLimitOptions option)
|
||||||
{
|
{
|
||||||
var key = $"{option.RateLimitCounterPrefix}_{requestIdentity.ClientId}_{option.RateLimitRule.Period}_{requestIdentity.HttpVerb}_{requestIdentity.Path}";
|
var key = $"{option.RateLimitCounterPrefix}_{requestIdentity.ClientId}_{option.RateLimitRule.Period}_{requestIdentity.HttpVerb}_{requestIdentity.Path}";
|
||||||
|
|
||||||
var idBytes = System.Text.Encoding.UTF8.GetBytes(key);
|
var idBytes = Encoding.UTF8.GetBytes(key);
|
||||||
|
|
||||||
byte[] hashBytes;
|
byte[] hashBytes;
|
||||||
|
|
||||||
using (var algorithm = System.Security.Cryptography.SHA1.Create())
|
using (var algorithm = SHA1.Create())
|
||||||
{
|
{
|
||||||
hashBytes = algorithm.ComputeHash(idBytes);
|
hashBytes = algorithm.ComputeHash(idBytes);
|
||||||
}
|
}
|
||||||
@ -98,7 +95,7 @@ namespace Ocelot.RateLimit
|
|||||||
public string RetryAfterFrom(DateTime timestamp, RateLimitRule rule)
|
public string RetryAfterFrom(DateTime timestamp, RateLimitRule rule)
|
||||||
{
|
{
|
||||||
var secondsPast = Convert.ToInt32((DateTime.UtcNow - timestamp).TotalSeconds);
|
var secondsPast = Convert.ToInt32((DateTime.UtcNow - timestamp).TotalSeconds);
|
||||||
var retryAfter = Convert.ToInt32(rule.PeriodTimespan.Value.TotalSeconds);
|
var retryAfter = Convert.ToInt32(rule.PeriodTimespan.TotalSeconds);
|
||||||
retryAfter = retryAfter > 1 ? retryAfter - secondsPast : 1;
|
retryAfter = retryAfter > 1 ? retryAfter - secondsPast : 1;
|
||||||
return retryAfter.ToString(System.Globalization.CultureInfo.InvariantCulture);
|
return retryAfter.ToString(System.Globalization.CultureInfo.InvariantCulture);
|
||||||
}
|
}
|
||||||
@ -111,11 +108,16 @@ namespace Ocelot.RateLimit
|
|||||||
|
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case "d": return TimeSpan.FromDays(double.Parse(value));
|
case "d":
|
||||||
case "h": return TimeSpan.FromHours(double.Parse(value));
|
return TimeSpan.FromDays(double.Parse(value));
|
||||||
case "m": return TimeSpan.FromMinutes(double.Parse(value));
|
case "h":
|
||||||
case "s": return TimeSpan.FromSeconds(double.Parse(value));
|
return TimeSpan.FromHours(double.Parse(value));
|
||||||
default: throw new FormatException($"{timeSpan} can't be converted to TimeSpan, unknown type {type}");
|
case "m":
|
||||||
|
return TimeSpan.FromMinutes(double.Parse(value));
|
||||||
|
case "s":
|
||||||
|
return TimeSpan.FromSeconds(double.Parse(value));
|
||||||
|
default:
|
||||||
|
throw new FormatException($"{timeSpan} can't be converted to TimeSpan, unknown type {type}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,8 +10,14 @@ namespace Ocelot.RateLimit
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public struct RateLimitCounter
|
public struct RateLimitCounter
|
||||||
{
|
{
|
||||||
public DateTime Timestamp { get; set; }
|
public RateLimitCounter(DateTime timestamp, long totalRequest)
|
||||||
|
{
|
||||||
|
Timestamp = timestamp;
|
||||||
|
TotalRequests = totalRequest;
|
||||||
|
}
|
||||||
|
|
||||||
public long TotalRequests { get; set; }
|
public DateTime Timestamp { get; private set; }
|
||||||
|
|
||||||
|
public long TotalRequests { get; private set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,12 +8,20 @@ namespace Ocelot.RateLimit
|
|||||||
{
|
{
|
||||||
public class RateLimitHeaders
|
public class RateLimitHeaders
|
||||||
{
|
{
|
||||||
public HttpContext Context { get; set; }
|
public RateLimitHeaders(HttpContext context, string limit, string remaining, string reset)
|
||||||
|
{
|
||||||
|
Context = context;
|
||||||
|
Limit = limit;
|
||||||
|
Remaining = remaining;
|
||||||
|
Reset = reset;
|
||||||
|
}
|
||||||
|
|
||||||
public string Limit { get; set; }
|
public HttpContext Context { get; private set; }
|
||||||
|
|
||||||
public string Remaining { get; set; }
|
public string Limit { get; private set; }
|
||||||
|
|
||||||
public string Reset { get; set; }
|
public string Remaining { get; private set; }
|
||||||
|
|
||||||
|
public string Reset { get; private set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,9 @@ namespace Ocelot.AcceptanceTests
|
|||||||
ClientIdHeader = "ClientId",
|
ClientIdHeader = "ClientId",
|
||||||
DisableRateLimitHeaders = false,
|
DisableRateLimitHeaders = false,
|
||||||
QuotaExceededMessage = "",
|
QuotaExceededMessage = "",
|
||||||
RateLimitCounterPrefix = ""
|
RateLimitCounterPrefix = "",
|
||||||
|
HttpStatusCode = 428
|
||||||
|
|
||||||
},
|
},
|
||||||
RequestIdKey ="oceclientrequest"
|
RequestIdKey ="oceclientrequest"
|
||||||
}
|
}
|
||||||
@ -76,8 +78,12 @@ namespace Ocelot.AcceptanceTests
|
|||||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879/api/ClientRateLimit"))
|
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879/api/ClientRateLimit"))
|
||||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||||
.And(x => _steps.GivenOcelotIsRunning())
|
.And(x => _steps.GivenOcelotIsRunning())
|
||||||
.When(x => _steps.WhenIGetUrlOnTheApiGatewayMultipleTimesForRateLimit("/api/ClientRateLimit", 5))
|
.When(x => _steps.WhenIGetUrlOnTheApiGatewayMultipleTimesForRateLimit("/api/ClientRateLimit",1))
|
||||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(429))
|
.Then(x => _steps.ThenTheStatusCodeShouldBe(200))
|
||||||
|
.When(x => _steps.WhenIGetUrlOnTheApiGatewayMultipleTimesForRateLimit("/api/ClientRateLimit", 2))
|
||||||
|
.Then(x => _steps.ThenTheStatusCodeShouldBe(200))
|
||||||
|
.When(x => _steps.WhenIGetUrlOnTheApiGatewayMultipleTimesForRateLimit("/api/ClientRateLimit",1))
|
||||||
|
.Then(x => _steps.ThenTheStatusCodeShouldBe(428))
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,55 +160,6 @@ namespace Ocelot.AcceptanceTests
|
|||||||
_builder.Start();
|
_builder.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
//private void GetApiRateLimait(string url)
|
|
||||||
//{
|
|
||||||
// var clientId = "ocelotclient1";
|
|
||||||
// var request = new HttpRequestMessage(new HttpMethod("GET"), url);
|
|
||||||
// request.Headers.Add("ClientId", clientId);
|
|
||||||
|
|
||||||
// var response = _client.SendAsync(request);
|
|
||||||
// responseStatusCode = (int)response.Result.StatusCode;
|
|
||||||
// }
|
|
||||||
|
|
||||||
//}
|
|
||||||
|
|
||||||
//public void WhenIGetUrlOnTheApiGatewayMultipleTimes(string url, int times)
|
|
||||||
//{
|
|
||||||
// var clientId = "ocelotclient1";
|
|
||||||
// var tasks = new Task[times];
|
|
||||||
|
|
||||||
// for (int i = 0; i < times; i++)
|
|
||||||
// {
|
|
||||||
// var urlCopy = url;
|
|
||||||
// tasks[i] = GetForServiceDiscoveryTest(urlCopy);
|
|
||||||
// Thread.Sleep(_random.Next(40, 60));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Task.WaitAll(tasks);
|
|
||||||
//}
|
|
||||||
|
|
||||||
//private void WhenICallTheMiddlewareWithWhiteClient()
|
|
||||||
//{
|
|
||||||
// var clientId = "ocelotclient2";
|
|
||||||
// // Act
|
|
||||||
// for (int i = 0; i < 2; i++)
|
|
||||||
// {
|
|
||||||
// var request = new HttpRequestMessage(new HttpMethod("GET"), apiRateLimitPath);
|
|
||||||
// request.Headers.Add("ClientId", clientId);
|
|
||||||
|
|
||||||
// var response = _client.SendAsync(request);
|
|
||||||
// responseStatusCode = (int)response.Result.StatusCode;
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//private void ThenresponseStatusCodeIs429()
|
|
||||||
//{
|
|
||||||
// responseStatusCode.ShouldBe(429);
|
|
||||||
//}
|
|
||||||
|
|
||||||
//private void ThenresponseStatusCodeIs200()
|
|
||||||
//{
|
|
||||||
// responseStatusCode.ShouldBe(200);
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -101,7 +101,6 @@ namespace Ocelot.AcceptanceTests
|
|||||||
})
|
})
|
||||||
.WithDictionaryHandle();
|
.WithDictionaryHandle();
|
||||||
};
|
};
|
||||||
s.AddMemoryCache();
|
|
||||||
s.AddOcelotOutputCaching(settings);
|
s.AddOcelotOutputCaching(settings);
|
||||||
s.AddOcelotFileConfiguration(configuration);
|
s.AddOcelotFileConfiguration(configuration);
|
||||||
s.AddOcelot();
|
s.AddOcelot();
|
||||||
|
@ -1 +1 @@
|
|||||||
{"ReRoutes":[{"DownstreamPathTemplate":"41879/","UpstreamTemplate":"/","UpstreamHttpMethod":"Get","AuthenticationOptions":{"Provider":null,"ProviderRootUrl":null,"ScopeName":null,"RequireHttps":false,"AdditionalScopes":[],"ScopeSecret":null},"AddHeadersToRequest":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{},"AddQueriesToRequest":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0},"ReRouteIsCaseSensitive":false,"ServiceName":null,"DownstreamScheme":"http","DownstreamHost":"localhost","DownstreamPort":41879,"QoSOptions":{"ExceptionsAllowedBeforeBreaking":0,"DurationOfBreak":0,"TimeoutValue":0},"LoadBalancer":null,"RateLimitOptions":{"ClientWhitelist":[],"EnableRateLimiting":false,"Period":null,"PeriodTimespan":0,"Limit":0}}],"GlobalConfiguration":{"RequestIdKey":null,"ServiceDiscoveryProvider":{"Provider":null,"Host":null,"Port":0},"RateLimitOptions":{"ClientIdHeader":"ClientId","QuotaExceededMessage":null,"RateLimitCounterPrefix":"ocelot","DisableRateLimitHeaders":false,"HttpStatusCode":429}}}
|
{"ReRoutes":[{"DownstreamPathTemplate":"41879/","UpstreamTemplate":"/","UpstreamHttpMethod":"Get","AuthenticationOptions":{"Provider":null,"ProviderRootUrl":null,"ScopeName":null,"RequireHttps":false,"AdditionalScopes":[],"ScopeSecret":null},"AddHeadersToRequest":{},"AddClaimsToRequest":{},"RouteClaimsRequirement":{},"AddQueriesToRequest":{},"RequestIdKey":null,"FileCacheOptions":{"TtlSeconds":0},"ReRouteIsCaseSensitive":false,"ServiceName":null,"DownstreamScheme":"http","DownstreamHost":"localhost","DownstreamPort":41879,"QoSOptions":{"ExceptionsAllowedBeforeBreaking":0,"DurationOfBreak":0,"TimeoutValue":0},"LoadBalancer":null,"RateLimitOptions":{"ClientWhitelist":[],"EnableRateLimiting":false,"Period":null,"PeriodTimespan":0.0,"Limit":0}}],"GlobalConfiguration":{"RequestIdKey":null,"ServiceDiscoveryProvider":{"Provider":null,"Host":null,"Port":0},"RateLimitOptions":{"ClientIdHeader":"ClientId","QuotaExceededMessage":null,"RateLimitCounterPrefix":"ocelot","DisableRateLimitHeaders":false,"HttpStatusCode":429}}}
|
@ -23,7 +23,6 @@
|
|||||||
"Microsoft.AspNetCore.Http": "1.1.0",
|
"Microsoft.AspNetCore.Http": "1.1.0",
|
||||||
"Microsoft.DotNet.InternalAbstractions": "1.0.0",
|
"Microsoft.DotNet.InternalAbstractions": "1.0.0",
|
||||||
"Ocelot": "0.0.0-dev",
|
"Ocelot": "0.0.0-dev",
|
||||||
"xunit": "2.2.0-beta2-build3300",
|
|
||||||
"dotnet-test-xunit": "2.2.0-preview2-build1029",
|
"dotnet-test-xunit": "2.2.0-preview2-build1029",
|
||||||
"Ocelot.ManualTest": "0.0.0-dev",
|
"Ocelot.ManualTest": "0.0.0-dev",
|
||||||
"Microsoft.AspNetCore.TestHost": "1.1.0",
|
"Microsoft.AspNetCore.TestHost": "1.1.0",
|
||||||
@ -34,7 +33,8 @@
|
|||||||
"Shouldly": "2.8.2",
|
"Shouldly": "2.8.2",
|
||||||
"TestStack.BDDfy": "4.3.2",
|
"TestStack.BDDfy": "4.3.2",
|
||||||
"Consul": "0.7.2.1",
|
"Consul": "0.7.2.1",
|
||||||
"Microsoft.Extensions.Caching.Memory": "1.1.0"
|
"Microsoft.Extensions.Caching.Memory": "1.1.0",
|
||||||
|
"xunit": "2.2.0-rc1-build3507"
|
||||||
},
|
},
|
||||||
"runtimes": {
|
"runtimes": {
|
||||||
"win10-x64": {},
|
"win10-x64": {},
|
||||||
|
@ -37,7 +37,6 @@ namespace Ocelot.ManualTest
|
|||||||
})
|
})
|
||||||
.WithDictionaryHandle();
|
.WithDictionaryHandle();
|
||||||
};
|
};
|
||||||
services.AddMemoryCache();
|
|
||||||
services.AddOcelotOutputCaching(settings);
|
services.AddOcelotOutputCaching(settings);
|
||||||
services.AddOcelotFileConfiguration(Configuration);
|
services.AddOcelotFileConfiguration(Configuration);
|
||||||
services.AddOcelot();
|
services.AddOcelot();
|
||||||
|
@ -20,6 +20,7 @@ using Xunit;
|
|||||||
using TestStack.BDDfy;
|
using TestStack.BDDfy;
|
||||||
using Ocelot.Configuration.Builder;
|
using Ocelot.Configuration.Builder;
|
||||||
using Shouldly;
|
using Shouldly;
|
||||||
|
using Ocelot.Configuration;
|
||||||
|
|
||||||
namespace Ocelot.UnitTests.RateLimit
|
namespace Ocelot.UnitTests.RateLimit
|
||||||
{
|
{
|
||||||
@ -70,11 +71,13 @@ namespace Ocelot.UnitTests.RateLimit
|
|||||||
{
|
{
|
||||||
var downstreamRoute = new DownstreamRoute(new List<Ocelot.DownstreamRouteFinder.UrlMatcher.UrlPathPlaceholderNameAndValue>(),
|
var downstreamRoute = new DownstreamRoute(new List<Ocelot.DownstreamRouteFinder.UrlMatcher.UrlPathPlaceholderNameAndValue>(),
|
||||||
new ReRouteBuilder().WithEnableRateLimiting(true).WithRateLimitOptions(
|
new ReRouteBuilder().WithEnableRateLimiting(true).WithRateLimitOptions(
|
||||||
new Ocelot.Configuration.RateLimitOptions(true, "ClientId", new List<string>(), false, "", "", new Ocelot.Configuration.RateLimitRule() { Limit = 3, Period = "1s", PeriodTimespan = TimeSpan.FromSeconds(100) },429))
|
new Ocelot.Configuration.RateLimitOptions(true, "ClientId", new List<string>(), false, "", "", new Ocelot.Configuration.RateLimitRule("1s", TimeSpan.FromSeconds(100), 3), 429))
|
||||||
.Build());
|
.Build());
|
||||||
|
|
||||||
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
|
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
|
||||||
.When(x => x.WhenICallTheMiddleware())
|
.When(x => x.WhenICallTheMiddlewareMultipleTime(2))
|
||||||
|
.Then(x => x.ThenresponseStatusCodeIs200())
|
||||||
|
.When(x => x.WhenICallTheMiddlewareMultipleTime(2))
|
||||||
.Then(x => x.ThenresponseStatusCodeIs429())
|
.Then(x => x.ThenresponseStatusCodeIs429())
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
@ -84,7 +87,7 @@ namespace Ocelot.UnitTests.RateLimit
|
|||||||
{
|
{
|
||||||
var downstreamRoute = new DownstreamRoute(new List<Ocelot.DownstreamRouteFinder.UrlMatcher.UrlPathPlaceholderNameAndValue>(),
|
var downstreamRoute = new DownstreamRoute(new List<Ocelot.DownstreamRouteFinder.UrlMatcher.UrlPathPlaceholderNameAndValue>(),
|
||||||
new ReRouteBuilder().WithEnableRateLimiting(true).WithRateLimitOptions(
|
new ReRouteBuilder().WithEnableRateLimiting(true).WithRateLimitOptions(
|
||||||
new Ocelot.Configuration.RateLimitOptions(true, "ClientId", new List<string>() { "ocelotclient2" }, false, "", "", new Ocelot.Configuration.RateLimitRule() { Limit = 3, Period = "1s", PeriodTimespan = TimeSpan.FromSeconds(100) },429))
|
new Ocelot.Configuration.RateLimitOptions(true, "ClientId", new List<string>() { "ocelotclient2" }, false, "", "", new RateLimitRule( "1s", TimeSpan.FromSeconds(100),3),429))
|
||||||
.Build());
|
.Build());
|
||||||
|
|
||||||
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
|
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
|
||||||
@ -102,11 +105,11 @@ namespace Ocelot.UnitTests.RateLimit
|
|||||||
.Returns(_downstreamRoute);
|
.Returns(_downstreamRoute);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WhenICallTheMiddleware()
|
private void WhenICallTheMiddlewareMultipleTime(int times)
|
||||||
{
|
{
|
||||||
var clientId = "ocelotclient1";
|
var clientId = "ocelotclient1";
|
||||||
// Act
|
// Act
|
||||||
for (int i = 0; i <10; i++)
|
for (int i = 0; i < times; i++)
|
||||||
{
|
{
|
||||||
var request = new HttpRequestMessage(new HttpMethod("GET"), _url);
|
var request = new HttpRequestMessage(new HttpMethod("GET"), _url);
|
||||||
request.Headers.Add("ClientId", clientId);
|
request.Headers.Add("ClientId", clientId);
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
"Microsoft.Extensions.Options.ConfigurationExtensions": "1.1.0",
|
"Microsoft.Extensions.Options.ConfigurationExtensions": "1.1.0",
|
||||||
"Microsoft.AspNetCore.Http": "1.1.0",
|
"Microsoft.AspNetCore.Http": "1.1.0",
|
||||||
"Ocelot": "0.0.0-dev",
|
"Ocelot": "0.0.0-dev",
|
||||||
"xunit": "2.2.0-beta2-build3300",
|
|
||||||
"dotnet-test-xunit": "2.2.0-preview2-build1029",
|
"dotnet-test-xunit": "2.2.0-preview2-build1029",
|
||||||
"Moq": "4.6.38-alpha",
|
"Moq": "4.6.38-alpha",
|
||||||
"Microsoft.AspNetCore.TestHost": "1.1.0",
|
"Microsoft.AspNetCore.TestHost": "1.1.0",
|
||||||
@ -24,7 +23,8 @@
|
|||||||
"Shouldly": "2.8.2",
|
"Shouldly": "2.8.2",
|
||||||
"TestStack.BDDfy": "4.3.2",
|
"TestStack.BDDfy": "4.3.2",
|
||||||
"Microsoft.AspNetCore.Authentication.OAuth": "1.1.0",
|
"Microsoft.AspNetCore.Authentication.OAuth": "1.1.0",
|
||||||
"Microsoft.DotNet.InternalAbstractions": "1.0.0"
|
"Microsoft.DotNet.InternalAbstractions": "1.0.0",
|
||||||
|
"xunit": "2.2.0-rc1-build3507"
|
||||||
},
|
},
|
||||||
"runtimes": {
|
"runtimes": {
|
||||||
"win10-x64": {},
|
"win10-x64": {},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user