Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Developing RESTful APIs With Loopback

DZone's Guide to

Developing RESTful APIs With Loopback

In this tutorial, I'll show you how to leverage Loopback, an open-source Node.js framework, to build out your REST APIs quickly.

· Web Dev Zone
Free Resource

Tips, tricks and tools for creating your own data-driven app, brought to you in partnership with Qlik.

Note: Check out the repo to get the code.

RESTful API Overview

API (Application Programming Interface) endpoints are the connections between your application and the rest of the developer community. You can decide to open up your data source to the world by crafting API endpoints that developers can consume. Furthermore, developing an application that will require clients for different platforms such as Desktop, Android, iOS and Windows platform will most likely need a RESTful API for all the clients to access data seamlessly. Unless of course, you are engaging GraphQL, the alternate option to RESTful APIs.

If you have built a RESTful API from scratch before now, you'll understand that there are a lot of processes you have to follow, a lot of code to write, and a lot of testing to do to ensure your APIs work correctly. Loopback was designed to fast-track those processes and take away the pain of developing RESTful APIs from scratch.

What Is Loopback

Loopback is a highly extensible open-source Node.js framework that can be used to build dynamic end-to-end REST APIs. With little or no code, Loopback hands you the power to:

  • Quickly create APIs.
  • Connect your APIs to data sources such as relational databases, MongoDB, REST APIs, etc.
  • Incorporate model relationships and access controls for complex APIs.
  • Extend your APIs.

Loopback runs on-premises or in the cloud. It also provides several add-on components for file management, 3rd-party login, OAuth2, Storage providers, etc. Simply put, Loopback allows you to create REST APIs in minutes. It does that by:

  • Providing a CLI tool for use.
  • Providing a built-in API explorer.
  • Allowing a developer to create models based on a particular schema.
  • Allowing a developer to create dynamic models in the absence of a schema.
  • Providing SDKs for iOS, Android, and AngularJS to easily create client apps.

Application Overview

In this tutorial, we'll build a RESTful API for Star Wars. A Star Wars API, SWAPI already exists. Rather than crafting an entirely different API, we'll build a clone of the Star Wars API. The objective of building the API clone is to learn how to craft APIs quickly with Loopback. Consider a case where you are assigned the task of designing an API for a new interesting HBO show, e.g Game of Thrones, that has caught the attention of Google and Facebook.

Explore SWAPI (Star Wars API) Design

We will explore the API endpoints for SWAPI(Star Wars API). There are six endpoints for the Star Wars API:

  • Planets - /planets
  • People - /people
  • Starships - /starships
  • Species - /species
  • Vehicles - /vehicles
  •     Films - /films  
  • Planets - This resource is about the planetary bodies in the Star Wars Universe.
    • GET - /planets returns a list of all the planets.
    • GET - /planets/<id> returns the details of a specific planet.
  • People - This resource deals with characters in the Star Wars Universe.
    • GET - /people returns a list of all the characters.
    • GET - /planets/<id> returns the details of a specific character.
  • Starships - This resource is about the transport crafts that have hyperdrive capability in the Star Wars Universe.
    • GET - /starships returns a list of all the starships.
    • GET - /starships/<id> returns the details of a specific starship.
  • Vehicles - This resource is about the transport crafts that do not have hyperdrive capability.
    • GET - /vehicles returns a list of all the vehicles.
    • GET - /vehicles/<id> returns the details of the vehicle.
  • Species - This resource is about the type of characters in the Star Wars Universe.
    • GET - /species returns a list of all the species.
    • GET - /species/<id> returns the details of a specific species.
  • Films - This resource is about the episodes of the Star Wars film.
    • GET - /films returns a list of all the episodes.
    • GET - /films/<id> returns the details of a specific film.

In the analysis above, you'll observe that all the calls for the endpoints are GET requests. We'll ensure that the other HTTP verbs, POST, PUT, and DELETE will be active for these endpoints when building the API.

Getting Started: Building Star Wars API

Let's get started. Go ahead and install Loopback:

npm install -g loopback-cli 

Once you are done installing, go ahead and run the loopback command:

lb

The Loopback CLI is an interactive wizard. A series of questions will be asked such as the name of the application, directory to store the project, the version of loopback you prefer, and the kind of application you want loopback to provision. Answer the questions:

Next, move into the starwars directory from the terminal.

Create Models

