Page Contents

To get started with accessing REST APIs, you need to create a datasource as discussed below:

Add a Datasource with OpenAPI specification

When calling REST services which comes with the OpenAPI specification, select OpenAPI for connector. The OpenAPI connector will be used.

$ lb4 datasource
? Datasource name: ds
? Select the connector for ds: OpenAPI (supported by StrongLoop)
? HTTP URL/path to Swagger spec file (file name extension .yaml/.yml or .json):
petstore.json
? Validate spec against Swagger spec 2.0?: No
? Security config for making authenticated requests to API:
? Use positional parameters instead of named parameters?: No
   create src/datasources/ds.datasource.ts

For details regarding the prompts about authentication and positional parameters, see the Authentication and Named parameters vs positional parameters sections of the OpenAPI connector page.

Datasource for REST service without OpenAPI specification

In the case where the REST services do not have a corresponding OpenAPI specification, select REST services for connector. We’ll leave the default for the last 3 prompts.

$ lb4 datasource
? Datasource name: restds
? Select the connector for restds: REST services (supported by StrongLoop)
? Base URL for the REST service: https://swapi.dev/api/
? Default options for the request:
? An array of operation templates:
? Use default CRUD mapping: No

The next step is to edit the DataSource file for options and operations.

The REST connector uses the request module as the HTTP client. You can configure the same options as for the request() function. See details in this documentation page.

The template object specifies the REST API invocation as a JSON template. You can find more details in the Defining a custom method using a template page.

const config = {
  name: 'restds',
  connector: 'rest',
  baseURL: 'https://swapi.dev/api/',
  crud: false,
  options: {
    headers: {
      accept: 'application/json',
      'content-type': 'application/json',
    },
  },
  operations: [
    {
      template: {
        method: 'GET',
        url: 'https://swapi.dev/api/people/{personId}',
      },
      functions: {
        getCharacter: ['personId'],
      },
    },
  ],
};

Add a service

Add a service using the Service generator and specify the DataSource that you just created.

Define the methods that map to the operations

In the Service interface, define the methods that map to the operations of your external service.

To promote type safety, we recommend you to declare data types and service interfaces in TypeScript and use them to access the service proxy.

export interface PeopleService {
  getCharacter(personId: number): Promise<object>;
}

Alternately, we also provide a weakly-typed generic service interface as follows:

/**
 * A generic service interface with any number of methods that return a promise
 */
export interface GenericService {
  [methodName: string]: (...args: any[]) => Promise<any>;
}

For details on implementing the Services with OpenAPI DataSource, see the OpenAPI connector page.

Add a Controller

Add a controller using the Controller generator with the Empty Controller option.

Inject the Service in the constructor

  constructor(
    @inject('services.PeopleService')
    protected peopleService: PeopleService,
  ) {}

Add the REST endpoints

This will be similar to how you normally add a REST endpoint in a Controller. The only difference is you’ll be calling the methods that you’ve exposed in the Service interface.

@get('/people/{personId}')
  async getCharacter(
    @param.path.integer('personId') personId: number,
  ): Promise<object> {
    //Preconditions

    return this.peopleService.getCharacter(personId);
  }
@post('/people')
  async getPeople(
    @param.query.string('name') name: string,
  ): Promise<object> {
    //Preconditions

    return this.peopleService.getPeople(name);
  }

For calling Services with OpenAPI DataSource,

  • the parameters need to be wrapped in a JSON object
  • the response includes the headers and the body

See the code snippet below for illustration:

@get('/pets/{petId}', {
    responses: {
      '200': {
        description: 'Pet model instance',
        content: {'application/json': {schema: PetSchema}},
      },
    },
  })
  async findPetById(@param.path.number('petId') petId: number): Promise<Pet> {
    // wrap the parameters in a JSON object
    const response = await this.petStoreService.getPetById({petId: petId});
    // we normally only return the response body
    return response.body;
  }
}

More examples

Further reading