Controllers and routing

One thing that NestJS has that Angular does not is controllers. Controllers are used to define endpoints in NestJS and to associate requests/parameters to functions/arguments, shown as follows:

How Controllers are used in NestJS

NestJS's routing mechanism is responsible for identifying which controller should receive and process incoming requests. Indeed, NestJS's routing system is built upon Express or, optionally, Fastify (https://www.fastify.io).

A controller's purpose is to handle the requests targeting specific routes of the application. The routing mechanism controls which controllers/methods receive which requests.

Usually, controllers are associated with multiple routes, each of which implements different operations. For instance, in a Customer controller, we could define routes to handle the different CRUD operations.

NestJS controllers are created using TypeScript classes and dedicated decorators such as @Get(), @Post(), and @Body. These decorators associate the classes/methods with the metadata allowing NestJS to define its internal routing table.

Let's take a look at an example created using the CLI:

npx @nestjs/cli generate controller hello

Here is an example controller:

import {Controller, Get, Query} from '@nestjs/common'; 
 
@Controller('/') 
export class HelloController { 
    @Get('hello') 
    hello(@Query('name') name?: string) { 
        const personName = name? name: 'stranger'; 
        return `Hello ${personName}`; 
    } 
} 

Unsurprisingly, controllers are declared using the @Controller decorator. Within that decorator, we can set an optional base path associated with this controller. Here, we have set it to /to match the root route of the backend, but it isn't mandatory in this case.

The @Get('hello') decorator associates our hello method with the /hello route, which means our method will be invoked whenever a GET request is sent toward /hello. The method name actually doesn't matter. All that matters is the combination of the base path defined on the @Controller and/or the one defined on the method's decorator.

Also notice the @Query decorator, which we have used to retrieve the value of a query parameter (if present). In the method, we use the associated value (or lack thereof) to determine what message to return.

Accessing the URL http://localhost:3000/hello results in the following response: Hello stranger. If you provide the query parameter in the URL http://localhost:3000/hello?name=world, then the response becomes Hello world. Neat!

Of course, you can also access other parts of the request objects:

Check out the official controller documentation to learn about how NestJS handles routing, method parameters, and return values.