We'll create all the models needed for this API. As mentioned earlier, we have 6 resources, People, Films, Starships, Species, Vehicles and Planets. In our API, we'll deal with just 5.

lb model

It will prompt you for a model name: enter People. Next, select db(memory) as the data source. Go ahead and select PersistedModel as the model's base class. Hit Enter to expose People via the REST API.

Next, select common model. Selecting this ensures that the models are stored in the common directory. You can also decide to store them in the server directory only. The server directory is used to store server-side models while the common directory stores models that can potentially be used by both server and client Loopback APIs.

Now, you are going to define properties for the People model. The properties are:

  • Property name: name, Property type: string, Required? Yes
  • Property name: height, Property type: number, Required? Yes
  • Property name: mass, Property type: number, Required? Yes
  • Property name: gender, Property type: string, Required? Yes

Repeat the same process for the Films, Starships, Species and Planets models with these properties:

Note: You'll have to run lb model on your terminal everytime you need to create a new model.

Film

  • Property name: title, Property type: string, Required? Yes
  • Property name: opening_crawl, Property type: string, Required? Yes
  • Property name: director, Property type: string, Required? Yes
  • Property name: producer, Property type: string, Required? Yes

Starship

  • Property name: name, Property type: string, Required? Yes
  • Property name: model, Property type: string, Required? Yes
  • Property name: manufacturer, Property type: string, Required? Yes
  • Property name: passengers, Property type: number, Required? Yes
  • Property name: class, Property type: string, Required? Yes

Species

  • Property name: name, Property type: string, Required? Yes
  • Property name: classification, Property type: string, Required? Yes
  • Property name: designation, Property type: string, Required? Yes
  • Property name: average_height, Property type: number, Required? Yes
  • Property name: skin_color, Property type: string, Required? Yes
  • Property name: language, Property type: string, Required? Yes

Planet

  • Property name: name, Property type: string, Required? Yes
  • Property name: rotation_period, Property type: number, Required? Yes
  • Property name: orbital_period, Property type: number, Required? Yes
  • Property name: diameter, Property type: number, Required? Yes
  • Property name: population, Property type: nunber, Required? Yes

Once you are done provisioning all the models, head over to the common/models directory. In this directory, you'll see all the models in .js and .json files. For example, people.js and people.json file.

Next, test the API. Run the command below in the root path of the project:

node .

Check out your API explorer.

Here, you can see the structure of the Species resource. Clicking the Try it out button hits the /api/species endpoint and returns a result. Right now, there is no data so it returns an empty array.

Note: The API explorer allows you test the REST API operations during development.

Let's make a POST request to the /api/film endpoint using the explorer. Head over to http://localhost:3000/explorer/#!/Films/Films_create.

In the diagram above, I highlighted three steps:

  1. Click on the text-area box that contains the parameter type. Once clicked, it immediately appears in box 2.
  2. Edit the JSON in the box.
  3. Click the Try it out button to execute the POST operation.

Note: If you are making a POST request to create a new record, remove the id attribute and value from the JSON in the box. id is automatically assigned.

Result of POST operation

Now check out the URL, http://localhost:3000/api/films.

Try making a POST request to the films endpoint with Postman.

Voila! Be careful, our API is not connected to any data source yet.

Next, let's connect our API to a data source.

Connect API to Data Source

Let's connect our API to a database. Luckily for us, Loopback supports a lot of data sources. Head over to your terminal and run the following command:

lb datasource 

It will prompt you for a name. Enter mysqlDs.

mysqlDs is MySQL Datasource for short. Yes, we'll make use of MySQL. So, make sure you have MySQL database installed on your machine.

Next, select MySQLas the connector for mysqlDs and hit Enter. Go ahead and supply the host, port, user and password values for the connection string. And enter Yes to install the loopback-connector-mysql tool.

The connection details can be found at server/datasources.json. Feel free to edit the file anytime.

Connect API to MySQL

Open up server/model-config.json and change the value of the dataSource property from db to mysqlDs for each of the models.

server/model-config.json

...
"People": {
  "dataSource": "db",
  "public": true
},
"Film": {
  "dataSource": "db",
  "public": true
},
"Starship": {
  "dataSource": "db",
  "public": true
},
"Specie": {
  "dataSource": "db",
  "public": true
},
"Planet": {
  "dataSource": "db",
  "public": true
}

After changing to mysqlDsserver/model-config.json

