Parsing requests
LoopBack 4 uses the Content-Type
header and requestBody
of the OpenAPI specto parse the body of http requests. Please seeParsing requests for more details.
The @loopback/rest
module ships a set of built-in body parsers:
json
: parses the http request body as a json value (object, array, string,number, boolean, null)urlencoded
: decodes the http request body from‘application/x-www-form-urlencoded’text
: parses the http request body as astring
stream
: keeps the http request body as a stream without parsingraw
: parses the http request body as aBuffer
To support more media types, LoopBack defines extension points to plug in bodyparsers to parse the request body. LoopBack’s request body parsing capabilitycan be extended in the following ways:
Adding a new parser
To add a new body parser, follow the steps below:
- Define a class that implements the
BodyParser
interface:
/**
* Interface to be implemented by body parser extensions
*/
export interface BodyParser {
/**
* Name of the parser
*/
name: string | symbol;
/**
* Indicate if the given media type is supported
* @param mediaType - Media type
*/
supports(mediaType: string): boolean;
/**
* Parse the request body
* @param request - http request
*/
parse(request: Request): Promise<RequestBody>;
}
A body parser implementation class will be instantiated by the LoopBack runtimewithin the context and it can leverage dependency injections. For example:
export class JsonBodyParser implements BodyParser {
name = 'json';
private jsonParser: BodyParserMiddleware;
constructor(
@inject(RestBindings.REQUEST_BODY_PARSER_OPTIONS, {optional: true})
options: RequestBodyParserOptions = {},
) {
const jsonOptions = getParserOptions('json', options);
this.jsonParser = json(jsonOptions);
}
// ...
}
See the complete code athttps://github.com/strongloop/loopback-next/blob/master/packages/rest/src/body-parsers/body-parser.json.ts.
- Bind the body parser class to your REST server/application:For example,
server.bodyParser(XmlBodyParser);
The bodyParser
api binds XmlBodyParser
to the context with:
- key:
request.bodyParser.XmlBodyParser
- tag:
request.bodyParser
Please note that newly added body parsers are always invoked before the built-inones.
Contribute a body parser from a component
A component can add one or more body parsers via its bindings property:
import {createBodyParserBinding} from '@loopback/rest';
export class XmlComponent implements Component {
bindings = [createBodyParserBinding(XmlBodyParser)];
}
Customize parser options
The request body parser options is bound toRestBindings.REQUEST_BODY_PARSER_OPTIONS
. To customize request body parseroptions, you can simply bind a new value to its key.
Built-in parsers retrieve their own options from the request body parseroptions. The parser specific properties override common ones. For example, giventhe following configuration:
{
limit: '1MB'
json: {
strict: false
},
text: {
limit: '2MB'
},
/**
* Validation options for AJV, see https://github.com/epoberezkin/ajv#options
* This setting is global for all request body parsers and it cannot be
* overridden inside parser specific properties such as `json` or `text`.
*/
validation: {nullable: true},
}
The json parser will be created with {limit: '1MB', strict: false}
and thetext parser with {limit: '2MB'}
.
Custom parsers can choose to have its own options
from the context bydependency injection, for example:
export class XmlBodyParser implements BodyParser {
name = 'xml';
constructor(
@inject('request.bodyParsers.xml.options', {optional: true})
options: XmlBodyParserOptions = {},
) {
...
}
// ...
}
Replace an existing parser
An existing parser can be replaced by binding a different value to theapplication context.
class MyJsonBodyParser implements BodyParser {
// ...
}
app.bodyParser(MyJsonBodyParser, RestBindings.REQUEST_BODY_PARSER_JSON);
Remove an existing parser
An existing parser can be removed from the application by unbinding thecorresponding key. For example, the following code removes the built-in JSONbody parser.
app.unbind(RestBindings.REQUEST_BODY_PARSER_JSON);