Controllers
Controllers are the classes responsible for processing the incoming requests and returning requests to the client.
It's prupose is to receive a specific request, perform some business logic and return a response back to the client. For the server to know which controller will be handling which requests is made possible by hyper-express.
Controllers can group related request handling logic in a class. For example, UserController class can handle all incoming requests related to users.
Creating Controllers
Controllers are placed inside the app/http/controllers directory.
Manually Creating Controllers
To create a controller manually, you can create a file inside the app/http/controllers directory. For example, user-controller.ts.
import { Controller, Get } from '@intentjs/core'; @Controller('/users/') export class UserController { constructor() {} @Get('') async create() { return 'Hello with an intent!'; } }For a class to be identified as a controller, it needs to be anotated with @Controller decorator from @intentjs/core. In this class, we will define our various routes.
Registering Controller
For Intent to know, you will need to register the UserController inside the the controllers method in app/http/kernel.ts.
import { Kernel } from '@intentjs/core'; import { UserController } from '#http/controllers/users'; export class HttpKernel extends Kernel { public controllers(): Type<any>[] { return [ UserController ]; } }The HttpKernel class is then passed to the IntentHttpServer inside main.ts.
We don't use HttpKernel just for registering controllers, but also for adding global middlewares, route based middlewares and guards. If you would like to know more how to use HttpKernel, read middlewares and guards.
Routing
Creating Routes
If you have used express in the past, you would remember how the routes were defined in the express servers. For example,
// respond with "hello world" when a GET request is made to the homepage app.get('/', (req, res) => { res.send('hello world') })In Intent, you can define the same route in your controller, just like below.
import { Controller, Get, Req, Request } from '@intentjs/core'; @Controller('/users') export class UserController { constructor() {} @Get('') async get(@Req() req: Request) { return 'hello world'; } }The @Get decorator before the get method tells Intent to bind all requests which come to GET /users to this method. So whenever the client pings GET /users they will receive hello world as response.
The method will return a 200 status code and the response, which is a string.
You can also add a subpath in the HTTP request method decorator, for example @Get('/all') will bind GET /users/all to the method.
Available Methods
In the previous section, we created an endpoint to fetch list of all users (GET /users). But in real world scenario, you will need multiple endpoints to create, update, delete data.
Intent comes with the support for following methods.
| Decorator | Http Method |
|---|---|
@Get(path?:string) | GET |
@Post(path?:string) | POST |
@Put(path?:string) | PUT |
@Patch(path?:string) | PATCH |
@Delete(path?:string) | DELETE |
@Options(path?:string) | OPTIONS |
@Head(path?:string) | HEAD |
@Any(path?:string) | ANY |
An example of this would be
import { Controller, Delete, Get, Patch, Post, Put, Req, Request } from '@intentjs/core'; @Controller('/users') export class UserController { constructor() {} @Get('') async index(@Req() req: Request) {} @Post('') async create(@Req() req: Request) {} @Put(':id') async update(@Req() req: Request) {} @Patch(':id') async patch(@Req() req: Request) {} @Delete(':id') async delete(@Req() req: Request) {} }Request Object
If you are building an endpoint, you will need to access the request object which let's you get the details from the request. To do so, you can make use of the @Req decorator and Request class from @intentjs/core package.
Intent comes with it's own Request utility which is more powerful than those available, you can read more about the Request objects here.
For example, let's say you want to build an endpoint which creates customer. For this, you will need to create a POST handler.
import { Req, Request, Controller, Post, } from '@intentjs/core'; @Controller('/users') export class UserController { constructor() {} @Post('') async create(@Req() req: Request) { console.log(req.all()); // your create user logic here... } }There are multiple approaches to using Requests inside Intent. You can read about them in detail here.
Route Wildcards
By default, out of the box Intent also supports Pattern based routes as well. For instance, the asterisk * is used as wildcard.
@Get('ab*cd') findAll() { return 'This route uses a wildcard'; }The ab*cd route path will match abcd, ab_cd, abecd, and so on. The characters ?, +, *, and () may be used in a route path, and are subsets of their regular expression counterparts. The hyphen ( -) and the dot (.) are interpreted literally by string-based paths.
Route Parameters
If you wish to accept dynamic data as part of your request, you can make use of the route parameters, for example GET /users/1 to get user with id 1. In order to define routes with parameters, we can add route parameter tokens in the part of the route to capture the dynamic value at that position in the request URL.
INFO
Route with parameters should always be declared after any static paths. This prevents the parameterized paths from intercepting the routes destined for static paths.
@Get(':id') findOne(@Param('id') id: string) { return `This action returns a user with id ${id}.`; }Request Payload
There are multiple ways you can retrieve the payload from the request, you can either make use of the req.all() method from Request object or alternatively make use of the @Payload() decorator to retrieve the payload.
@Controller('/users') export class UserController { constructor() {} @Get('') async index(@Req() req: Request) { const payload = req.all(); } @Post('') async create(@Payload() payload: CreateUserDto) { console.log(payload); } }INFO
We recommend using @Payload decorator as it provides a typed safe object, whereas req.all only returns a POJO.
