Setting up a simple REST server in Node.js
In my experience lots of people have heard of Node.js, but aren't entirely sure how to get started. In this tutorial we will be setting up a simple RESTful API server in Node.js and how to host it in the cloud for free, with Heroku.
What is a RESTful API?
An Application Program Interface (API) based on the Representational State Transfer (REST) design architecture is called a RESTful API. An API is simply a software layer that abstracts certain commands so that another application can access your data and functions, via HTTP requests. To be considered RESTful, your API must have a clear separation between client and server, stateless and cacheable.
This means that you should be able to independently change the front and back-ends of your application, making it more robust. To be stateless, there should be no client data stored on your server for requests and session data should be stored on the client. Clients should also be able to cache responses to improve performance. This is not an exhaustive list, but is a good rule of thumb.
Now that we understand roughly what a RESTful API server is, we can begin to build our own.
Development Environment
First we need to get set-up to start, you should have the following installed:
- Code Editor e.g. Visual Studio Code
- Node.js
- Git
Note: I will be using Visual Studio Code for Mac throughout this post.
Installing Node.js
Navigate to the Node.js downloads page found here and download the correct file for your operating systems.
For Windows
For those on Windows, just follow the install wizard. Once Node is installed you can check your install by opening PowerShell (or another commandline tool if you prefer) and running the commands: node -v
and npm -v
. These commands should both produce a version number if successfully installed.
For Mac
For those on Mac, you may wish to install through Homebrew instead as it saves you some effort in getting ready to start development.
You will need Xcode from the Apple App Store and Homebrew which can be installed via commandline:
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
Just follow the prompts to finish installing Homebrew.
Once you have Homebrew installed, you can can install Node with the following command: brew install node
. Once Node is installed, you can check your installation by running the command node -v
, if you have successfully installed node you should see a version number in your commandline. You should run a similar command to ensure the Node Package Manager (NPM) is installed correctly, the command is: npm -v
. Once again, if NPM has been successfully installed, you should see a version number.
Installing Git
Navigate to the Git SCM downloads page found here and download the correct file for your operating system. Once you have finished installing Git, run the command git --version
. If you successfully installed Git, you should see a version number.
For Mac
Once again, you can install this via Homebrew, using the command: brew install git
.
Creating a Node project
Using NPM, we can follow a commandline wizard to create a package.json
file, which lets us install dependencies, run all our tests with a single command and more. This command is: npm init
.
Create a folder for your project, enter the folder and then run npm init
. The first prompt is for your package (read: application) name, you will then be prompted with a number of other fields, you can just keep hitting enter to get through it! Before the package file is generated, you will be asked to confirm that it is correct.
Once you have successfully generated your package file, the next step is to create your main JavaScript file. Make sure to use the same name as you supplied in your package file, it is index.js
by default.
For Mac
If you are fond of the commandline and using a non-windows machine, you can likely use the touch
command. This command creates an empty file for you, the following command will produce an empty file called index.js
: touch index.js
.
Setting up an Express Node server
The Express framework for Node.js is a fast, small and flexible framework that provides a robust set of features for web and mobile applications, using this we can quickly set-up a RESTful API server.
Installing Express
To install Express, navigate to the root-folder of your application and run the command: npm install express --save-dev
. The --save-dev
flag means that the package will be added to our package file, if all of your packages are added to the package file then you can install all your dependencies with one command: npm install
. This must be ran on the same level as your package.json
file.
Starting a server
To get up and running, we will write a very basic server using GET as the HTTP method.
Note: You can use app.post
for the post method, and so on.
// our dependencies
const express = require('express');
const app = express();
// from top level path e.g. localhost:3000, this response will be sent
app.get('/', (request, response) => response.send('Hello World'));
// set the server to listen on port 3000
app.listen(3000, () => console.log('Listening on port 3000'));
If you add the above code to your main JavaScript file, save and then run the app using the command node [my_file_name].js
. Then you should be able to navigate to http://localhost:3000/ and see 'Hello World'.
Note: If you are unfamiliar with arrow functions, I recommend having a quick read of this blog post going over some JavaScript techniques new to ECMAScript 6.
Adding a Router
We can separate our programmatic and human web, by adding a suffix to all our API (programmatic) paths. We do this by using a router, which is included in the Express framework.
const express = require('express');
const app = express();
const router = express.Router();
const port = 3000;
// url: http://localhost:3000/
app.get('/', (request, response) => response.send('Hello World'));
// all routes prefixed with /api
app.use('/api', router);
// using router.get() to prefix our path
// url: http://localhost:3000/api/
router.get('/', (request, response) => {
response.json({message: 'Hello, welcome to my server'});
});
// set the server to listen on port 3000
app.listen(port, () => console.log(`Listening on port ${port}`));
Running the above code and navigating to http://localhost:3000/api/ will show you your json message: {message: 'Hello, welcome to my server'}
.
Using URL parameters
Now that we've got our server setup and isolated our API layer using a router, we can start using some URL parameters to do things!
Sending HTTP requests
I recommend using Postman to test APIs, because it's a lovely little GUI for building HTTP requests, you can save them and collect a number of different requests and save them as a suite. You can then even set up expected results for each of the requests, allowing you to unit test your API!
// all of the code from the previous section should be here
const url = require('url');
router.get('/stuff', (request, response) => {
var urlParts = url.parse(request.url, true);
var parameters = urlParts.query;
var myParam = parameters.myParam;
// e.g. myVenues = 12;
var myResponse = `I multiplied the number you gave me (${myParam}) by 5 and got: ${myParam * 5}`;
response.json({message: myResponse});
});
In the above example, using my example value you should receive a json response equal to: {"message":"I multiplied the number you gave me (20) by 5 and got: 100"}
.
Note: For those not using Postman or otherwise sending a HTTP request, you can test this route using the following URL: http://localhost:3000/api/stuff?myParam=12.
CORS
If you're looking to use a HTTP server in production then you will know that we have to take CORS (Cross-Origin Resource Sharing) into account to allow given origins to access our server.
// all our previous code should be here
// this array is used for identification of allowed origins in CORS
const originWhitelist = ['http://localhost:3000', 'https://example.net'];
// middleware route that all requests pass through
router.use((request, response, next) => {
console.log('Server info: Request received');
let origin = request.headers.origin;
// only allow requests from origins that we trust
if (originWhitelist.indexOf(origin) > -1) {
response.setHeader('Access-Control-Allow-Origin', origin);
}
// only allow get requests, separate methods by comma e.g. 'GET, POST'
response.setHeader('Access-Control-Allow-Methods', 'GET');
response.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
response.setHeader('Access-Control-Allow-Credentials', true);
// push through to the proper route
next();
});
The above code implements a middleware route that all requests sent to the /api
namespace will be routed through before continuing to their destination route. This is ideal for adding CORS headers to requests from our whitelist of origins.
Heroku deployment
Heroku is an online Platform as a Service (PaaS) that allows you to host your applications in the cloud for free. Register yourself on the Heroku website found here and create a new application on the dashboard.
If your Git repository for this project is public, you can connect the application to Heroku via the Github option. Otherwise you should download and install the Heroku CLI tools. Follow the instructions for the relevant deployment method.
Once you have completed the instructions you will have a version of your application hosted online. Remember that to test your online app via HTTP requests you will need to add the origin to your whitelist. In the CORS example above, you should replace https://example.net/
with your Heroku app URL.
Leave a comment
You have now successfully setup a RESTful HTTP server on Heroku, it's now up to you to make something useful for the internet! Let me know how you found this tutorial and what you've made using your newfound knowledge!