Write a express like api using bunjs
Tags: javascript, webdev, programming, tutorial
Published: 2022-08-10 10:05:00

I came across Youtube to find some interesting tech videos, then I found a video talking about Bun, which is a javascript runtime written in Zig. It introduces itself as an incredibly fast runtime, way more faster than Nodejs.

So I decided to take a try…

I take a look at the http server api from Bun.

Here is how to download bun in command line

```bash
curl -fsSL https://bun.sh/install | bash
```
Here is the first way, if the js file export a default object with fetch function in it, it will start the server.

Inside indexjs
```js
export default {
  fetch(req) {
    return new Response("HI!");
  },
};
```
Or you can use Bun.serve
```js
Bun.serve({
  fetch(req) {
    return new Response("HI!");
  },
});
```
To start server, run `bun run index.js`

And that’s it ! Everything is working…


**But this api is too down level, it means it needs developers to write duplicate code when project gets big. So I decided to make an express like api using bun from scratch, every one new to bun would no need to learn the bun api if they have experience on express.**

Here is what I do.

First, we need to handle the request.

We create a BunServer class with http method in it.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yqilspcv1zozs9va7j2i.png)

Everything go through the http method will use delegate function to handle.

`requestMap` is store the map of path and its handler.

`middlewares` stores all the middlewares user declares


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lq3g993w6d4gcm4w74ez.png)
Above is the delegate function, which we store them in cache.

And that’s how we handler request, pretty simple.

Then it’s the middleware.

On express, we have middleware function with signature `(req, res, next)` , it’s a [chain of responsibility](https://en.wikipedia.org/wiki/Chain-of-responsibility_pattern) design pattern. Here is how I implemented.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1un1quwo6wa6tutp2u3u.png)

I created a `Chain` class to handle middlewares passing. Just a few things you need to know here.

1. every next function is called, will do `index++` , we get the callback function from middlewares with that index.
2. Stop signal. To stop the middleware from passing, we check `this.ready` first, which user returns response from one of the middlewares. And `this.isFinish()` , we had already called all the middlewares.

Finally, we wrap things up on the fetch method on bun api.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hjw0g6v21yxq42lw2r98.png)
When the request comes in, we first called all the middlewares first, if the middleware does not stop the request, we called the request handler, which we actually how to handle our business logic.

Here is how to use it.

The package is called bunrest, it’s already published on npm
```js
npm i bunrest
```
First create a server object
```js
import App from 'bunrest'
const server = new App.BunServer();
```
Then you can use it like on express.
```js
server.get('/test', (req, res) => {
  res.status(200).json({ message: 'succeed' });
}, (req, res, next) => {
  console.log('get');
  next();
});
server.put('/test', (req, res) => {
  res.status(200).json({ message: 'succeed' });
}, (req, res, next) => {
  console.log('put');
});
server.post('/test', (req, res) => {
  res.status(200).json({ message: 'succeed' });
});
```
Add middlewares
```js
// or you can add the middlewares this way
server.get('/user', 
    (req, res) => { /** handle request **/ }, 
    (req, res, next) => {
      /**
       *  Handle middlewares
       * */
    });
```
Add router
```js
// add router
const router = server.Router();

router.get('/test', (req, res) => {
  res.status(200).json({ message: 'Router succeed' });
})

router.post('/test', (req, res) => {
  res.status(200).json({ message: 'Router succeed' });
})

router.put('/test', (req, res) => {
  res.status(200).json({ message: 'Router succeed' });
})

server.use('/your_route_path', router);
```
Finally, to start the server
```js
server.listen(3000, () => {
  console.log('App is listening on port 3000');
});
```
If you want to checkout the source code or contribute, here is the [github](https://github.com/lau1944/bunrest) page