DEV Community

Cover image for Adventures of a Hobbyist ~ Part seven
Andrew Bone
Andrew Bone

Posted on • Edited on

Adventures of a Hobbyist ~ Part seven

Playing with routing

What is this?

Here we are in part seven of my learning experience. The aim is to learn node in order to make an opensource web app that can be used by sysadmins for daily tasks.

If you're interested in reading earlier posts here's the index page.

So you mean express?

No, I know express.js is a thing and I know people like it but I thought, to start with at least, I'd try my hand at making a custom router. I don't intend to make it do anything fancy just a simple thing to help me understand the greater concept.

Starting point

To start with I made an incredibly simple proof on concept.

const http = require('http');

function router(url) {
  let address = url.split('/')[1] || "index";
  return address;
}

http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end(router(req.url));
}).listen(80);
Enter fullscreen mode Exit fullscreen mode

It looks at the URL path and prints the first part to the screen, if there's nothing there it prints index. Super simple but proofs we can use a function to work out what need to be printed.

Loading files

The next step was having it load files rather than just pushing text.

const http = require('http');
const fs = require("fs");

const pages = "pages";

function router(url) {
  let address = url.split('/')[1] || "index";
  let content;
  try {
    content = fs.readFileSync(`.\\${pages}\\${address}.html`, 'utf8');
  } catch (err) {
    content = fs.readFileSync(`.\\${pages}\\404.html`, 'utf8');
  }
  return content;
}

http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/html' });
  res.end(router(req.url));
}).listen(80);
Enter fullscreen mode Exit fullscreen mode

I just used readFileSync from fs, it checks if the file exists, if it does it will serve the file if not it will serve the 404 page.

There are a couple of problems with this approach. If I try and browser to http://localhost/home?beta=true I'll get a 404 as .\pages\home?beta=true.html can't be opened, anchors do work, however. Also, there is no support for deeper links like http://localhost/api/userlist.

Limitations

I've already mentioned there are solutions for this out there already so I'm not going to try and overcome these limitations. Though if you want to tell me some ways you'd have solved them I'd love to hear them.

What's next

Next week I'm going to look at express.js and try my hand at making a quick project, I was thinking perhaps a MySQL client to read and maybe write, data. Though, if you have a suggestion for something else I should do I'll happily concider that.

Sorry for the short post, hopefully, I'll be back to the longer ones soon, unless you prefer the short ones of course.
Thanks for reading! 🦄🦄🦄

Top comments (2)

Collapse
 
avalander profile image
Avalander • Edited

Great progress, I enjoy reading these posts!

Though if you want to tell me some ways you'd have solved them I'd love to hear them.

Glad you asked!

If I try and browser to http://localhost/home?beta=true I'll get a 404

Since you're not using the query string at all, the easiest is to simply ignore it. You can use node's url module to parse the url and get the path and query string separately.

const url = require('url')
const path = require('path')
...
function router(request_url) {
    const address = url.parse(request_url).pathname // get only the path of the url, without host or query
        .replace(/\/$/, '') || 'index' // remove the trailing slash, should there be any. Use 'index' if the path is empty
    try {
        const filepath = path.join(__dirname, pages, ...address.split('/'))
        return fs.readFileSync(`${filepath}.html`, 'utf8')
    } catch (err) {
        ...
    }
}

Incidentally, this would also address the other limitation you mention. Using url.parse(...).pathname will get you the full path without the host or the query string, so you can use that to read the correct file.

path.join(pages, ...address.split('/')) will basically return the right file path in any OS, it will append the pages folder to the file's folder (__dirname is the folder where your source file is located) and then replace all slashes in the url path with the OS character to separate folders.

Collapse
 
4lch4 profile image
Devin W. Leaman

Lookin' good so far! I can't wait to see where it goes from here 😊