From 790a5d086f1bca4296cddcc0d79e9cd7f4cf37a1 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me=20Benoit?= Date: Wed, 11 Feb 2026 16:46:57 +0100 Subject: [PATCH] feat(ui-server): add HTTP body size and rate limiting Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus --- .../ui-server/UIHttpServer.ts | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/charging-station/ui-server/UIHttpServer.ts b/src/charging-station/ui-server/UIHttpServer.ts index 4b122606..a86f7218 100644 --- a/src/charging-station/ui-server/UIHttpServer.ts +++ b/src/charging-station/ui-server/UIHttpServer.ts @@ -23,10 +23,19 @@ import { logPrefix, } from '../../utils/index.js' import { AbstractUIServer } from './AbstractUIServer.js' +import { + createBodySizeLimiter, + createRateLimiter, + DEFAULT_MAX_BODY_SIZE, + DEFAULT_RATE_LIMIT, + DEFAULT_RATE_WINDOW, +} from './UIServerSecurity.js' import { isProtocolAndVersionSupported } from './UIServerUtils.js' const moduleName = 'UIHttpServer' +const rateLimiter = createRateLimiter(DEFAULT_RATE_LIMIT, DEFAULT_RATE_WINDOW) + enum HttpMethods { GET = 'GET', PATCH = 'PATCH', @@ -87,6 +96,20 @@ export class UIHttpServer extends AbstractUIServer { } private requestListener (req: IncomingMessage, res: ServerResponse): void { + // Rate limiting check + const clientIp = req.socket.remoteAddress ?? 'unknown' + if (!rateLimiter(clientIp)) { + res + .writeHead(StatusCodes.TOO_MANY_REQUESTS, { + 'Content-Type': 'text/plain', + 'Retry-After': '60', + }) + .end(`${StatusCodes.TOO_MANY_REQUESTS.toString()} Too Many Requests`) + res.destroy() + req.destroy() + return + } + this.authenticate(req, err => { if (err != null) { res @@ -144,8 +167,19 @@ export class UIHttpServer extends AbstractUIServer { } const bodyBuffer: Uint8Array[] = [] + const checkBodySize = createBodySizeLimiter(DEFAULT_MAX_BODY_SIZE) req .on('data', (chunk: Uint8Array) => { + if (!checkBodySize(chunk.length)) { + res + .writeHead(StatusCodes.REQUEST_TOO_LONG, { + 'Content-Type': 'text/plain', + }) + .end(`${StatusCodes.REQUEST_TOO_LONG.toString()} Payload Too Large`) + res.destroy() + req.destroy() + return + } bodyBuffer.push(chunk) }) .on('end', () => { -- 2.53.0