Monday, October 19, 2020

How to Create Your First REST API with Fastify

Fastify is a framework designed for back-end web development. It offers a more lightweight alternative to heavier Node.js API frameworks, such as Hapi and Express. From July 2020, Fastify has released its third version of the framework. This third version comes with improved validation abilities to verify incoming and outgoing requests, as request parameters. Moreover, the third version of the framework consolidates its throughput claims of being the fastest Node.js framework compared with Koa, Resitfy, Hapi, and Express. More information can be found on the benchmarks page.

Fastify has gained a lot of popularity due to its lightweight design. However, a lot of attention goes to its plugin ecosystem. Fastify has adopted the idea that everything is a plugin, whereas with JavaScript, everything is an object. This allows you to quickly encapsulate functionality for your project as a plugin and distribute it so other projects can use your code.

Let’s get started with this tutorial. You’ll learn the following aspects of Fastify:

  • How to set up your first Fastify API
  • How to define Fastify API routes
  • How to add schema validation to requests
  • How to load and use Fastify plugins
  • How to define Fastify hooks

Requirements and Installation

To follow this tutorial, you’ll need:

  1. the latest Node.js version
  2. a tool for sending requests, such as cURL or Postman

Next, make sure to create an empty Node.js project. If you don’t have one yet, you can use the following command to set up your project:

npm init -y

Lastly, we want to add this Fastify dependency to our project:

npm i fastify --save

All good? Let’s create our basic API setup in the next step.

Step 1: Basic API Setup

First, let’s create our basic API setup. To get started, we need to create a new file called index.js within our project root:

touch index.js

Next, let’s add the basic server setup. Copy the code below:

// Require the framework and instantiate it
const app = require('fastify')({
    logger: true
})

// Declare a route
app.get('/', function (req, reply) {
    reply.send({ hello: 'world' })
})

// Run the server!
app.listen(3000, (err, address) => {
    if (err) {
        app.log.error(err)
        process.exit(1)
    }
    app.log.info(`server listening on ${address}`)
})

There are a couple of things happening here. We first load the Fastify application object and enable logging. Next, we declare a root route that replies with a JSON response. The last part of the code snippet shows that we’re listening on port 3000 for the application to receive requests.

Let’s validate if your basic server setup works. First, we need to start the server by running the index.js file:

node index.js

Thereafter, navigate to http://localhost:3000 in your browser. You should see the following response:

{
    "hello": "world"
}

Success? Let’s go to Step 2 to define different CRUD routes.

Step 2: Define CRUD Routes

An API is useless with only GET routes. Let’s define more routes for handling blogs. Therefore, let’s create the following routes:

  • GET all blogs at /api/blogs
  • GET one blog at /api/blogs/:id
  • POST add blog at /api/blogs
  • PUT update blog at /api/blogs/:id
  • DELETE delete blog at /api/blogs/:id

The first thing to do is creating a blog controller.

Step 2.1: Create Blogs Controller

To keep our code clean, let’s define a controller folder in the project root. Here, we create a file called blogs.js.

This file contains some demo data to avoid complicating this tutorial with a database integration. Therefore, we use an array containing blog objects which each contain an ID and title field.

Moreover, we define the different handlers for all the above routes in this file. A handler always accepts a req (request) and reply parameter. The request parameter is useful to access request parameters or request body data.

Add the following code to your /controller/blogs.js file:

// Demo data
let blogs = [
    {
        id: 1,
        title: 'This is an experiment'
    },
    {
        id: 2,
        title: 'Fastify is pretty cool'
    },
    {
        id: 3,
        title: 'Just another blog, yea!'
    }
]

// Handlers
const getAllBlogs = async (req, reply) => {
    return blogs
}

const getBlog = async (req, reply) => {
    const id = Number(req.params.id) // blog ID
    const blog = blogs.find(blog => blog.id === id)
    return blog
}

const addBlog = async (req, reply) => {
    const id = blogs.length + 1 // generate new ID
    const newBlog = {
        id,
        title: req.body.title
    }

    blogs.push(newBlog)
    return newBlog
}

const updateBlog = async (req, reply) => {
    const id = Number(req.params.id)
    blogs = blogs.map(blog => {
        if (blog.id === id) {
            return {
                id,
                title: req.body.title
            }
        }
    })

    return {
        id,
        title: req.body.title
    }
}

const deleteBlog = async (req, reply) => {
    const id = Number(req.params.id)

    blogs = blogs.filter(blog => blog.id !== id)
    return { msg: `Blog with ID ${id} is deleted` }
}

module.exports = {
    getAllBlogs,
    getBlog,
    addBlog,
    updateBlog,
    deleteBlog
}

Note how we can access the request parameter for routes such as /api/blogs/:id via req.params.id. For POST and PUT routes, we can access the body of the request via req.body.

In step 2.2, we’ll connect the route handlers to the route objects.

Step 2.2: Define Blog Routes and Couple Blogs Controller

Again, to keep our code clean, let’s define a routes folder in the project root. Here, we create a file called blogs.js. This file holds the routes object for our blog routes:

mkdir routes
cd routes
touch blogs.js

Luckily, Fastify allows us to define an array containing route objects. Here, we can couple the handlers we’ve defined previously to the different routes. Don’t forget to require the blogs controller. Let’s take a look:

const blogController = require('../controller/blogs');

const routes = [{
        method: 'GET',
        url: '/api/blogs',
        handler: blogController.getAllBlogs
    },
    {
        method: 'GET',
        url: '/api/blogs/:id',
        handler: blogController.getBlog
    },
    {
        method: 'POST',
        url: '/api/blogs',
        handler: blogController.addBlog
    },
    {
        method: 'PUT',
        url: '/api/blogs/:id',
        handler: blogController.updateBlog
    },
    {
        method: 'DELETE',
        url: '/api/blogs/:id',
        handler: blogController.deleteBlog
    }
]
module.exports = routes

Now we’ve defined all routes. However, Fastify doesn’t know about these routes. The next step shows how you can register routes with your Fastify application object.

Continue reading How to Create Your First REST API with Fastify on SitePoint.


by Michiel Mulders via SitePoint

No comments:

Post a Comment