Skip to content

Body Limits & Security

Moost HTTP provides built-in protection against oversized request bodies and compression bombs. Limits can be configured at three levels, each overriding the previous.

App-wide defaults

Pass requestLimits when creating the HTTP adapter:

ts
import { MoostHttp } from '@moostjs/event-http'
import { Moost } from 'moost'

const app = new Moost()

void app.adapter(new MoostHttp({
    requestLimits: {
        maxCompressed: 5 * 1024 * 1024,   // 5 MB compressed (default: 1 MB)
        maxInflated: 50 * 1024 * 1024,     // 50 MB decompressed (default: 10 MB)
        maxRatio: 200,                     // compression ratio limit (default: 100)
        readTimeoutMs: 30_000,             // body read timeout (default: 10 000 ms)
    },
})).listen(3000)

void app.init()
OptionDefaultDescription
maxCompressed1 MBMax compressed body size in bytes
maxInflated10 MBMax decompressed body size in bytes
maxRatio100Max compression ratio (zip-bomb protection)
readTimeoutMs10 000 msBody read timeout

Per-handler overrides

Use decorators to set limits on specific handlers or controllers:

ts
import {
    BodySizeLimit,
    CompressedBodySizeLimit,
    BodyReadTimeoutMs,
    Post,
} from '@moostjs/event-http'
import { Controller, Body } from 'moost'

@Controller('upload')
export class UploadController {
    @Post('')
    @BodySizeLimit(50 * 1024 * 1024)           // 50 MB inflated
    @CompressedBodySizeLimit(10 * 1024 * 1024)  // 10 MB compressed
    @BodyReadTimeoutMs(60_000)                  // 60 seconds
    async upload(@Body() payload: unknown) {
        return { received: true }
    }
}

These decorators work on both handlers and controllers. When applied to a controller, all handlers inherit the limits.

Global interceptors

For organization-wide policies applied through code (e.g., from a shared library), use the global interceptor helpers:

ts
import {
    globalBodySizeLimit,
    globalCompressedBodySizeLimit,
    globalBodyReadTimeoutMs,
} from '@moostjs/event-http'
import { Moost } from 'moost'

const app = new Moost()
app.applyGlobalInterceptors(
    globalBodySizeLimit(20 * 1024 * 1024),
    globalCompressedBodySizeLimit(5 * 1024 * 1024),
    globalBodyReadTimeoutMs(15_000),
)

Override precedence

Limits are applied in this order (later wins):

  1. Constructor defaults (requestLimits)
  2. Global interceptors (app.applyGlobalInterceptors(...))
  3. Controller-level decorators (@BodySizeLimit on class)
  4. Handler-level decorators (@BodySizeLimit on method)

404 handling

When no route matches a request, Moost runs the response through the global interceptor chain before returning a 404 Resource Not Found error. This means your global error handlers and logging interceptors will catch 404s too.

Custom server integration

Using getServerCb()

To integrate Moost HTTP with an existing Node.js server or serverless runtime, use getServerCb():

ts
import { MoostHttp } from '@moostjs/event-http'
import { Moost } from 'moost'
import { createServer } from 'http'

const app = new Moost()
const http = app.adapter(new MoostHttp())

void app.registerControllers(MyController).init()

// Use with a custom Node.js server
const server = createServer(http.getServerCb())
server.listen(3000)

This is useful for:

  • Serverless functions — pass the callback to your serverless framework
  • Custom HTTPS — create an https.createServer with your own certificates
  • Testing — use with libraries like supertest

Released under the MIT License.