BREAKING CHANGE(request): introduce lazy request body parsing via ctx.json()/text()/arrayBuffer()/formData and remove IRequestContext.body

This commit is contained in:
2025-12-20 06:55:47 +00:00
parent 39f0cdf380
commit 4a17bf39c6
9 changed files with 191 additions and 65 deletions

View File

@@ -44,8 +44,9 @@ class UserController {
}
@Post('/users')
createUser(ctx: IRequestContext<{ name: string; email: string }>) {
return { id: 'new-id', ...ctx.body };
async createUser(ctx: IRequestContext<{ name: string; email: string }>) {
const body = await ctx.json();
return { id: 'new-id', ...body };
}
}
@@ -75,8 +76,9 @@ class ApiController {
}
@Post('/items') // POST /api/v1/items
createItem(ctx: IRequestContext<{ name: string }>) {
return { created: ctx.body.name };
async createItem(ctx: IRequestContext<{ name: string }>) {
const body = await ctx.json();
return { created: body.name };
}
@Put('/items/:id') // PUT /api/v1/items/:id
@@ -345,8 +347,7 @@ Every handler receives a typed request context:
```typescript
interface IRequestContext<TBody = unknown> {
request: Request; // Original Web Standards Request
body: TBody; // Parsed and typed body
request: Request; // Original Web Standards Request (body never consumed by framework)
params: Record<string, string>; // URL path parameters
query: Record<string, string>; // Query string parameters
headers: Headers; // Request headers
@@ -355,9 +356,17 @@ interface IRequestContext<TBody = unknown> {
url: URL; // Full URL object
runtime: 'node' | 'deno' | 'bun'; // Current runtime
state: Record<string, unknown>; // Per-request state bag
// Lazy body parsing methods (cached after first call)
json(): Promise<TBody>; // Parse body as JSON (typed)
text(): Promise<string>; // Parse body as text
arrayBuffer(): Promise<ArrayBuffer>; // Parse body as binary
formData(): Promise<FormData>; // Parse body as form data
}
```
Body parsing is lazy - the request body is only consumed when you call `json()`, `text()`, etc. This allows raw access to `ctx.request` for cases like signature verification.
## Custom Request Handler
Bypass decorator routing entirely: