77use Noxlogic \RateLimitBundle \Events \GenerateKeyEvent ;
88use Noxlogic \RateLimitBundle \Events \RateLimitEvents ;
99use Noxlogic \RateLimitBundle \Exception \RateLimitExceptionInterface ;
10+ use Noxlogic \RateLimitBundle \Exception \Storage \RateLimitStorageExceptionInterface ;
1011use Noxlogic \RateLimitBundle \Service \RateLimitService ;
1112use Noxlogic \RateLimitBundle \Util \PathLimitProcessor ;
1213use Symfony \Component \HttpFoundation \Request ;
@@ -33,6 +34,9 @@ public function __construct(
3334 $ this ->pathLimitProcessor = $ pathLimitProcessor ;
3435 }
3536
37+ /**
38+ * @throws RateLimitStorageExceptionInterface
39+ */
3640 public function onKernelController (ControllerEvent $ event ): void
3741 {
3842 // Skip if the bundle isn't enabled (for instance in test environment)
@@ -68,31 +72,39 @@ public function onKernelController(ControllerEvent $event): void
6872
6973 $ key = $ this ->getKey ($ event , $ rateLimit , $ rateLimits );
7074
71- // Ratelimit the call
72- $ rateLimitInfo = $ this ->rateLimitService ->limitRate ($ key );
73- if (! $ rateLimitInfo ) {
74- // Create new rate limit entry for this call
75- $ rateLimitInfo = $ this ->rateLimitService ->createRate ($ key , $ rateLimit ->getLimit (), $ rateLimit ->getPeriod ());
75+ $ shouldFailOpenOnStorageError = $ rateLimit ->failOpen ?? $ this ->getParameter ('fail_open ' , false );
76+ try {
77+ // Ratelimit the call
78+ $ rateLimitInfo = $ this ->rateLimitService ->limitRate ($ key );
7679 if (! $ rateLimitInfo ) {
77- // @codeCoverageIgnoreStart
78- return ;
79- // @codeCoverageIgnoreEnd
80+ // Create new rate limit entry for this call
81+ $ rateLimitInfo = $ this ->rateLimitService ->createRate ($ key , $ rateLimit ->getLimit (), $ rateLimit ->getPeriod ());
82+ if (! $ rateLimitInfo ) {
83+ // @codeCoverageIgnoreStart
84+ return ;
85+ // @codeCoverageIgnoreEnd
86+ }
8087 }
81- }
82-
8388
84- // Store the current rating info in the request attributes
85- $ request ->attributes ->set ('rate_limit_info ' , $ rateLimitInfo );
86-
87- // Reset the rate limits
88- if (time () >= $ rateLimitInfo ->getResetTimestamp ()) {
89- $ this ->rateLimitService ->resetRate ($ key );
90- $ rateLimitInfo = $ this ->rateLimitService ->createRate ($ key , $ rateLimit ->getLimit (), $ rateLimit ->getPeriod ());
91- if (! $ rateLimitInfo ) {
92- // @codeCoverageIgnoreStart
89+ // Store the current rating info in the request attributes
90+ $ request ->attributes ->set ('rate_limit_info ' , $ rateLimitInfo );
91+
92+ // Reset the rate limits
93+ if (time () >= $ rateLimitInfo ->getResetTimestamp ()) {
94+ $ this ->rateLimitService ->resetRate ($ key );
95+ $ rateLimitInfo = $ this ->rateLimitService ->createRate ($ key , $ rateLimit ->getLimit (), $ rateLimit ->getPeriod ());
96+ if (! $ rateLimitInfo ) {
97+ // @codeCoverageIgnoreStart
98+ return ;
99+ // @codeCoverageIgnoreEnd
100+ }
101+ }
102+ } catch (RateLimitStorageExceptionInterface $ storageException ) {
103+ if ($ shouldFailOpenOnStorageError ) {
93104 return ;
94- // @codeCoverageIgnoreEnd
95105 }
106+
107+ throw $ storageException ;
96108 }
97109
98110 // When we exceeded our limit, return a custom error response
0 commit comments