Refactoring
This commit is contained in:
1 parent
e13a710fa6
commit
8835137e9b
7 files changed
+63
-81
No files matched your search
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using Asp.Versioning;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
@@ -25,24 +24,22 @@ namespace PostNordLotteriet.WebAPI.Controllers
|
||||
[HttpGet("trackandtrace")]
|
||||
public IActionResult Get()
|
||||
{
|
||||
DateTime currentDate = DateTime.Now;
|
||||
|
||||
if (_workDayService.IsNonWorkDay(currentDate))
|
||||
if (_workDayService.IsNonWorkDay(DateTime.Now))
|
||||
{
|
||||
DateTime nextWorkDay = _workDayService.GetNextWorkDay(currentDate);
|
||||
|
||||
Response.Headers.RetryAfter = nextWorkDay
|
||||
.ToUniversalTime()
|
||||
.ToString("R", CultureInfo.InvariantCulture);
|
||||
|
||||
return StatusCode(
|
||||
StatusCodes.Status503ServiceUnavailable,
|
||||
new { message = "Ingen postutdelning på arbetsfria dagar." });
|
||||
new { message = "Ingen postutdelning när det är helg." });
|
||||
}
|
||||
|
||||
return Random.Shared.NextDouble() < 0.4
|
||||
? Ok(new { message = "Grattis! Försändelsen finns snart i en brevlåda nära dig." })
|
||||
: BadRequest(new { message = "Tyvärr, ingen post idag." });
|
||||
bool won = Random.Shared.NextDouble() < 0.4;
|
||||
|
||||
return Ok(new
|
||||
{
|
||||
won,
|
||||
message = won
|
||||
? "Grattis! Försändelsen finns snart i en brevlåda nära dig."
|
||||
: "Tyvärr, ingen post idag."
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Text.Json;
|
||||
using System.Threading.RateLimiting;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
@@ -12,77 +11,63 @@ namespace PostNordLotteriet.WebAPI.Extensions
|
||||
public static class RateLimiterExtensions
|
||||
{
|
||||
// Adds a rate limiter with a custom error message in JSON format.
|
||||
public static IServiceCollection AddPostNordLotterietRateLimiter(this IServiceCollection services)
|
||||
public static IServiceCollection AddPostNordLotterietRateLimiter(
|
||||
this IServiceCollection services)
|
||||
{
|
||||
services.AddRateLimiter(options =>
|
||||
{
|
||||
options.AddPolicy(policyName: "fixed", httpContext =>
|
||||
options.AddPolicy("fixed", httpContext =>
|
||||
{
|
||||
// Disable rate limiter if today is a non-work day.
|
||||
if (httpContext.RequestServices.GetRequiredService<IWorkDayService>().IsNonWorkDay(DateTime.Now))
|
||||
{
|
||||
return RateLimitPartition.GetNoLimiter("NoLimiter");
|
||||
}
|
||||
else
|
||||
{
|
||||
return RateLimitPartition.GetFixedWindowLimiter(partitionKey: httpContext.Connection.RemoteIpAddress?.ToString()
|
||||
?? "Unknown",
|
||||
factory: _ => new FixedWindowRateLimiterOptions
|
||||
{
|
||||
Window = TimeSpan.FromDays(1),
|
||||
PermitLimit = 1
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
options.RejectionStatusCode = StatusCodes.Status429TooManyRequests;
|
||||
|
||||
options.OnRejected = async (context, cancellationToken) =>
|
||||
{
|
||||
HttpContext httpContext = context.HttpContext;
|
||||
|
||||
IWorkDayService workDayService =
|
||||
httpContext.RequestServices.GetRequiredService<IWorkDayService>();
|
||||
|
||||
DateTimeOffset now = DateTimeOffset.Now;
|
||||
DateTime now = DateTime.Now;
|
||||
|
||||
DateTime nextWorkDay = workDayService.GetNextWorkDay(now.DateTime);
|
||||
|
||||
// The next workday starts at midnight in the server's local time zone.
|
||||
DateTimeOffset nextWorkDayStart = new(
|
||||
nextWorkDay,
|
||||
now.Offset);
|
||||
|
||||
DateTimeOffset nextAttempt = nextWorkDayStart;
|
||||
|
||||
// Get the rate limiter's actual remaining lockout duration.
|
||||
if (context.Lease.TryGetMetadata(
|
||||
MetadataName.RetryAfter,
|
||||
out TimeSpan retryAfter))
|
||||
// Disable the rate limiter on non-work days.
|
||||
if (workDayService.IsNonWorkDay(now))
|
||||
{
|
||||
DateTimeOffset limiterReset = now.Add(retryAfter);
|
||||
|
||||
if (limiterReset > nextAttempt)
|
||||
{
|
||||
nextAttempt = limiterReset;
|
||||
}
|
||||
return RateLimitPartition.GetNoLimiter("NoLimiter");
|
||||
}
|
||||
|
||||
string formattedNextAttempt = nextAttempt.ToString(
|
||||
"dddd d MMMM 'klockan' HH:mm",
|
||||
CultureInfo.GetCultureInfo("sv-SE"));
|
||||
string ipAddress =
|
||||
httpContext.Connection.RemoteIpAddress?.ToString()
|
||||
?? "Unknown";
|
||||
|
||||
httpContext.Response.ContentType = "application/json";
|
||||
// Include today's date in the partition key so a new
|
||||
// partition is created automatically at midnight.
|
||||
string partitionKey = $"{ipAddress}:{now:yyyy-MM-dd}";
|
||||
|
||||
httpContext.Response.Headers.RetryAfter = nextAttempt
|
||||
.ToUniversalTime()
|
||||
.ToString("R", CultureInfo.InvariantCulture);
|
||||
|
||||
await httpContext.Response.WriteAsync(
|
||||
JsonSerializer.Serialize(new
|
||||
return RateLimitPartition.GetFixedWindowLimiter(
|
||||
partitionKey,
|
||||
_ => new FixedWindowRateLimiterOptions
|
||||
{
|
||||
message = $"Posten delas ut en gång per arbetsdag. Gör ett nytt försök {formattedNextAttempt}."
|
||||
}),
|
||||
PermitLimit = 1,
|
||||
Window = TimeSpan.FromDays(1)
|
||||
});
|
||||
});
|
||||
|
||||
options.RejectionStatusCode =
|
||||
StatusCodes.Status429TooManyRequests;
|
||||
|
||||
options.OnRejected = async (context, cancellationToken) =>
|
||||
{
|
||||
DateTime now = DateTime.Now;
|
||||
DateTime nextMidnight = now.Date.AddDays(1);
|
||||
|
||||
int retryAfterSeconds = (int)Math.Ceiling(
|
||||
(nextMidnight - now).TotalSeconds);
|
||||
|
||||
context.HttpContext.Response.ContentType = "application/json";
|
||||
|
||||
context.HttpContext.Response.Headers.RetryAfter = retryAfterSeconds.ToString();
|
||||
|
||||
string response = JsonSerializer.Serialize(new
|
||||
{
|
||||
message = "Posten delas ut en gång om dagen. Gör ett nytt försök imorgon."
|
||||
});
|
||||
|
||||
await context.HttpContext.Response.WriteAsync(
|
||||
response,
|
||||
cancellationToken);
|
||||
};
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user