88use Neuron \Routing \RateLimit \RateLimitResponse ;
99use Neuron \Routing \RateLimit \Storage \IRateLimitStorage ;
1010use Neuron \Routing \RateLimit \Storage \RateLimitStorageFactory ;
11+ use Neuron \Routing \IIpResolver ;
12+ use Neuron \Routing \DefaultIpResolver ;
1113use Neuron \Patterns \Registry ;
1214use Neuron \Log \Log ;
1315
@@ -26,24 +28,29 @@ class RateLimitFilter extends Filter
2628 private string $ _keyStrategy ;
2729 private array $ _whitelist ;
2830 private array $ _blacklist ;
31+ private IIpResolver $ _ipResolver ;
2932
3033 /**
3134 * @param RateLimitConfig $config Rate limit configuration
3235 * @param string $keyStrategy Key generation strategy ('ip', 'user', 'route', 'custom')
3336 * @param array $whitelist IP addresses or user IDs to exempt from rate limiting
3437 * @param array $blacklist IP addresses or user IDs to apply stricter limits
38+ * @param IIpResolver|null $ipResolver Optional IP resolver (defaults to DefaultIpResolver)
39+ * @throws \Exception
3540 */
3641 public function __construct (
3742 RateLimitConfig $ config ,
3843 string $ keyStrategy = 'ip ' ,
3944 array $ whitelist = [],
40- array $ blacklist = []
45+ array $ blacklist = [],
46+ ?IIpResolver $ ipResolver = null
4147 )
4248 {
4349 $ this ->_config = $ config ;
4450 $ this ->_keyStrategy = $ keyStrategy ;
4551 $ this ->_whitelist = $ whitelist ;
4652 $ this ->_blacklist = $ blacklist ;
53+ $ this ->_ipResolver = $ ipResolver ?? new DefaultIpResolver ();
4754
4855 // Get base path from registry if available
4956 $ basePath = Registry::getInstance ()->get ( 'BasePath ' ) ?? '' ;
@@ -59,7 +66,7 @@ function( RouteMap $route ) { $this->checkRateLimit( $route ); },
5966 }
6067
6168 /**
62- * Check rate limit for the current request.
69+ * Check the rate limit for the current request.
6370 *
6471 * @param RouteMap $route
6572 * @return void
@@ -112,45 +119,23 @@ protected function checkRateLimit( RouteMap $route ): void
112119 */
113120 protected function generateKey ( RouteMap $ route ): string
114121 {
115- switch ( $ this ->_keyStrategy )
122+ return match ( $ this ->_keyStrategy )
116123 {
117- case 'ip ' :
118- return $ this ->getClientIp ();
119-
120- case 'user ' :
121- return $ this ->getUserId ();
122-
123- case 'route ' :
124- return $ this ->getClientIp () . ': ' . $ route ->getPath ();
125-
126- case 'custom ' :
127- return $ this ->getCustomKey ( $ route );
128-
129- default :
130- return $ this ->getClientIp ();
131- }
124+ 'user ' => $ this ->getUserId (),
125+ 'route ' => $ this ->getClientIp () . ': ' . $ route ->getPath (),
126+ 'custom ' => $ this ->getCustomKey ( $ route ),
127+ default => $ this ->getClientIp (),
128+ };
132129 }
133130
134131 /**
135- * Get client IP address.
132+ * Get the client IP address using the configured IP resolver .
136133 *
137134 * @return string
138135 */
139136 protected function getClientIp (): string
140137 {
141- // Check for forwarded IP (proxy/load balancer)
142- if ( !empty ( $ _SERVER ['HTTP_X_FORWARDED_FOR ' ] ) )
143- {
144- $ ips = explode ( ', ' , $ _SERVER ['HTTP_X_FORWARDED_FOR ' ] );
145- return trim ( $ ips [0 ] );
146- }
147-
148- if ( !empty ( $ _SERVER ['HTTP_X_REAL_IP ' ] ) )
149- {
150- return $ _SERVER ['HTTP_X_REAL_IP ' ];
151- }
152-
153- return $ _SERVER ['REMOTE_ADDR ' ] ?? '0.0.0.0 ' ;
138+ return $ this ->_ipResolver ->resolve ( $ _SERVER );
154139 }
155140
156141 /**
@@ -173,7 +158,7 @@ protected function getUserId(): string
173158 }
174159
175160 /**
176- * Get custom key for rate limiting.
161+ * Get a custom key for rate limiting.
177162 *
178163 * @param RouteMap $route
179164 * @return string
@@ -224,7 +209,7 @@ protected function getLimit( string $key ): int
224209 }
225210
226211 /**
227- * Get time window for a key.
212+ * Get the time window for a key.
228213 *
229214 * @param string $key
230215 * @return int
@@ -236,7 +221,7 @@ protected function getWindow( string $key ): int
236221 }
237222
238223 /**
239- * Add rate limit headers to response.
224+ * Add the rate limit headers to response.
240225 *
241226 * @param string $key
242227 * @param int $limit
@@ -283,4 +268,4 @@ public function clear(): void
283268 {
284269 $ this ->_storage ->clear ();
285270 }
286- }
271+ }
0 commit comments