Overview

The Server interfacedefines the minimal required functions (start and stop) and a ‘listening’property to implement for a LoopBack application. Servers in LoopBack 4 are usedto represent implementations for inbound transports and/or protocols such asREST over http, gRPC over http2, graphQL over https, etc. They typically listenfor requests on a specific port, handle them, and return appropriate responses.A single application can have multiple server instances listening on differentports and working with different protocols.

Usage

LoopBack 4 offers the@loopback/restpackage out of the box, which provides an HTTP/HTTPS-based server calledRestServer for handling REST requests.

In order to use it in your application, your application class needs to extendRestApplication to provide an instance of RestServer listening on port 3000.The following example shows how to use RestApplication:

  1. import {RestApplication, RestServer} from '@loopback/rest';
  2. export class HelloWorldApp extends RestApplication {
  3. constructor() {
  4. super();
  5. // give our RestServer instance a sequence handler function which
  6. // returns the Hello World string for all requests
  7. // with RestApplication, handler function can be registered
  8. // at app level
  9. this.handler((sequence, request, response) => {
  10. sequence.send(response, 'Hello World!');
  11. });
  12. }
  13. async start() {
  14. // call start on application class, which in turn starts all registered
  15. // servers
  16. await super.start();
  17. // get a singleton HTTP server instance
  18. const rest = await this.getServer(RestServer);
  19. console.log(`REST server running on port: ${await rest.get('rest.port')}`);
  20. }
  21. }

Configuration

The REST server can be configured by passing a rest property inside yourRestApplication options. For example, the following code customizes the portnumber that a REST server listens on.

  1. const app = new RestApplication({
  2. rest: {
  3. port: 3001,
  4. },
  5. });

Customize How OpenAPI Spec is Served

There are a few options under rest.openApiSpec to configure how OpenAPI specis served by the given REST server.

  • servers: Configure servers for OpenAPI spec
  • setServersFromRequest: Set servers based on HTTP request headers, default tofalse
  • disabled: Set to true to disable endpoints for the OpenAPI spec. It willdisable API Explorer too.
  • endpointMapping: Maps urls for various forms of the spec. Default to:
  1. {
  2. '/openapi.json': {version: '3.0.0', format: 'json'},
  3. '/openapi.yaml': {version: '3.0.0', format: 'yaml'},
  4. }
  1. const app = new RestApplication({
  2. rest: {
  3. openApiSpec: {
  4. servers: [{url: 'http://127.0.0.1:8080'}],
  5. setServersFromRequest: false,
  6. endpointMapping: {
  7. '/openapi.json': {version: '3.0.0', format: 'json'},
  8. '/openapi.yaml': {version: '3.0.0', format: 'yaml'},
  9. },
  10. },
  11. },
  12. });

Configure the API Explorer

LoopBack allows externally hosted API Explorer UI to render the OpenAPIendpoints for a REST server. Such URLs can be specified with rest.apiExplorer:

  1. const app = new RestApplication({
  2. rest: {
  3. apiExplorer: {
  4. url: 'https://petstore.swagger.io',
  5. httpUrl: 'http://petstore.swagger.io',
  6. },
  7. },
  8. });

Disable redirect to API Explorer

To disable redirect to the externally hosted API Explorer, set the config optionrest.apiExplorer.disabled to true.

  1. const app = new RestApplication({
  2. rest: {
  3. apiExplorer: {
  4. disabled: true,
  5. },
  6. },
  7. });

Use a self-hosted API Explorer

Hosting the API Explorer at an external URL has a few downsides, for example aworking internet connection is required to explore the API. As a recommendedalternative, LoopBack comes with an extension that provides a self-hostedExplorer UI. Please refer toSelf-hosted REST API Explorer for moredetails.

Enable HTTPS

Enabling HTTPS for the LoopBack REST server is just a matter of specifying theprotocol as https and specifying the credentials.