...
"People": {
  "dataSource": "mysqlDs",
  "public": true
},
"Film": {
  "dataSource": "mysqlDs",
  "public": true
},
"Starship": {
  "dataSource": "mysqlDs",
  "public": true
},
"Specie": {
  "dataSource": "mysqlDs",
  "public": true
},
"Planet": {
  "dataSource": "mysqlDs",
  "public": true
}

Create Model Tables in MySQL

We'll go ahead and create tables for each of the models in MySQL. There are two approaches:

  • Create tables manually in MySQL database.
  • Programmatically create the tables.

Let's go with the second option. It's more effective. And we need test data. We'll write an automigration script to programmatically create the tables.

Create a new file, server/boot/create-data-tables.js and add code to it:

module.exports = function(app) {
  app.dataSources.mysqlDs.automigrate('People', function(err) {
    if (err) throw err;

    app.models.People.create([{
      name: 'Luke Skywalker',
      height: 172,
      mass: 77,
      gender: 'Male'
    }, {
      name: 'C-3PO',
      height: 167,
      mass: 75,
      gender: 'Undetermined'
    }], function(err, People) {
      if (err) throw err;

      console.log('Models created: \n', People);
    });
  });

  app.dataSources.mysqlDs.automigrate('Film', function(err) {
    if (err) throw err;

    app.models.Film.create([{
      title: 'A New Hope',
      opening_crawl: 'It is a period of civil war',
      director: 'George Lucas',
      producer: 'Gary Kurtz'
    }, {
      title: 'The Empire Strikes Back',
      opening_crawl: 'It is a dark time for the rebellion',
      director: 'Irvin Kershner',
      producer: 'Rick McCallum'
    }], function(err, People) {
      if (err) throw err;

      console.log('Models created: \n', People);
    });
  });

  app.dataSources.mysqlDs.automigrate('Starship', function(err) {
    if (err) throw err;

    app.models.Starship.create([{
      name: 'Death Star',
      model: 'DS-1 Orbital Battle Station',
      manufacturer: 'Imperial Department of Military Research',
      passengers: 843342,
      class: 'Deep Space Mobile Battlestation'
    }, {
      name: 'Sentinel-class landing craft',
      model: 'Sentinel-class landing craft',
      manufacturer: 'Sienar Fleet Systems, Cyngus Spaceworks',
      passengers: 75,
      class: 'Landing Craft'
    }], function(err, Starship) {
      if (err) throw err;

      console.log('Models created: \n', Starship);
    });
  });

  app.dataSources.mysqlDs.automigrate('Specie', function(err) {
    if (err) throw err;

    app.models.Specie.create([{
      name: 'Droid',
      classification: 'artificial',
      designation: 'sentient',
      average_height: 34,
      skin_color: "brown",
      language: "Galacticus"
    }, {
      name: 'Human',
      classification: 'Mammal',
      designation: 'sentient',
      average_height: 180,
      skin_color: 'black',
      language: 'Galactic Basic'
    }], function(err, Specie) {
      if (err) throw err;

      console.log('Models created: \n', Specie);
    });
  });

  app.dataSources.mysqlDs.automigrate('Planet', function(err) {
    if (err) throw err;

    app.models.Planet.create([{
      name: 'Yavin IV',
      rotation_period: 24,
      orbital_period: 4818,
      diameter: 10200,
      population: 1000
    }, {
      name: 'Hoth',
      rotation_period: 23,
      orbital_period: 549,
      diameter: 7200,
      population: 12500
    }], function(err, Planet) {
      if (err) throw err;

      console.log('Models created: \n', Planet);
    });
  });
};

The bunch of code above simply creates the tables and seeds them with the data provided. Whenever your app is initialized, the script will run and ensure the tables exist and are seeded with the right data.

Head over to your console and start your app again:

Create Tables and seed data

Check your database. The new tables and data should reflect there.

Test the API

Now that our API is connected to MySQL. Let's test our API for persistence. Make a GET request to http://localhost:3000/api/planets.

Initial GET Request

Go ahead and make a POST request to the URL.

POST Request

Now, make another GET request to the URL.

Another GET Request

Yes, we see three records. Our data was persisted successfully. You can test out the PUT, PATCH, and DELETE operations for the Planets and other API endpoints.

Explore data-driven apps with less coding and query writing, brought to you in partnership with Qlik.

Topics:
web dev ,restful apis ,node.js ,loopback

Published at DZone with permission of Prosper Otemuyiwa, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}