1
+ using System . Collections . Concurrent ;
2
+ using System . Net ;
3
+ using Microsoft . AspNetCore . Http ;
4
+ using Microsoft . AspNetCore . Mvc ;
5
+ using Microsoft . Azure . Functions . Worker ;
6
+ using Microsoft . Extensions . Logging ;
7
+
8
+ namespace firewallmon . function ;
9
+
10
+ class RequestLog
11
+ {
12
+ public List < DateTime > Requests { get ; } = new ( ) ;
13
+ }
14
+
15
+
16
+ public class Backend
17
+ {
18
+ private static readonly ConcurrentDictionary < string , RequestLog > IpLogs = new ( ) ;
19
+
20
+ private readonly ILogger < Backend > _logger ;
21
+
22
+ private int ThrottlingInterval = int . TryParse ( Environment . GetEnvironmentVariable ( "aiao_throttling_window" ) , out var interval ) ? interval : 0 ; // minutes
23
+ private int ThrottlingRequests = int . TryParse ( Environment . GetEnvironmentVariable ( "aiao_throttling_calls" ) , out var requests ) ? requests : 0 ; // max requests in the interval
24
+ private bool IsThrottlingEnabled => ThrottlingInterval > 0 && ThrottlingRequests > 0 ;
25
+
26
+ private bool ImplementThrottling ( HttpRequest req )
27
+ {
28
+ if ( ! IsThrottlingEnabled )
29
+ {
30
+ return false ;
31
+ }
32
+
33
+ string ip = req . HttpContext . Connection . RemoteIpAddress ? . ToString ( ) ?? "unknown" ;
34
+
35
+ var now = DateTime . UtcNow ;
36
+ var logEntry = IpLogs . GetOrAdd ( ip , _ => new RequestLog ( ) ) ;
37
+
38
+ lock ( logEntry )
39
+ {
40
+ logEntry . Requests . RemoveAll ( t => ( now - t ) . TotalMinutes > ThrottlingInterval ) ;
41
+
42
+ int count = logEntry . Requests . Count ;
43
+ if ( count >= ThrottlingRequests )
44
+ {
45
+ // Log the throttling event
46
+ _logger . LogError ( $ "Throttling request from IP: { ip } ") ;
47
+ return true ;
48
+ }
49
+ else
50
+ {
51
+ _logger . LogInformation ( $ "Request { count } from IP { ip } .") ;
52
+ }
53
+
54
+ logEntry . Requests . Add ( now ) ;
55
+ }
56
+
57
+ return false ;
58
+ }
59
+
60
+ public Backend ( ILogger < Backend > logger )
61
+ {
62
+ _logger = logger ;
63
+ }
64
+
65
+ [ Function ( "helloWorld" ) ]
66
+ public IActionResult Run ( [ HttpTrigger ( AuthorizationLevel . Anonymous , "get" , "post" ) ] HttpRequest req )
67
+ {
68
+ if ( ImplementThrottling ( req ) )
69
+ {
70
+ return new ContentResult
71
+ {
72
+ StatusCode = StatusCodes . Status429TooManyRequests ,
73
+ Content = "Too many requests. Please try again later."
74
+ } ;
75
+ }
76
+
77
+ string ? author = "" ;
78
+
79
+ author = Environment . GetEnvironmentVariable ( "author" ) ;
80
+ if ( string . IsNullOrEmpty ( author ) )
81
+ {
82
+ author = "unknown" ;
83
+ }
84
+
85
+ return new OkObjectResult ( $ "Hello from the other side... of the endpoint.\r \n backend owned by { author } .\r \n ") ;
86
+ }
87
+ }
0 commit comments