APIs are the backbone of modern-day software development. Whether we create mobile apps or single-page applications, we need APIs to fetch the data from the backend. Usually, we tend to create REST APIs to solve our API needs. In this post, we will learn how to create a KoaJS REST API.

We will be using JSON format to transmit the data. JSON makes it easy to work with JavaScript applications on the front-end as well.

If you are new to KoaJS, I recommend you first go through the post about getting started with KoaJS.

1 – Installation of KoaJS Packages

To create a REST API using KoaJS, we first need to install a few packages.

Execute the below command:

$ npm install --save koa koa-router koa-body

Below are the details of the three packages:

  • The koa package is the main package. Basically, this has the necessary files for a bare minimum Koa project.
  • Next, we have koa-router. Basically, koa-router package allows us to create a KoaJS route.
  • Lastly, we have the koa-body package. This package allows us to handle JSON request body. You can read more about this package at this link.

KoaJS is a minimal framework. The core of KoaJS has very little lines of code. To extend any functionality, we have to add standard packages. These packages are basically middleware functions that enhance the functionality of our KoaJS application.

Once the packages are installed, we can now create the application.

2 – Creating the KoaJS REST API Routes

As a first step, we will create the API routes.

For demo, consider that we are building a set of API to handle books. Also, we are not using a database and instead, maintaining the records in an array.

See below example of the books.js file we create in our project directory.

const Router = require('koa-router');

const router = Router({
    prefix: '/books'
});

let books = [
    {id: 1, name: 'The Eye of the World', author: 'Robert Jordan'},
    {id: 2, name: 'The Way of Kings', author: 'Brandon Sanderson'}
];

router.get('/', (ctx, next) => {
    ctx.body = books
});

router.get('/:id([0-9]{1,})', (ctx, next) => {
    let fetchedBook = books.filter(book => {
        if(book.id == ctx.params.id) {
            return true;
        }
    })

    if (fetchedBook.length == 1) {
        ctx.body = fetchedBook[0];
    } else {
        ctx.response.status = 404;
        ctx.body = {message: "Book with given id not found"};
    }
})

router.post('/', (ctx, next) => {
    if (!ctx.request.body.name || !ctx.request.body.author) {
        ctx.response.status = 400;
        ctx.body = {message: "Bad request"};
    }else {
        const newId = books[books.length-1].id + 1;
        books.push({
            id: newId,
            name: ctx.request.body.name,
            author: ctx.request.body.author
        })
        ctx.body = {message: "New book created successfully with id: " + newId}
    }
})

router.put('/:id([0-9]{1,})', (ctx, next) => {
    if (!ctx.request.body.name || !ctx.request.body.author) {
        ctx.response.status = 400;
        ctx.body = {message: "Bad request"};
    }else{
        const updateIndex = books.map(book => {
            return book.id
        }).indexOf(parseInt(ctx.params.id))

        if (updateIndex === -1) {
            const newId = books[books.length-1].id + 1;
            books.push({
                id: newId,
                name: ctx.request.body.name,
                author: ctx.request.body.author
            })
            ctx.body = {message: "New book created successfully with id: " + newId} 
        }else{
            books[updateIndex] = {
                id: parseInt(ctx.params.id),
                name: ctx.request.body.name,
                year: ctx.request.body.author
            }
            ctx.body = {message: 'Book details updated successfully'}
        }
    }
})

router.delete('/:id([0-9]{1,})', (ctx, next) => {
    const removeIndex = books.map(book => {
        return book.id
    }).indexOf(parseInt(ctx.params.id));

    if(removeIndex === -1){
        ctx.response.status = 404;
        ctx.body = {message: "Not found"}
    }else{
        books.splice(removeIndex, 1);
        ctx.body = {message: "Book deleted successfully"}
    }
})
  
module.exports = router;

Let us walk through this code in detail:

  • We first important the koa-router package. And then, using this package, we create a router function with prefix set to /books. Basically, this will make sure that all the routes in this file will start with /books.
  • Next, we create a dummy books array with a couple of records.
  • Now, we have to implement the various routes. To cover the entire spectrum, we create route handlers for all important HTTP methods such as GET, POST, PUT and DELETE. Also, we have to two GET methods – one for fetching all books and the other for fetching books by id.
  • To add the routes to the router function, we use router.get(), router.post(), router.put() and router.delete() functions. Each of these handlers has a path property and a callback function to handle the incoming request.
  • As you can see, we manipulate the books array according to the method invoked and return the response by setting the ctx.body() parameter. Here, ctx is the KoaJS application context. If interested, we have detailed posts on KoaJS request handling and KoaJS response handling.
  • At the end, we export the router() function from the books.js file or module.

3 – Creating the KoaJS Application Context

Now, we can create the main file for the KoaJS application context. This is basically the entry point of our application. As a standard, we name it index.js.

const koa = require('koa');
const bodyParser = require('koa-body');
const app = new koa();

app.use(bodyParser());

const books = require('./books.js');

app.use(books.routes());

app.listen(3000, function(){
   console.log('Server running on https://localhost:3000')
});

In this file, we import the necessary packages such as koa and koa-body. Using the koa() function, we create the app context and then, add the bodyParser() middleware to the context. Adding the body parser is needed to handle incoming HTTP requests with payload data.

Next, we also register the book related routes books.js file. Again, this is added as a middleware function.

Finally, we start the application on port 3000.

We can now start the application using node index.js and test the REST API endpoints one by one. They should work as expected.

Conclusion

With this, we have successfully created a KoaJS REST API. In the process, we also implemented a separate file to manage the routes and created route handlers for GET, POST, PUT and DELETE HTTP methods.

Want to implement error handling in your KoaJS application? Check out this post on KoaJS error handling.

If you have any comments or queries about this post, please feel free to mention them in the comments section below.

Categories: BlogKoaJS

Saurabh Dashora

Saurabh is a Software Architect with over 12 years of experience. He has worked on large-scale distributed systems across various domains and organizations. He is also a passionate Technical Writer and loves sharing knowledge in the community.

0 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *