feat: rate limiting, shared DB instance, TCP_NODELAY fix
- Add rate limiter to TCP and HTTP servers - Share single LSMTree between TCP and HTTP servers - Replace unsafe cast[string]/cast[seq[byte]] with safe helpers - Stabilize gossip UDP socket with exponential backoff - Fix TCP_NODELAY via low-level setSockOptInt(IPPROTO_TCP) (asyncnet.setSockOpt(OptNoDelay) uses SOL_SOCKET and fails) - Apply TCP_NODELAY to server and websocket sockets
This commit is contained in:
@@ -19,6 +19,7 @@ import ../protocol/wire
|
||||
import ../core/websocket
|
||||
import jwt as jwtlib
|
||||
import ../protocol/auth
|
||||
import ../protocol/ratelimit
|
||||
|
||||
type
|
||||
HttpServer* = ref object
|
||||
@@ -29,6 +30,7 @@ type
|
||||
metrics*: Metrics
|
||||
secretKey*: string
|
||||
authManager*: AuthManager
|
||||
rateLimiter*: RateLimiter
|
||||
ws*: WsServer
|
||||
|
||||
Metrics* = ref object
|
||||
@@ -38,13 +40,12 @@ type
|
||||
selectCount*: int
|
||||
activeConnections*: int
|
||||
|
||||
proc newHttpServer*(config: BaraConfig): HttpServer =
|
||||
let dataDir = config.dataDir / "server"
|
||||
let db = newLSMTree(dataDir)
|
||||
proc newHttpServerWithDb*(config: BaraConfig, db: LSMTree): HttpServer =
|
||||
let ctx = newExecutionContext(db)
|
||||
ctx.txnManager = newTxnManager()
|
||||
let secret = config.getEffectiveJwtSecret()
|
||||
let ws = newWsServer(config, secret)
|
||||
let rl = newRateLimiter(rlaTokenBucket, config.rateLimitGlobal, config.rateLimitPerClient)
|
||||
ctx.onChange = proc(ev: ChangeEvent) =
|
||||
let msg = $ev.kind & " " & ev.table
|
||||
asyncCheck ws.broadcastToTable(ev.table, msg)
|
||||
@@ -52,8 +53,14 @@ proc newHttpServer*(config: BaraConfig): HttpServer =
|
||||
HttpServer(config: config, running: false, db: db, ctx: ctx,
|
||||
secretKey: secret,
|
||||
authManager: am,
|
||||
rateLimiter: rl,
|
||||
metrics: Metrics(), ws: ws)
|
||||
|
||||
proc newHttpServer*(config: BaraConfig): HttpServer =
|
||||
let dataDir = config.dataDir / "server"
|
||||
let db = newLSMTree(dataDir)
|
||||
return newHttpServerWithDb(config, db)
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# JWT helpers
|
||||
# ----------------------------------------------------------------------
|
||||
@@ -124,6 +131,13 @@ proc queryHandler(server: HttpServer): RequestHandler =
|
||||
userId = uid
|
||||
role = r
|
||||
|
||||
# Rate limiting
|
||||
let clientKey = request.headers["X-Forwarded-For"]
|
||||
let rateLimitKey = if clientKey.len > 0: clientKey else: "http-global"
|
||||
if not server.rateLimiter.allowRequest(rateLimitKey):
|
||||
ctx.json(%*{"error": "Rate limit exceeded"}, 429)
|
||||
return
|
||||
|
||||
let body = parseJson(request.body)
|
||||
if body == nil or "query" notin body:
|
||||
ctx.json(%*{"error": "Missing 'query' in request body"}, 400)
|
||||
|
||||
Reference in New Issue
Block a user