HTTP
OPRA's HTTP layer is a decorator-driven API framework that sits on top of adapters such as Express and NestJS. You define controllers and operations once using TypeScript decorators; the adapter handles routing, content negotiation, and lifecycle hooks. Query parameters, path parameters, headers, cookies, and request bodies are automatically validated and decoded against their declared types before your handler is called, and response payloads are encoded and validated before they are sent to the client.
An HTTP API in OPRA is built from two decorator types:
@HttpController()— groups related operations under a shared URL path. Controllers can be nested to model resource hierarchies.@HttpOperation()— defines a single HTTP endpoint on a controller method. Shorthand variants (HttpOperation.GET(),HttpOperation.POST(), …) set the HTTP method automatically.
Both decorators expose chainable methods for parameters, request bodies, responses, and type registration.
Controllers
@HttpController() registers a class as an HTTP controller and groups its operations under a shared URL path. Controllers can be nested to model resource hierarchies, and any parameters declared on a controller are inherited by all its operations.
Methods
@HttpOperation() and its shorthand variants (GET, POST, PUT, PATCH, DELETE, …) define individual HTTP endpoints on controller methods. Options control the path, merge behaviour, and human-readable description.
→ Methods
Entity Method Templates
HttpOperation.Entity provides pre-built decorators for standard CRUD endpoints — Create, Get, Replace, Update, Delete, FindMany, UpdateMany, DeleteMany. Each one wires up the HTTP method, path, request body, and response automatically based on the given type.
Path Parameters
Declare path parameters with .PathParam() on a controller or operation. OPRA parses and coerces them to the declared type before the handler runs.
Query Parameters
Declare query parameters with .QueryParam(). OPRA validates and coerces values — strings become numbers, dates, booleans — according to the declared type.
Headers
Read request headers through ctx.request.header(name) or ctx.request.get(name). Set response headers with ctx.response.setHeader(), appendHeader(), or the contentType() shorthand. Declare expected headers with .Header() on a controller or operation.
→ Headers
Cookies
Read parsed cookies from ctx.cookies. Set response cookies with ctx.response.cookie(name, value, options) and clear them with ctx.response.clearCookie(). Declare expected cookies with .Cookie() on a controller or operation.
→ Cookies
Reading the Request Body
Access the request body with await ctx.getBody(). OPRA validates and decodes it against the type declared by .RequestContent() before handing it to your handler.
Multipart & File Uploads
Use .MultipartContent() to handle multipart/form-data requests. Chain .File() and .Field() to declare individual parts with size limits and required flags.
Batch Requests
Send multiple HTTP requests in a single round-trip using POST /$bundle with Content-Type: multipart/mixed. Each part is an independent sub-request; responses are returned as a multipart/mixed reply. Add ?transaction=true to wrap the entire batch in a single database transaction — supported automatically by @opra/mongodb and @opra/sqb.
Sending Responses
Return a value from your handler or call ctx.response.write() / ctx.response.end() directly. OPRA encodes the return value against the type declared by .Response() and sets the Content-Type automatically.
Error Handling
Throw any of OPRA's built-in error classes (BadRequestError, NotFoundError, ForbiddenError, …) or use wrapException() to map arbitrary errors to the correct HTTP status. Validation errors are handled automatically — the framework rejects invalid input with a structured error response before your handler is called.
Schema Endpoint
Every OPRA HTTP API exposes a built-in GET /$schema endpoint that returns a full machine-readable description of the API. Use oprimp to generate typed TypeScript client code directly from this endpoint.