@@ -2,74 +2,42 @@ import { Request, Response } from 'express'
22import { getConfiguration } from '../../utils/config.js'
33import { HTTP_LOGGER } from '../../utils/logging/common.js'
44import { OceanNodeConfig } from '../../@types/OceanNode.js'
5- import { RequestLimiter } from '../../OceanNode.js'
65import {
7- CONNECTIONS_RATE_INTERVAL ,
8- DEFAULT_MAX_CONNECTIONS_PER_MINUTE
9- } from '../../utils/constants.js'
6+ checkGlobalConnectionsRateLimit ,
7+ checkRequestsRateLimit ,
8+ CommonValidation
9+ } from '../../utils/validators.js'
1010
11- // TODO we should group common stuff,
12- // we have multiple similar validation interfaces
13- export interface CommonValidation {
14- valid : boolean
15- error ?: string
16- }
17-
18- // hold data about last request made
19- const connectionsData : RequestLimiter = {
20- lastRequestTime : Date . now ( ) ,
21- requester : '' ,
22- numRequests : 0
23- }
24-
25- // midleware to validate client addresses against a denylist
26- // it also checks the global rate limit
11+ // Middleware to validate IP and apply rate limiting
2712export const requestValidator = async function ( req : Request , res : Response , next : any ) {
28- // Perform the validations.
29- const requestIP = req . headers [ 'x-forwarded-for' ] || req . socket . remoteAddress
30-
31- // grab request time
32- const requestTime = Date . now ( )
33- if ( requestTime - connectionsData . lastRequestTime > CONNECTIONS_RATE_INTERVAL ) {
34- // last one was more than 1 minute ago? reset counter
35- connectionsData . numRequests = 0
36- }
37- // always increment counter
38- connectionsData . numRequests += 1
39- // update time and requester information
40- connectionsData . lastRequestTime = requestTime
41- connectionsData . requester = requestIP
13+ const now = Date . now ( )
14+ const requestIP = ( req . headers [ 'x-forwarded-for' ] ||
15+ req . socket . remoteAddress ||
16+ '' ) as string
4217
4318 const configuration = await getConfiguration ( )
4419
45- // check if IP is allowed or denied
4620 const ipValidation = await checkIP ( requestIP , configuration )
47- // Validation failed, or an error occurred during the external request.
4821 if ( ! ipValidation . valid ) {
49- res . status ( 403 ) . send ( ipValidation . error )
50- return
22+ HTTP_LOGGER . logMessage ( `IP denied: ${ ipValidation . error } ` )
23+ return res . status ( 403 ) . send ( ipValidation . error )
5124 }
52- // check global rate limits (not ip related)
53- const requestRateValidation = checkConnectionsRateLimit ( configuration , connectionsData )
54- if ( ! requestRateValidation . valid ) {
55- res . status ( 403 ) . send ( requestRateValidation . error )
56- return
25+
26+ const rateLimitCheck = checkRequestsRateLimit ( requestIP , configuration , now )
27+ if ( ! rateLimitCheck . valid ) {
28+ HTTP_LOGGER . logMessage (
29+ `Exceeded limit of requests per minute ${ configuration . rateLimit } : ${ rateLimitCheck . error } `
30+ )
31+ return res . status ( 429 ) . send ( rateLimitCheck . error )
5732 }
58- // Validation passed.
59- next ( )
60- }
6133
62- export function checkConnectionsRateLimit (
63- configuration : OceanNodeConfig ,
64- connectionsData : RequestLimiter
65- ) : CommonValidation {
66- const connectionLimits =
67- configuration . maxConnections || DEFAULT_MAX_CONNECTIONS_PER_MINUTE
68- const ok = connectionsData . numRequests <= connectionLimits
69- return {
70- valid : ok ,
71- error : ok ? '' : 'Unauthorized request. Rate limit exceeded!'
34+ const connectionsRateValidation = checkGlobalConnectionsRateLimit ( configuration , now )
35+ if ( ! connectionsRateValidation . valid ) {
36+ res . status ( 403 ) . send ( connectionsRateValidation . error )
37+ return
7238 }
39+
40+ next ( )
7341}
7442
7543function checkIP (
0 commit comments