Controllers — HTTP Request Handlers

A Class Whose Methods Are Route Handlers

Controllers — HTTP Request Handlers

Controllers receive incoming HTTP requests and return responses. Methods are decorated with HTTP verbs to bind them to routes.

4 min read Level 2/5 #nestjs#controllers#http
What you'll learn
  • Decorate a class with `@Controller('path')`
  • Define `@Get`/`@Post` handlers
  • Let return values auto-serialize to JSON

A controller in Nest is just a class. Its methods become HTTP handlers when you decorate them with verb decorators. The class itself gets a route prefix from @Controller().

Your First Controller

import { Controller, Get, Post, Body } from '@nestjs/common';
import { UsersService } from './users.service';

@Controller('users')
export class UsersController {
  constructor(private readonly users: UsersService) {}

  @Get()
  list() {
    return this.users.findAll();
  }

  @Post()
  create(@Body() body: { name: string }) {
    return this.users.create(body.name);
  }
}

That class declares two endpoints:

  • GET /users returns users.findAll()
  • POST /users reads the JSON body and calls users.create()

Auto-Serialization

You don’t call res.json(...) or set Content-Type. Whatever your method returns (object, array, string, number) Nest serializes to JSON and sends back with a 200 for @Get or 201 for @Post. Returning a Promise works too — Nest awaits it.

Constructor Injection

Notice how UsersService arrives via the constructor. The private readonly shorthand creates the field and assigns it in one line. Nest’s DI container does the wiring; you never new UsersService() yourself.

Registering the Controller

A controller only handles routes after you list it in a module:

import { Module } from '@nestjs/common';
import { UsersController } from './users.controller';
import { UsersService } from './users.service';

@Module({
  controllers: [UsersController],
  providers: [UsersService],
})
export class UsersModule {}

If a controller seems “dead” — request hits 404 — almost always the fix is adding it to a module that gets loaded.

Quick Sanity Check

curl http://localhost:3000/users
curl -X POST http://localhost:3000/users \
  -H 'content-type: application/json' \
  -d '{"name":"Ada"}'

That’s enough to see both handlers fire. From here it’s all about adding more decorators to shape the request/response.

Providers & Services →