In the following app, we configure HTTPS for a bare minimum app using a key +certificate chain variant.

  1. import {RestApplication, RestServer, RestBindings} from '@loopback/rest';
  2. import * as fs from 'fs';
  3. export async function main() {
  4. const options = {
  5. rest: {
  6. protocol: 'https',
  7. key: fs.readFileSync('./key.pem'),
  8. cert: fs.readFileSync('./cert.pem'),
  9. },
  10. };
  11. const app = new RestApplication(options);
  12. app.handler(handler => {
  13. handler.response.send('Hello');
  14. });
  15. await app.start();
  16. const url = app.restServer.url;
  17. console.log(`Server is running at ${url}`);
  18. }

Customize CORS

CORS is enabledby default for REST servers with the following options:

  1. {
  2. origin: '*',
  3. methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
  4. preflightContinue: false,
  5. optionsSuccessStatus: 204,
  6. maxAge: 86400,
  7. credentials: true,
  8. }

The application code can customize CORS via REST configuration:

  1. export async function main() {
  2. const options = {
  3. rest: {
  4. cors: {...},
  5. },
  6. };
  7. const app = new RestApplication(options);
  8. }

For a complete list of CORS options, seehttps://github.com/expressjs/cors#configuration-options.

Express settings

Override the default express settings and/or assign your own settings:

  1. const app = new RestApplication({
  2. rest: {
  3. expressSettings: {
  4. 'x-powered-by': false,
  5. env: 'production',
  6. ...
  7. },
  8. },
  9. });

Checkout express documentation formore details about the build-in settings.

Configure the Base Path

Sometime it’s desirable to expose REST endpoints using a base path, such as/api. The base path can be set as part of the RestServer configuration.

  1. const app = new RestApplication({
  2. rest: {
  3. basePath: '/api',
  4. },
  5. });

The RestApplication and RestServer both provide a basePath() API:

  1. const app: RestApplication;
  2. // ...
  3. app.basePath('/api');

With the basePath, all REST APIs and static assets are served on URLs startingwith the base path.

Configure the router

The router can be configured to enforce strict mode as follows:

  • strict is true:
  • request /orders matches route /orders but not /orders/
  • request /orders/ matches route /orders/ but not /orders
  • strict is false (default)
  • request /orders matches route /orders first and falls back to /orders/
  • request /orders/ matches route /orders/ first and falls back to /ordersSee strict routing at http://expressjs.com/en/4x/api.html#app for moreinformation.

Configure the request body parser options

We can now configure request body parser options as follows:

  1. const app = new Application({
  2. rest: {requestBodyParser: {json: {limit: '1mb'}}},
  3. });

The value of rest.requestBodyParser will be bound toRestBindings.REQUEST_BODY_PARSER_OPTIONS. SeeCustomize request body parser optionsfor more details.

rest options

PropertyTypePurpose
hoststringSpecify the hostname or ip address on which the RestServer will listen for traffic.
portnumberSpecify the port on which the RestServer listens for traffic.
protocolstring (http/https)Specify the protocol on which the RestServer listens for traffic.
basePathstringSpecify the base path that RestServer exposes http endpoints.
keystringSpecify the SSL private key for https.
certstringSpecify the SSL certificate for https.
corsCorsOptionsSpecify the CORS options.
sequenceSequenceHandlerUse a custom SequenceHandler to change the behavior of the RestServer for the request-response lifecycle.
openApiSpecOpenApiSpecOptionsCustomize how OpenAPI spec is served
apiExplorerApiExplorerOptionsCustomize how API explorer is served
requestBodyParserRequestBodyParserOptionsCustomize how request body is parsed
routerRouterOptionsCustomize how trailing slashes are used for routing

Add servers to application instance

You can add server instances to your application via the app.server() methodindividually or as an array using app.servers() method. Using app.server()allows you to uniquely name your binding key for your specific server instance.The following example demonstrates how to use these functions:

  1. import {Application} from '@loopback/core';
  2. import {RestServer} from '@loopback/rest';
  3. export class HelloWorldApp extends Application {
  4. constructor() {
  5. super();
  6. // This server instance will be bound under "servers.fooServer".
  7. this.server(RestServer, 'fooServer');
  8. // Creates a binding for "servers.MQTTServer" and a binding for
  9. // "servers.SOAPServer";
  10. this.servers([MQTTServer, SOAPServer]);
  11. }
  12. }

You can also add multiple servers in the constructor of your application classas shown here.

Next Steps