routing-controllers
Allows to create controller classes with methods as actions that handle requests.
Right now it works only with express.js. If you are interested to make it work with other frameworks, feel free to
contribute and implement integrations with other frameworks.
Installation
-
Install module:
npm install routing-controllers --save
-
reflect-metadata
shim is required, so make sure to import it before you use the library,
in a global place, like app.ts:
import "reflect-metadata";
-
ES6 features are used, so you are using old versions of node.js you may need to install a
es6-shim too:
npm install es6-shim --save
and import it in a global place like app.ts:
import "es6-shim";
Simple usage
-
Create a file UserController.ts
import {Request, Response} from "express";
import {Controller} from "routing-controllers/decorator/Controllers";
import {Get, Post, Put, Patch, Delete} from "routing-controllers/decorator/Methods";
import {Req, Res} from "routing-controllers/decorator/Params";
@Controller()
export class UserController {
@Get("/users")
getAll() {
return "Hello all users";
}
@Get("/users/:id")
getOne(@Req() request: Request, @Res() response: Response) {
response.send("Hello user #" + request.param("id"));
}
@Post("/users")
post(@Req() request: Request, @Res() response: Response) {
}
@Put("/users/:id")
put(@Req() request: Request, @Res() response: Response) {
}
@Patch("/users/:id")
patch(@Req() request: Request, @Res() response: Response) {
}
@Delete("/users/:id")
remove(@Req() request: Request, @Res() response: Response) {
}
}
This class will register routes specified in method decorators in your server framework (express.js).
-
Create a file app.ts
import * as express from "express";
import {useExpressServer} from "routing-controllers";
import "./UserController";
let app = express();
useExpressServer(app);
app.listen(3000);
-
Open browser on http://localhost:3000/users
. You should see Hello all users
in your browser. If you open
http://localhost:3000/users/1
you should see Hello user #1
in your browser.
More usage examples
Load all controllers from the given directory
You probably don't want to require every controller in your app, and instead want to load all controllers from
specific directory. To do it you can install require-all package and use
it like this:
import "reflect-metadata";
import * as express from "express";
import {useExpressServer} from "routing-controllers";
var controllers = require('require-all')({
dirname : __dirname + '/controllers',
filter : /(.+Controller)\.js$/,
excludeDirs : /^\.(git|svn)$/,
recursive : true
});
let app = express();
useExpressServer(app);
app.listen(3000);
Load all controllers from the given directory and prefix routes
If you want to prefix all routes in some directory eg. /api
import "reflect-metadata";
import * as express from "express";
import {useExpressServer} from "routing-controllers";
let app = express();
useExpressServer(app, {
routePrefix: '/api',
controllerDirs: [__dirname + "/api"]
});
useExpressServer(app, {
routePrefix: '/auth',
controllerDirs: [__dirname + "/auth"]
});
app.listen(3000);
Set response body value returned by a controller action
To return a response body you usually do response.send("Hello world!")
. But there is alternative way of doing it.
You can also return result right from the controller, and this result will be pushed via response.send()
@Get("/users")
getAll() {
return "Hello World!";
}
You can also return a Promise (object that contains .then method), and its result will be pushed to response.send after
promise is resolved.
@Get("/users")
getAll() {
return Database.loadUsers();
}
Output JSON instead of regular text content
If you are designing a REST API where your endpoints always return JSON you can use @JsonController
decorator instead
of @Controller
. This will guarantee you that data returned by your controller actions always be transformed to JSON
objects and Content-Type
header will be always set to application/json
:
@JsonController()
export class UserController {
}
Inject parameters
You can inject some common params you may need right into the controller action method using proper decorators:
@Get("/users/:id")
getAll( @Req() request: Request,
@Res() response: Response,
@Body() requestBody: any,
@Param("id") id: number,
@QueryParam("name") name: string) {
}
Inject body and transform it to object
If you want to have response body and wish it to be automatically converted to object you need to use @Body
parameter decorator and specify extra parameters to it:
@Post("/users")
save(@Body({ parseJson: true }) user: any) {
}
There is also simplified way of doing it: save(@Body(true) user: any)
Make body required
If you want to have response body and wish it to be automatically converted to object you need to use @Body
parameter decorator and specify extra parameters to it:
@Post("/users")
save(@Body({ required: true }) user: any) {
}
Same you can do with all other parameter inectors: @Param, @QueryParam, @BodyParam and others.
Inject parameters and transform them to objects
You can inject some common params you may need right into the controller action method using proper decorators:
@Get("/users")
getAll(@QueryParam("filter", { required: true }) filter: UserFilter) {
if (filter.showAll === true)
return "all users";
return "not all users";
}
Decorators Documentation
Controller Decorators
Signature | Example | Description |
---|
Controller(baseRoute: string) | @Controller("/users") class SomeController | Class that is marked with this decorator is registered as controller and its annotated methods are registered as actions. Base route is used to concatenate it to all controller action routes. |
JsonController(baseRoute: string) | @JsonController("/users") class SomeJsonController | Class that is marked with this decorator is registered as controller and its annotated methods are registered as actions. Difference between @JsonController and @Controller is that @JsonController automatically converts results returned by controller to json objects (using JSON.parse) and response being sent to a client is sent with application/json content-type. Base route is used to concatenate it to all controller action routes. |
Controller Method Decorators
Signature | Example | Description | express.js analogue |
---|
`Get(route: string | RegExp, options?: ActionOptions)` | @Get("/users") all() | Methods marked with this decorator will register a request made with GET HTTP Method to a given route. In action options you can specify if action should response json or regular text response. |
`Post(route: string | RegExp, options?: ActionOptions)` | @Post("/users") save() | Methods marked with this decorator will register a request made with POST HTTP Method to a given route. In action options you can specify if action should response json or regular text response. |
`Put(route: string | RegExp, options?: ActionOptions)` | @Put("/users/:id") update() | Methods marked with this decorator will register a request made with PUT HTTP Method to a given route. In action options you can specify if action should response json or regular text response. |
`Patch(route: string | RegExp, options?: ActionOptions)` | @Patch("/users/:id") patch() | Methods marked with this decorator will register a request made with PATCH HTTP Method to a given route. In action options you can specify if action should response json or regular text response. |
`Delete(route: string | RegExp, options?: ActionOptions)` | @Delete("/users/:id") delete() | Methods marked with this decorator will register a request made with DELETE HTTP Method to a given route. In action options you can specify if action should response json or regular text response. |
`Head(route: string | RegExp, options?: ActionOptions)` | @Head("/users/:id") head() | Methods marked with this decorator will register a request made with HEAD HTTP Method to a given route. In action options you can specify if action should response json or regular text response. |
`Options(route: string | RegExp, options?: ActionOptions)` | @Options("/users/:id") head() | Methods marked with this decorator will register a request made with OPTIONS HTTP Method to a given route. In action options you can specify if action should response json or regular text response. |
`Method(methodName: string, route: string | RegExp, options?: ActionOptions)` | @Method("move", "/users/:id") move() | Methods marked with this decorator will register a request made with given methodName HTTP Method to a given route. In action options you can specify if action should response json or regular text response. |
Method Parameter Decorators
Signature | Example | Description | express.js analogue |
---|
Req() | getAll(@Req() request: Request) | Injects a Request object to a controller action parameter value | function (request, response) |
Res() | getAll(@Res() response: Response) | Injects a Reponse object to a controller action parameter value | function (request, response) |
Body(options: ParamOptions) | save(@Body() body: any) | Injects a body to a controller action parameter value. In options you can specify if body should be parsed into a json object or not. Also you can specify there if body is required and action cannot work without body being specified. | request.body |
Param(name: string, options?: ParamOptions) | get(@Param("id") id: number) | Injects a parameter to a controller action parameter value. In options you can specify if parameter should be parsed into a json object or not. Also you can specify there if parameter is required and action cannot work with empty parameter. | request.params.id |
QueryParam(name: string, options?: ParamOptions) | get(@QueryParam("id") id: number) | Injects a query string parameter to a controller action parameter value. In options you can specify if parameter should be parsed into a json object or not. Also you can specify there if query parameter is required and action cannot work with empty parameter. | request.query.id |
HeaderParam(name: string, options?: ParamOptions) | get(@HeaderParam("token") token: string) | Injects a parameter from response headers to a controller action parameter value. In options you can specify if parameter should be parsed into a json object or not. Also you can specify there if query parameter is required and action cannot work with empty parameter. | request.headers.token |
BodyParam(name: string, options?: ParamOptions) | post(@BodyParam("name") name: string) | Injects a body parameter to a controller action parameter value. In options you can specify if parameter should be parsed into a json object or not. Also you can specify there if body parameter is required and action cannot work with empty parameter. | request.body.name |
CookieParam(name: string, options?: ParamOptions) | get(@CookieParam("username") username: string) | Injects a cookie parameter to a controller action parameter value. In options you can specify if parameter should be parsed into a json object or not. Also you can specify there if cookie parameter is required and action cannot work with empty parameter. | request.cookie("username") |
Samples
Take a look on samples in ./sample for more examples
of usage.
Todos
- cover with tests
- add reversed error override map
- integration with other frameworks (other then express.js) can be easily added, so PRs are welcomed
Release notes
0.6.0
- middleware and error handlers support
- added beta support of koa v2 framework
- refactored core
- everything important is packed into "routing-controllers" main entrypoint now
0.5.0
- renamed package from
controllers.ts
to routing-controllers
- added integration with
constructor-utils
for serialization and deserialization