Skip to content

Latest commit

 

History

History
134 lines (100 loc) · 3.36 KB

CHAP02.md

File metadata and controls

134 lines (100 loc) · 3.36 KB

In this chapter, we are going to make the route matching logic bit more stable.

Currently our handle looks like the following:

proto.handle = function handle(req, res, out) {
    var self = this;
    var stack = self.stack;
    var layer = stack[0];
    var route = layer.route;
    route.stack[0].handle_request(req, res);
}

It served our purpose in chapter 1, but lets make it more stable. Lets make changes such a way that, it can match the path automatically. Remember, the path data is already stored in Route's path (In doubt, play around by printing the Router stack when needed).

We will require this library parseurl to parse the url. Defining the util functions in router.js first:

var parseUrl = require('parseurl');

...

function getPathname(req) {
    try {
        return parseUrl(req).pathname;
    } catch (err) {
        return undefined;
    }
}

Now its time to change our handle function:

proto.handle = function handle(req, res, out) {
    var self = this;
    var stack = self.stack;
    var path = getPathname(req);

    // find next matching layer
    var layer;
    var match;
    var route;
    var idx = 0

    while (match !== true && idx < stack.length) {
        layer = stack[idx++];
        match = matchLayer(layer,path)
        route = layer.route;

        if (match !== true) {
            continue;
        }

        if (!route) {
            // process non-route handlers normally
            continue;
        }

        route.stack[0].handle_request(req, res);
    }
}

function matchLayer(layer, path) {
    try {
        return layer.match(path);
    } catch (err) {
        return err;
    }
}

Ok, lets understand whats going on here. I have defined a variable called match & idx. We are iterating until my stack is empty (all our config is pushed into Router's stack). We will pick each layer out of the stack and call matchLayer. We will implement matchLayer in a moment, but assume it returns boolean if a path is matched at a given layer object. If so, we will pick its route and then call the route's handle_request by passing req & res. Else repeat until the stack is empty.

The implementation of matchLayer looks like this:

Layer.prototype.match = function match(path) {
    return this.route.path === path;
};

Simple check. It checks path matches the request path. That's all!

Now lets play around:

let express = require('./src/express')
const app = express()

app.get('/', (req, res) => {
    res.writeHead(200)
    res.write('Hello world from /');
    res.end();
});


app.get('/2', (req, res) => {
    res.writeHead(200)
    res.write('Hello world from /2');
    res.end();
});

app.post('/post',(req,res) => {
    res.writeHead(200)
    res.write('Data from post :)');
    res.end();
})

app.listen(3000, () => console.log('Example app listening on port 3000!'))

Now try hitting /, we will get Hello world from /; for /2 we will get the corresponding output.

I have also made a post handler here, so lets fire a post request:

curl --request POST http://localhost:3000/post

-- Data from post :)

That's cool progress. We have made our routing logic works. In the next chapter, we will actually build a small next (the magic guy).