SawyerBx
SawyerBx

Reputation: 21

Paramaters in a Node.js HTTP server

I'm trying to make a simple HTTP module, similar to express, to help learn how to use HTTP.

When working with express I often use parameters such as:

app.get('/id/:id' (req, res) => {console.log(req.params.id); stuff})

I was wondering-

  1. Is it possible just using HTTP?
  2. If it isn't able to be done with just HTTP, then how would you go about creating it?

Upvotes: 2

Views: 1130

Answers (2)

slebetman
slebetman

Reputation: 114024

Yes but you need to process it manually.

Assuming you're using node's http module, the information you are looking for is in req.url but it includes the whole url path.

For example, you want to parse /id/:id, and the browser is making a request to http://your.server/id/100?something=something. Then the value of req.url will be:

/id/100?something=something

But if you are writing an HTTP module from scratch using the net module then you need to know the format of an HTTP request. Basically an HTTP request looks like a text file with the following format:

GET /id/100?something=something HTTP/1.1
Host: your.server

The header section ends with double newlines. Technically it should be \r\n\r\n but \n\n is also acceptable. You first need to get the url from the first line of the request between the protocol (GET in the example above but can be POST, PUT etc.) and the HTTP version number.

For anyone interested in writing a HTTP server from scratch I always recommend James Marshall's excellent article: https://www.jmarshall.com/easy/http/. It was originally written in the late 90s but to this day I haven't found a clearer summary of the HTTP protocol. I've used it myself to write my first HTTP server.

Now you have to write code to extract the 100 from the string.

If you are doing this manually, not trying to write a framework like Express, you can do it like this:

const matches = req.url.match(/id\/([^\/?]+)/);
const id = matches[1];

If you want to write a library to interpret the /id/:id pattern you can maybe do something like this (note: not an optimized implementation, also it behaves slightly differently to express):

function matchRoute (req, route) {
    const [ urlpath, query ] = req.url.split('?'); // separate path and query
    const pathParts = urlpath.split('/');
    const routeParts = urlpath.split('/');
    let params = {};

    for (let i=0; i<pathParts.length; i++) {
        if (routeParts[i].match(/^:/)) { // if route part starts with ":"
            // this is a parameter:
            params[routeParts[i].replace(':','')] = pathParts[i];
        }
        else {
            if (routeParts[i] !== urlParts[i]) {
                return false; // false means path does not match route
            }
        }

        // if we get here (don't return early) it means
        // the route matches the path, copy all found params to req.params:

        req.params = params;
        return true; // true signifies a match so we should process this route
    }
}

// Test:
let req.url = '/id/100';
let result = matchRoute(req, '/id/:id');
console.log(result, req.params); // should print "true, {id:100}"

Upvotes: 1

Mestre San
Mestre San

Reputation: 1925

Your question is a little bit confusing but I think what you mean is how to implement an HTTP Router in pure javascript instead of relying on a framework like express.

If that's the case I support your initiative 100%! It's really important to understand what is going on behind the scenes.

A good way to really understand a good way to do so would be by reading the source code of a good router that is already out there.

You could study the Express router's source code but I recommend you to go play with find-my-way which is a dedicated router that you can use with HTTP only without any other framework.

Upvotes: 1

Related Questions