Skip to main content

Let's create a simple RESTful CRUD server with Node.js (and fake db)

Greetings

RESTful API development is one of the most used use cases for Node.js. We will explore how we can build such an API in this post.
As the focus here is on the web layer, I'll use an in-memory data store (an array). Also, I'll use my starter project to save some typing.

The source can be found here.

What we will build

We are going to create CRUD operations for books. It is very simple and we don't go too in-depth as the idea is to create something to play with.

Steps

  • Create the project and install dependencies
  • Create the express server
  • Define end points
  • Fill endpoints

Create the project and install dependencies

npm init -y
npm install express body-parser cors --save
npm install @babel/core @babel/node @babel/preset-env --save-dev
npm install nodemon --save-dev
We need to add module type in package.json in order to use ES6 modules. When we import we need to add .js as well.
in package.json
"type": "module"
"scripts": {
  "start": "nodemon --exec babel-node src/index",
}
Create a file called .babelrc in the project and add the below content.
touch .babelrc
{
  "presets": ["@babel/preset-env"]
}

Create the express server

Create index.js in src folder -> src/index.js and add the below content to create a basic express server.
import express from "express";
import bodyParser from "body-parser";
import cors from "cors";

const app = express();

app.use(cors());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

app.get("/", (req, res) => res.json({ message: "Hello World" }));

app.listen(3000, () => console.log("app listening on port 3000"));

Define our endpoints

Let's create a new module for books as src/book-server.js. Express router has methods for relevant HTTP methods that have path and handler callback. In the handler, we can access request and response objects.
bookRouter.get('/path/:parameter', (req, res) => res.status().json())
  • req.body - gives us the request body, as we have used json-bodyparser this gives us the json object.
  • req.params - gives us request parameters.
  • res.json() - returns the response in json format.
  • res.status() - we can set status codes
import express from "express";

const bookRouter = express.Router();

let books = []; // in-memory data store

bookRouter.get('/', (req, res) => res.json([ { title: "get books" } ]));
bookRouter.get('/:id', (req, res) => res.json({ title: "get book by id" }));
bookRouter.post('/', (req, res) => res.status(201).json({ title: "save book" }));
bookRouter.put('/:id', (req, res) => res.json({ title: "update book" }));
bookRouter.delete('/:id', (req, res) => res.status(204).json({ title: "delete book" }));

export { bookRouter };
Then import it index.js and use it as express middleware.
import { bookRouter } from './book-server.js';

app.use("/books", bookRouter);
Well, that is how simple it is. Run 'npm start' and try out these endpoints.

Let's add logics

This is a simple CRUD application. We do not have special logic other than saving and retrieving. As the idea he is to create basic endpoints, we keep things as simple as possible and use an array to store our data.

GET /books to return all books
bookRouter.get('/', (req, res) => {
  res.json(books);
});
GET /books/:id to return a book with the given id. If the book is not found, 404 will be returned.
bookRouter.get('/:id', (req, res) => {
  const book = books.find(book => book.id === parseInt(req.params.id));
  if (book) {
    res.json(book);
  } else {
    res.status(404).json({ message: "Book not found" });
  }
});
POST /books to save a new book.
bookRouter.post('/', (req, res) => {
  const book = req.body;
  book.id = new Date().valueOf();
  books.push(book);
  res.status(201).json(book);
});
PUT /books/:id to update a book.
bookRouter.put('/:id', (req, res) => {
  const book = books.find(book => book.id === parseInt(req.params.id));
  if (book) {
    const updatable = req.body;
    book.title = updatable.title;
    book.author = updatable.author;
    res.json(book);
  } else {
    res.status(404).json({ message: "Book not found" });
  }
});
DELETE /books/:id to remove a book.
bookRouter.delete('/:id', (req, res) => {
  books = books.filter(book => book.id !== parseInt(req.params.id));
  res.status(204).send();
});
That is it. It is very easy and simple. Let's connect to a database on another day. And also, we need a better packaging structure next time.

Happy learning ☺

Comments