Route Decorators
Route decorators are used to expose controller methods as REST API operations. If you are not familiar with the concept of Route or Controller, please see LoopBack Route and LoopBack Controller to learn more about them.
By calling a route decorator, you provide OpenAPI specification to describe the endpoint which the decorated method maps to. You can choose different decorators accordingly or do a composition of them:
API Decorator
Syntax:
@api(spec: ControllerSpec)
@api
is a decorator for the controller class and is appended just before it’s
declared. @api
is used when you have multiple
Paths Objects
that contain all path definitions of your controller. Please note the api specs
defined with @api
will override other api specs defined inside the controller.
For example:
@api({
basePath: '/',
paths: {
'/greet': {
get: {
'x-operation-name': 'greet',
'x-controller-name': 'MyController',
parameters: [{name: 'name', schema: {type: 'string'}, in: 'query'}],
responses: {
'200': {
description: 'greeting text',
content: {
'application/json': {
schema: {type: 'string'},
},
},
},
},
},
},
},
})
class MyController {
// The operation endpoint defined here will be overriden!
@get('/greet')
greet(@param.query.number('limit') name: string) {}
}
app.controller(MyController);
A more detailed explanation can be found in Specifying Controller APIs
Operation Decorator
Syntax:
@operation(verb: string, path: string, spec?: OperationObject)
@operation
is a controller method decorator. It exposes a Controller method as
a REST API operation and is represented in the OpenAPI spec as an
Operation Object.
You can specify the verb, path, parameters, and response as a specification of
your endpoint, for example:
const spec = {
parameters: [{name: 'name', schema: {type: 'string'}, in: 'query'}],
responses: {
'200': {
description: 'greeting text',
content: {
'application/json': {
schema: {type: 'boolean'},
},
},
},
},
};
class MyController {
@operation('HEAD', '/checkExist', spec)
checkExist(name: string) {}
}
Commonly-used Operation Decorators
Syntax:
@get(path: string, spec?: OperationObject)
Same Syntax for decorators
@post
,
@put
,
@patch
,
@del
You can call these sugar operation decorators as a shortcut of @operation
. For
example:
class MyController {
@get('/greet', spec)
greet(name: string) {}
}
is equivalent to
class MyController {
@operation('GET', '/greet', spec)
greet(name: string) {}
}
Parameter Decorator
Syntax: see API documentation
@param
is applied to controller method parameters to generate an OpenAPI
parameter specification for them.
For example:
import {get, param} from '@loopback/rest';
const categorySpec = {
name: 'category',
in: 'path',
required: true,
schema: {type: 'string'},
};
const pageSizeSpec = {
name: 'pageSize',
in: 'query',
required: false,
schema: {type: 'integer', format: 'int32'},
};
class MyController {
@get('Pets/{category}')
list(
@param(categorySpec) category: string,
@param(pageSizeSpec) pageSize?: number,
) {}
}
Writing the whole parameter specification is tedious, so we’ve created shortcuts
to define the params with the pattern @param.${in}.${type}(${name})
:
- in: The parameter location. It can be one of the following values:
query
,header
, orpath
. - type: A common name of OpenAPI primitive data type.
- name: Name of the parameter. It should be a
string
.
A list of available shortcuts for query
can be found in
API document,
along with the shortcuts for path
and header
.
An equivalent example using the shortcut decorator would be:
class MyController {
@get('/Pets/{category}')
list(
@param.path.string('category') category: string,
@param.query.number('pageSizes') pageSize?: number,
) {}
}
You can find specific use cases in Writing Controller methods
The parameter location cookie is not supported yet, see (https://github.com/strongloop/loopback-next/issues/997)
RequestBody Decorator
Syntax: see API documentation
@requestBody()
is applied to a controller method parameter to generate OpenAPI
requestBody specification for it.
Only one parameter can be decorated by @requestBody
per controller method.
A typical
OpenAPI requestBody specification
contains properties description
, required
, and content
:
requestBodySpec: {
description: 'a user',
required: true,
content: {
'application/json': {...schemaSpec},
'application/text': {...schemaSpec},
},
}
In order to use @requestBody
in a parameter type, the model in the parameter
type must be decorated with @model
and @property
:
import {model, property} from '@loopback/repository';
import {Address} from './address.model';
@model()
class User {
@property()
firstname: string;
@property()
lastname: string;
@property()
address: Address;
}
To learn more about decorating models and the corresponding OpenAPI schema, see model decorators.
The model decorators allow type information of the model to be visible to the
spec generator so that @requestBody
can be used on the parameter:
// in file '/src/controllers/user.controller.ts'
import {User} from '../models/user.model';
import {put} from '@loopback/rest';
class UserController {
@put('/Users/{id}')
async replaceUser(
@param.path.string('id') id: string,
@requestBody() user: User,
) {}
}
For the simplest use case, you can leave the input of @requestBody
empty since
we automatically detect the type of user
and generate the corresponding schema
for it. The default content type is set to be application/json
.
You can also customize the generated requestBody
specification in three ways:
- Add the optional fields
description
andrequired
class MyController {
@put('/Users/{id}')
async replaceUser(
@param.path.string('id') id: string,
@requestBody({
description: 'a modified user',
required: true,
})
user: User,
) {}
}
- Override the content type or define multiple content types
class MyController {
@put('/Users/{id}')
async replaceUser(
@param.path.string('id') id: string,
@requestBody({
content: {
// leave the schema as empty object, the decorator will generate it for both.
'application/text': {},
'application/xml': {},
},
})
user: User,
) {}
}
- Override the schema specification
import {UserSchema, User} from '../model/user.schema';
class MyController {
@put('/Users/{id}')
async replaceUser(
@param.path.string('id') id: string,
@requestBody({
content: {
'application/json': UserSchema,
},
})
user: User,
) {}
}
We plan to support more @requestBody
shortcuts in the future. You can track
the feature in story
(https://github.com/strongloop/loopback-next/issues/1064)