What is a RESTful API
REST is an acronym for Representational State Transfer. REST is a resource based architecture style that defines how an API should built. With REST everything (all data) is a resource and uses a noun to specify the resource instead of an verb (SOAP API). For instance, if we want to get all animal data we would use /animals instead of /get-animals. Check this post for a great primer on designing RESTful APIs
We will build a RESTful API to interact with the telemetR database.
We will use Node.js, Express.js, and pg-promise.js to build a RESTful API to interact with the telemetR database and Postman to test it. My normal database connection library is Sequelize.js. However I don’t want to rewrite the database schema as models. All we need is to write raw SQL that can be interpreted by Node and sent to postgres. We will use pg-promise to do this.
First create a new folder and cd into it, then use npm init to start a new project and npm install to install the require libraries. We will use nodemon to monitor the directory and restart when files change.
The --save flag means to save the files to package.json, -g means to install globally. The list two lines are shortcuts for opening the finder and Atom at the current directory.
index.js is the entry point for the API. This is where all the server logic is compiled and the server is created.
Let’s go step by step. In the first blcok we are requiring the dependencies to run the API. In the second block we are setting body-parser to parse json input. In the next two blocks we are requiring and telling the app to use the routes we create. We will create the routes one at a time, however in order to require them the routes will need to exist. For now I’ll comment out routes we’ve yet to create, then uncomment each one as we get to it. Our first route will be for deployments.
We will put all the database connection logic in this file. We can reference this file from the routes we will create, that way we don’t have to duplicate this code in every route. When requiring pg-promise we can choose a few configuration options. I am overriding the default promise library to bluebird. I’ve used bluebird in the past, so I’ll continue using it here.
Open package.json and add "dev": "nodemon index.js" script and any other information you want to add. To start your server type npm run dev into the terminal.
Routes determine how the application responds to client requests from a URI and HTTP method. These will look like URLs. Before creating any routes make a new folder called routes. All the routes we create will be stored in here.
The first route we will write will be for deployments. We will make a call to the database for data, then return the data as a JSON.
First we require the modules we need, including the db.js, then write the routes. The first route will get all the deployments in the database. You don’t have to write your SQL like that, but I like the readability. Test this route in Postman with localhost:8080/deployments.
The first route will GET all the deployments in the database, localhost:8080/deployments. The second will GET deployments by the perm_id specified in the :id portion of the route, localhost:8080\deployments\F09. Try these in Postman.
The ` allows multiline strings, it is an ES6 template literal. Markdown isn’t properly rendering the grave symbol so I’ve prefixed it with a \. Remove prefixed \ before running the code.
Let’s write routes that will allow us to get data in the telemetry table. Below is the relocations.js folder (relocations is a term frequently used to refer to GPS points).
We’ve required the dbgeo package for these routes, this will allow us to convert the data returned from the database into a GeoJSON.
The first route returns all the telemetry data for the specified animal. Try localhost:8080/relocations/F09. The second route will return the same data, however the data returned will be a GeoJSON. In practice we wouldn’t create a route with the format in the URI. Instead we would include a format parameter in the query string. This is simpler, so let’s stick with that.
Here is a map of data portion for localhost:8080/relocations/M10/geojson.
Note: if you leave out telemetry.validity_id = 2 there is one improbable spike in the data.
Below I’ll write the routes to for animals and devices. These will be very similar the the routes above. After each set of routes I’ll include images from testing in Postman.
Get all devices
Get animal by serial_num
Get all animals
Get animal by perm_id
Get all captures
Get captures by perm_id
Now that we have the foundation of an API we can easily access the data from any client we choose. At this point all we can only use GET requests. We can’t write, update, or delete data yet. We will get to that in the next post.