#[controller]. Route handlers live in an impl block annotated with #[routes]. When the module builds, nestrs registers every handler in that impl block as an Axum route under the controller’s prefix.
Defining a controller
prefix argument sets the base path for every route in the controller. Paths are joined with each handler’s path, so prefix = "/api" + #[get("/")] produces GET /api/.
Optional attributes
Use the
#[version] attribute separately to apply a version to an entire controller struct:
Registering routes with #[routes]
The #[routes] macro annotates an impl block and takes a state argument that names the injected service type. nestrs uses this to build an Axum router with the correct State type:
state must be a type registered in the module’s providers list. nestrs resolves it from the ProviderRegistry and injects it as Axum State.Direct service parameter injection
Handlers do not need to manually wrap services inState(service): State<Arc<AppService>>. If a handler parameter is an Arc<T> matching the state type, #[routes] automatically transforms it into an Axum State extractor during macro expansion.
Explicit extractor syntax (State(service): State<Arc<AppService>>) remains fully supported for backward compatibility or when using custom state wrappers.
Multi-service controllers (tuple state)
Controllers that depend on multiple services do not require manual composite state structs. You can provide a tuple of provider types directly tostate:
ProviderRegistry via RouteStateFromRegistry. Handlers only extract the specific services they declare in their parameters.
HTTP method macros
nestrs provides a macro for every HTTP method:
Each macro takes the route path as its argument. The path is appended to the controller’s prefix.
Route examples
Basic GET and POST
Path parameters
Use Axum’sPath extractor. Parameters are declared in the route path with a colon prefix (:id):
Query parameters
Use Axum’sQuery extractor with a deserializable struct:
JSON request bodies
Use Axum’sJson extractor for unvalidated JSON, or ValidatedBody to run validator constraints automatically:
Response customization
Custom HTTP status code
Custom response headers
Redirects
Versioning a single route
You can version a single route within a controller using#[ver] while leaving other routes at the controller’s default version:
Registering the controller in a module
Controllers must be listed in thecontrollers field of their module: