Node.js REST API using Express and Swagger.
Node.js is a powerful and popular platform for building web applications, and it’s particularly well-suited for building REST APIs. In this tutorial, we’ll explore how to use the Express web framework and the Swagger API specification to build a REST API in Node.js.
What is REST?
Before we dive into building a REST API, let’s briefly discuss what REST is. REST stands for Representational State Transfer, and it’s an architectural style for building distributed systems. RESTful systems use HTTP to communicate, and they typically have a few key properties:
- They use resources, identified by URIs, to represent the state of the system
- They use standard HTTP methods (GET, POST, PUT, DELETE, etc.) to manipulate those resources
- They use standard HTTP response codes to indicate success or failure
RESTful APIs are designed to be simple, scalable, and easy to consume. They’re a popular choice for building web APIs, as they work well with a variety of different clients (web browsers, mobile apps, command-line tools, etc.).
What is Express?
Express is a minimalist web framework for Node.js. It provides a simple API for building web applications, and it’s very popular in the Node.js community. Express is designed to be flexible and unopinionated, so you can use it to build any kind of web application you want.
What is Swagger?
Swagger is a specification for describing and documenting APIs. It provides a standardized way to define the endpoints, parameters, responses, and other details of an API. Swagger makes it easy to generate documentation, client libraries, and server stubs for your API.
Getting started with Express
To get started, let’s create a new Node.js project and install Express:
mkdir my-api
cd my-api
npm init
npm install express
Now, let’s create a simple Express app that listens for HTTP requests on port 3000:
const express = require('express')
const app = express()
app.get('/', (req, res) => {
res.send('Hello, world!')
})
app.listen(3000, () => {
console.log('Server started on port 3000')
})
This app defines a single route, which responds to GET requests to the root path (“/”) by sending a simple “Hello, world!” message. We start the app by calling app.listen()
and passing in the port number we want to listen on.
Creating a Swagger specification
Now that we have a simple Express app up and running, let’s add some Swagger documentation to it. We’ll use the swagger-ui-express
and swagger-jsdoc
packages to generate the documentation.
First, let’s install the packages:
npm install swagger-ui-express swagger-jsdoc
Next, let’s create a swagger.js
file in our project's root directory:
const swaggerJsdoc = require('swagger-jsdoc')
const swaggerUi = require('swagger-ui-express')
const options = {
swaggerDefinition: {
restapi: '3.0.0',
info: {
title: 'My API',
version: '1.0.0',
description: 'My REST API',
},
servers: [
{
url: 'http://localhost:3000',
},
],
},
apis: ['**/*.js'],
}
const specs = swaggerJsdoc(options)
module.exports = (app) => {
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(specs))
}
This file defines a function that takes an Express app as an argument and adds a /api-docs
route to it. When this route is accessed in a web browser, it will display the Swagger UI, which is a user interface for browsing and interacting with the API documentation.
The options
object passed to swaggerJsdoc
defines some basic information about our API, including its title, version, and description. It also specifies the base URL of our API.
The apis
property tells Swagger to look for API documentation in all .js
files in our project's directory (including subdirectories).
Adding Swagger to our Express app
Now that we have a swagger.js
file that generates the Swagger documentation, let's add it to our Express app:
const express = require('express')
const swagger = require('./swagger')
const app = express()
app.get('/', (req, res) => {
res.send('Hello, world!')
})
swagger(app)
app.listen(3000, () => {
console.log('Server started on port 3000')
})
We’ve added a require()
statement to import the swagger.js
file, and we've added a call to swagger(app)
after we define our routes. This will add the /api-docs
route to our Express app.
Defining API routes
Now that we have Swagger documentation set up, let’s define some API routes. We’ll create a simple CRUD API for managing a collection of “todo” items.
First, let’s create a todo.js
file in our project's root directory:
let todos = []
exports.getAll = (req, res) => {
res.send(todos)
}
exports.create = (req, res) => {
const todo = req.body
todos.push(todo)
res.send(todo)
}
exports.getById = (req, res) => {
const id = parseInt(req.params.id)
const todo = todos.find((t) => t.id === id)
if (!todo) {
res.status(404).send()
} else {
res.send(todo)
}
}
exports.update = (req, res) => {
const id = parseInt(req.params.id)
const todo = todos.find((t) => t.id === id)
if (!todo) {
res.status(404).send()
} else {
const newTodo = req.body
todos = todos.map((t) => (t.id === id ? newTodo : t))
res.send(newTodo)
}
}
exports.delete = (req, res) => {
const id = parseInt(req.params.id)
todos = todos.filter((t) => t.id !== id)
res.status(204).send()
}
This file exports several functions that define the behavior of our API:
getAll
: returns a list of all todo itemscreate
: creates a new todo itemgetById
: returns a single todo item by IDupdate
: updates a todo item by IDdelete
: deletes a todo item by ID
We’re using an in-memory array to store our todo items for simplicity, but you could easily replace this with a database or some other data store.
Now, let’s update our app.js
file to define the routes for our API:
const express = require('express')
const swagger = require('./swagger')
const todo = require('./todo')
const app = express()
app.use(express.json())
app.get('/', (req, res) => {
res.send('Hello, world!')
})
app.get('/todos', todo.getAll)
app.post('/todos', todo.create)
app.get('/todos/:id', todo.getById)
app.put('/todos/:id', todo.update)
app.delete('/todos/:id', todo.delete)
swagger(app)
app.listen(3000, () => {
console.log('Server started on port 3000')
})
We’re using `app.use(express.json())` to enable JSON parsing for incoming requests, since we’ll be sending JSON data in our API requests and responses.
We’re then defining our API routes using the functions exported from `todo.js`.
Test the API
Now that we’ve defined our API, let’s test it using a tool like `curl` or Postman.
First, let’s create a new todo item:
$ curl -X POST
-H "Content-Type: application/json"
-d '{"title":"Buy milk","completed":false}'
http://localhost:3000/todos
{"title":"Buy milk","completed":false}
This should return the newly created todo item.
Now, let’s fetch a list of all todo items:
$ curl http://localhost:3000/todos
[{"title":"Buy milk","completed":false}]
This should return a JSON array containing our single todo item.
Finally, let’s update the todo item we just created:
$ curl -X PUT
-H "Content-Type: application/json"
-d '{"title":"Buy milk and eggs","completed":true}'
http://localhost:3000/todos/1
{"title":"Buy milk and eggs","completed":true}
This should return the updated todo item.
Conclusion
In this article, we’ve walked through the process of creating a REST API using Node.js and Express, and we’ve added documentation to our API using the Swagger framework. We’ve also shown how to test the API using a tool like `curl`.
There’s a lot more you can do with Node.js and Express to build powerful and scalable APIs, but this should give you a good starting point. Good luck!