Eenvoudige lokale webserver met node.js

Als je websites bouwt door de code zelf helemaal in te kloppen, zoals ik dat doe, kun je de code van je webpagina's eenvoudig testen op juistheid door het HTML-bestand in Verkenner aan te klikken. De standaard-browser start dan en toont de pagina.
Meestal werkt dat prima. HTML, CSS en JavaScript wordt correct uitgevoerd. De developer tools, die tegenwoordig in elke goede browser aanwezig zijn, kun je inzetten om de fouten er uit te halen.

Er zijn echter situaties waarin de hierboven beschreven aanpak niet werkt. Dat is o.a. het geval als je met cookies aan de gang gaat. Je browser heeft dan toegang nodig tot het filesystem (zeg maar de harddisk) van de computer. De beveiliging laat echter geen schrijf-acties toe toe.
Dit gaat op voor alle moderne, goed bijgewerkte browsers in combinatie met een recente versie van het Operating System.
In dit betoog wordt gewerkt met Windows 10-2004 met Edge Chromium versie 85.

Dit probleem is te omzeilen met een eenvoudige webserver, die wél naar de harddisk kan/mag schrijven.

Hieronder wordt een eenvoudige webserver beschreven die is geschreven in JavaScript, in de node.js variant om precies te zijn.

Er wordt vanuit gegaan dat node.js op de computer is geïnstalleerd en dat het werken met modules en de package manager npm bekend zijn. Er wordt dus niet ingegaan op het werken met node.js op een lokale computer. Daarvoor wordt verwezen naar de documentatie op internet.
Voor het voorbeeld is aangenomen dat de noodzakelijke modules lokaal zijn geïnstalleerd en de website zich in submappen van de zelfde map bevinden, zoals hier onder wordt getoond.

De root-map is C:\Websites. Daaronder hangt een aantal mappen, waarvan er twee van belang zijn: Nodejs en demosite. Andere bestanden en submappen zijn voor het voorbeeld niet van belang.
In de map Nodejs staat de submap Local server. Andere submappen en/of files zijn niet nodig voor het voorbeeld.
In de map Local server staan tenminste de file demoserver.js en de submap node_modules.
De file demoserver.js bevat de code die door node.js wordt uitgevoerd.
De submap node_modules bevat de modules (hulpprogramma's) die node.js nodig heeft om de webserver te kunnen draaien.
De map demosite bevat de website-bestanden: .HTML, .CSS en .JS. Uiteraard is er ook een file index.html.

De code van demoserver.js ziet er als volgt uit:

// Eenvoudige webserver, uitgebreid EJS (dynamische HTML-templates)

// 0. initialisatie en variabelen
var http = require('http'),
    colors =require('colors'),
    fs = require('fs'),
    path = require('path'),
    mime = require('mime'),
    ejs = require('ejs'),
    global = '../../demosite/',
    ip = require('ip');

// 0. Toon het IP-adres
console.log('\nUw IP-adres: ',ip.address().yellow);

// 1. Maak de webserver
var server = http.createServer(function (req, res) {
    // 1a. Check of de global wordt opgevraagd.
    var fileName = '';
    var url = req.url;
    if (url === '/') {
        url = 'index.html'; // redirect als geen bestandsnaam is opgegeven
    }
    fileName = global + url;
    console.log('Gevraagd bestand: ', path.basename(fileName).yellow);

    // 1b. Check of bestand bestaat.
    fs.exists(fileName, function (exists) {
        if (exists) {
            serveFile(fileName); // ja.
        } else {
            fileName = global + 'verdwenen.htm'; // nee
            serve404(fileName);
        }
    });

    // 1c. Serveer gevraagde bestand.
    function serveFile(requestFile) {
        // 2. Maak een stream en server op basis van Events
        res.writeHead(200, {'Content-Type': mime.getType(requestFile)});
        var stream = fs.createReadStream(requestFile);
        stream.on('data', function (chunk) {
            res.write(chunk);
        });
        stream.on('end', function () {
            res.end();
        });
        stream.on('error', function (err) {
            console.log('error: '.red + err);
        });
    }

    // 1d. Serveer 404, inclusief juiste http-header
    function serve404(requestFile) {
        res.writeHead(404, {'Content-Type': mime.getType(requestFile)});
        fs.readFile(requestFile, 'utf8', function (err, data) {
            if (err) {
                console.log('Error: '.yellow.bold, err);
            } else {
                res.end(data);
            }
        })
    }
});

// 2. Start de server
server.listen(3080, function () {
    console.log('Server gestart op poort :3080'.green);
});

Werken met de webserver
De webserver werkt in een command-line-window. Als je niet gewend met command-line interfaces te werken is dat in het begin wat lastig, maar het went snel.
Het command-line-window voor de webserver maak je het beste met een snelkoppeling. Die hoef je maar één keer te maken. Dat gaat als volgt:

Start nu de webserver op door op de snelkoppeling te dubbelklikken, zie de figuur hier onder.

Het lokale IP-adres van je computer wordt getoond met de gele letters, voor het poort-nummer zijn groene letters gebruikt.

Open vervolgens een browser-window. In de adresbalk typ je het IP-adres gevolgd door een dubbele punt en het nummer van de poort: 192.168.2.4:3080
De server zoekt nu naar index.html en stuurt die naar de browser. Als je een ander bestand wilt dan index.html, dan typ je bijvoorbeeld in de adresbalk: 192.168.2.4:3080/ander_bestand.html.
Alle bestanden die de server verstuurt worden getoond in het command-line-window, zie hieronder.

Je sluit de webserver af door in het command-line-window Control+C te typen. Met exit sluit je het command-line-window. Je kunt natuurlijk ook gewoon op het kruisje in de rechterbovenhoek klikken.

Er is een kleine onvolkomenheid…
Deze webserver kan niet overweg het parameters die aan de HTML worden meegegeven. Een URL zoals abcd.html?p=123&q=456 is dus niet mogelijk. Zie ook het item HTML met parameters.

Opmerking:
Je kunt in plaats van een command-line-window ook een PowerShell gebruiken. Op het moment dat dit geschreven wordt heeft dat een klein nadeel: De colors-module werkt daar niet helemaal goed. Kleuren komen dan niet altijd goed op het scherm. De server zelf werkt goed onder PowerShell.

 
terug

html-608; Laatste wijziging: 27 november 2020