File tree Expand file tree Collapse file tree 3 files changed +34
-4
lines changed
tests/LinkDotNet.Blog.IntegrationTests Expand file tree Collapse file tree 3 files changed +34
-4
lines changed Original file line number Diff line number Diff line change 1212using LinkDotNet . Blog . Infrastructure . Persistence ;
1313using LinkDotNet . Blog . Web . Features ;
1414using Microsoft . AspNetCore . Mvc ;
15+ using Microsoft . AspNetCore . RateLimiting ;
1516using Microsoft . Extensions . Options ;
1617using InvalidOperationException = System . InvalidOperationException ;
1718
1819namespace LinkDotNet . Blog . Web . Controller ;
1920
2021[ Route ( "feed.rss" ) ]
22+ [ EnableRateLimiting ( "ip" ) ]
2123public sealed class RssFeedController : ControllerBase
2224{
2325 private static readonly XmlWriterSettings Settings = CreateXmlWriterSettings ( ) ;
Original file line number Diff line number Diff line change 1+ using System ;
2+ using System . Threading . RateLimiting ;
13using System . Threading . Tasks ;
24using Blazored . Toast ;
35using Blazorise ;
810using LinkDotNet . Blog . Web . RegistrationExtensions ;
911using Microsoft . AspNetCore . Builder ;
1012using Microsoft . AspNetCore . Diagnostics . HealthChecks ;
13+ using Microsoft . AspNetCore . Http ;
1114using Microsoft . Extensions . DependencyInjection ;
1215using Microsoft . Extensions . Hosting ;
1316
@@ -40,6 +43,17 @@ private static void RegisterServices(WebApplicationBuilder builder)
4043 options . MaximumReceiveMessageSize = 1024 * 1024 ;
4144 } ) ;
4245
46+ builder . Services . AddRateLimiter ( options =>
47+ {
48+ options . RejectionStatusCode = StatusCodes . Status429TooManyRequests ;
49+ options . AddPolicy < string > ( "ip" , httpContext =>
50+
51+ RateLimitPartition . GetFixedWindowLimiter (
52+ httpContext . Connection . RemoteIpAddress ? . ToString ( ) ?? string . Empty ,
53+ _ => new FixedWindowRateLimiterOptions { PermitLimit = 15 , Window = TimeSpan . FromMinutes ( 1 ) } )
54+ ) ;
55+ } ) ;
56+
4357 builder . Services . AddConfiguration ( ) ;
4458
4559 builder . Services . AddBlazoredToast ( ) ;
@@ -91,6 +105,7 @@ private static void ConfigureApp(WebApplication app)
91105 app . UseAuthentication ( ) ;
92106 app . UseAuthorization ( ) ;
93107
108+ app . UseRateLimiter ( ) ;
94109 app . MapControllers ( ) ;
95110 app . MapBlazorHub ( ) ;
96111 app . MapFallbackToPage ( "/_Host" ) ;
Original file line number Diff line number Diff line change @@ -63,13 +63,26 @@ public async Task ShouldAllowDotsForFreeTextSearch()
6363 result . IsSuccessStatusCode . ShouldBeTrue ( ) ;
6464 }
6565
66+ [ Fact ]
67+ public async Task RssFeedShouldBeRateLimited ( )
68+ {
69+ const int numberOfRequests = 16 ;
70+ using var client = factory . CreateClient ( ) ;
71+
72+ for ( var i = 0 ; i < numberOfRequests - 1 ; i ++ )
73+ {
74+ var result = await client . GetAsync ( "/feed.rss" ) ;
75+ result . IsSuccessStatusCode . ShouldBeTrue ( ) ;
76+ }
77+
78+ var lastResult = await client . GetAsync ( "/feed.rss" ) ;
79+ lastResult . IsSuccessStatusCode . ShouldBeFalse ( ) ;
80+ }
81+
6682 public void Dispose ( ) => factory ? . Dispose ( ) ;
6783
6884 public async ValueTask DisposeAsync ( )
6985 {
70- if ( factory is not null )
71- {
72- await factory . DisposeAsync ( ) ;
73- }
86+ await factory . DisposeAsync ( ) ;
7487 }
7588}
You can’t perform that action at this time.
0 commit comments