Skip to main content

Request Parameters

In RapidREST, the arguments of each HTTP handler function are composable, taking any number of arguments, whose values are injected by the framework at execution time. This provides two key benefits over more traditional frameworks that use func(req, res, next) architecture. First, only the data needed to process the request is injected into the handler function, thereby signficantly reducing code complexity. Second, declaring the injected arguments in the function definition improves code readability and serves to self-document the code.

The following table describes all injectable value types for an HTTP handler function.

DecoratorResolves to
@Param(name?)req.params[name], or the whole params object if name is omitted
@Query(name?)req.query[name], or the whole query object if name is omitted
@Header(name)req.headers[name]
@Requestthe whole HttpRequest object (no parentheses)
@Responsethe whole HttpResponse object (no parentheses)
@Socketthe underlying WebSocket, for @WebSocket handlers (no parentheses)
@Userthe authenticated user (req.auth?.user), if any (no parentheses)
@AuthResultthe full auth result object (no parentheses)

The following example illustrates three injected values for the GET /:id request handler; @Param('id'), @Query('version'), and @User.

@Get('/:id')
async getPet(@Param('id') id: string, @Query('version') version: string, @User user?: JWTUser) {
/* ... */
}

The @Param('id') injected value will extract the :id portion of the HTTP request's path (e.g. GET /my-petmy-pet). The @Query('version') portion will extract the value for the query paramater key version (e.g. GET /my-pet?version=33). Finally, the @User injects the authenticated user (if applicable).

The @Request-injected object also carries req.cookies and, if sessions are configured, req.session — see HTTP Engine → Sessions and HTTP Engine → Cookies & CORS.

The request body

The first handler argument that isn't decorated automatically receives the parsed request body. Note that this can be anywhere in the function definition, with preceding injected arguments and/or proceeding injected arguments as shown in the examples below.

@Post()
async createPet(pet: Pet) {
// `pet` is the parsed JSON body, no decorator needed
return this.petService.create(pet);
}

@Post()
async createPet2(@Query() query: any, pet: Pet) {
// `pet` is the parsed JSON body, no decorator needed
return this.petService.create(pet);
}

@Post()
async createPet3(pet: Pet, @User user: JWTUser) {
// `pet` is the parsed JSON body, no decorator needed
return this.petService.create(pet);
}

@Post()
async createPet4(@Query() query: any, pet: Pet, @User user: JWTUser) {
// `pet` is the parsed JSON body, no decorator needed
return this.petService.create(pet);
}

WebSocket example

When defining a WebSocket handler function it is necessary to have at least one @Socket decorated argument in order to implement the WebSocket connection. If no @Socket argument is defined, the connection will be automatically closed.

@WebSocket('/connect')
onConnect(@Query('message') message: string, @Socket ws: WebSocket, @User user?: any) {
ws.on('message', (msg) => ws.send(`echo ${message ?? ''} ${msg}`));
}