2024-10-27 06:10:27 +01:00
package middleware
/ *
Copyright 2024 Jonas Kaninda
Licensed under the Apache License , Version 2.0 ( the "License" ) ;
you may not use this file except in compliance with the License .
You may obtain a copy of the License at
http : //www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing , software
distributed under the License is distributed on an "AS IS" BASIS ,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
See the License for the specific language governing permissions and
limitations under the License .
* /
import (
2024-11-14 00:26:21 +01:00
"fmt"
2024-10-27 06:10:27 +01:00
"github.com/gorilla/mux"
2024-11-04 08:48:38 +01:00
"github.com/jkaninda/goma-gateway/pkg/logger"
2024-10-27 06:10:27 +01:00
"net/http"
"time"
)
// RateLimitMiddleware limits request based on the number of tokens peer minutes.
func ( rl * TokenRateLimiter ) RateLimitMiddleware ( ) mux . MiddlewareFunc {
return func ( next http . Handler ) http . Handler {
return http . HandlerFunc ( func ( w http . ResponseWriter , r * http . Request ) {
if ! rl . Allow ( ) {
2024-11-14 00:26:21 +01:00
logger . Error ( "Too many requests from IP: %s %s %s" , getRealIP ( r ) , r . URL , r . UserAgent ( ) )
//RespondWithError(w, http.StatusUnauthorized, http.StatusText(http.StatusUnauthorized), basicAuth.ErrorInterceptor)
2024-10-27 06:10:27 +01:00
// Rate limit exceeded, return a 429 Too Many Requests response
w . WriteHeader ( http . StatusTooManyRequests )
2024-11-14 00:26:21 +01:00
_ , err := w . Write ( [ ] byte ( fmt . Sprintf ( "%d Too many requests, API rate limit exceeded. Please try again later" , http . StatusTooManyRequests ) ) )
2024-10-27 06:10:27 +01:00
if err != nil {
return
}
return
}
// Proceed to the next handler if rate limit is not exceeded
next . ServeHTTP ( w , r )
} )
}
}
// RateLimitMiddleware limits request based on the number of requests peer minutes.
func ( rl * RateLimiter ) RateLimitMiddleware ( ) mux . MiddlewareFunc {
return func ( next http . Handler ) http . Handler {
return http . HandlerFunc ( func ( w http . ResponseWriter , r * http . Request ) {
2024-10-28 02:26:02 +01:00
clientID := getRealIP ( r )
2024-10-27 06:10:27 +01:00
rl . mu . Lock ( )
client , exists := rl . ClientMap [ clientID ]
if ! exists || time . Now ( ) . After ( client . ExpiresAt ) {
client = & Client {
RequestCount : 0 ,
ExpiresAt : time . Now ( ) . Add ( rl . Window ) ,
}
rl . ClientMap [ clientID ] = client
}
client . RequestCount ++
rl . mu . Unlock ( )
if client . RequestCount > rl . Requests {
2024-11-14 00:26:21 +01:00
logger . Error ( "Too many requests from IP: %s %s %s" , clientID , r . URL , r . UserAgent ( ) )
2024-11-05 20:44:06 +01:00
//Update Origin Cors Headers
if allowedOrigin ( rl . Origins , r . Header . Get ( "Origin" ) ) {
w . Header ( ) . Set ( "Access-Control-Allow-Origin" , r . Header . Get ( "Origin" ) )
}
2024-11-14 00:26:21 +01:00
RespondWithError ( w , http . StatusTooManyRequests , fmt . Sprintf ( "%d Too many requests, API rate limit exceeded. Please try again later" , http . StatusTooManyRequests ) , rl . ErrorInterceptor )
2024-10-27 06:10:27 +01:00
return
}
// Proceed to the next handler if rate limit is not exceeded
next . ServeHTTP ( w , r )
} )
}
}