HTTP
HTTP support lives in @bunito/http. Add it when an application needs controllers, routes, middleware, request injections, JSON handling, or HTTP exceptions.
Installation
Install the HTTP package:
bun add @bunito/httpIf you want schema-backed validation, add Zod:
bun add zodEnable HTTP
Import HttpModule in the application module:
import { LoggerModule, Module } from '@bunito/bunito';
import { HttpModule } from '@bunito/http';
@Module({
imports: [LoggerModule, HttpModule],
})
class AppModule {}The HTTP package builds on the server package and registers routes from controller metadata.
Controllers
Controllers are classes decorated with @Controller():
import { Logger, Provider } from '@bunito/bunito';
import { Controller, Get } from '@bunito/http';
@Provider()
class UsersService {
findAll(): string[] {
return ['Ada', 'Grace'];
}
}
@Controller('/users', {
injects: [UsersService, Logger],
})
class UsersController {
constructor(
private readonly usersService: UsersService,
private readonly logger: Logger,
) {}
@Get()
list(): Response {
this.logger.debug('list() called');
return Response.json({
users: this.usersService.findAll(),
});
}
}Register the controller in a module:
@Module({
imports: [LoggerModule, HttpModule],
providers: [UsersService],
controllers: [UsersController],
})
class AppModule {}Routes
Use route decorators for HTTP methods:
import { Delete, Get, Patch, Post, Put } from '@bunito/http';Available decorators include Get, Post, Put, Patch, Delete, All, and Route.
Request Injections
HTTP handlers can receive request data through explicit injections:
import { Controller, Get, Params, Query } from '@bunito/http';
import { z } from 'zod';
const ParamsSchema = z.object({
id: z.string(),
});
const QuerySchema = z.object({
include: z.string().default('summary'),
});
@Controller('/users')
class UsersController {
@Get('/:id', {
injects: [Params(ParamsSchema), Query(QuerySchema)],
})
getUser(
params: Params<typeof ParamsSchema>,
query: Query<typeof QuerySchema>,
): Response {
return Response.json({ params, query });
}
}Important injections:
Params: route paramsQuery: URL query valuesBody: parsed request bodyMethod: HTTP method
JSON Middleware
Use JSONModule and JSONMiddleware to work with plain object responses and JSON bodies:
import {
Body,
Controller,
JSONMiddleware,
JSONModule,
Post,
UseMiddleware,
} from '@bunito/http';
import { z } from 'zod';
const BodySchema = z.object({
name: z.string(),
});
@Controller('/users')
@UseMiddleware(JSONMiddleware)
class UsersController {
@Post('/', {
injects: [Body(BodySchema)],
})
createUser(body: Body<typeof BodySchema>): Record<string, unknown> {
return {
created: true,
body,
};
}
}
@Module({
imports: [LoggerModule, HttpModule, JSONModule],
controllers: [UsersController],
})
class AppModule {}Prefixes And Middleware
UsePrefix and UseMiddleware can be applied at module level:
import { Module } from '@bunito/bunito';
import { JSONMiddleware, JSONModule, UseMiddleware, UsePrefix } from '@bunito/http';
@Module({
imports: [JSONModule],
controllers: [UsersController],
})
@UsePrefix('/api')
@UseMiddleware(JSONMiddleware)
class ApiModule {}This keeps route groups local to a feature module.
Exceptions
HTTP exceptions are exported from @bunito/http:
import { NotFoundException } from '@bunito/http';
throw new NotFoundException();Use them when a handler needs to stop normal response flow with an HTTP error.
Tutorials
Build these ideas step by step:
