Node.js/Webserver

Aus SELFHTML-Wiki
Wechseln zu: Navigation, Suche
Ruft ein Seitenbesucher eine Internetseite auf, so sendet der Browser einen "Request", (englisch für Anfrage) an den Webserver, die von diesem mit einer "Response" (englisch für Antwort) beantwortet wird. Dabei senden sich Browser und Webserver gegenseitig Textdateien zu, in denen nach den Regeln von HTTP diverse Informationen enthalten sind.
Hauptartikel: HTTP/Einsteiger-Tutorial

Die für eine Response nötige Software fällt im Allgemeinen in zwei Kategorien: Frontend und Backend.

  • Das clientseitige Frontend wird aus HTML, CSS und, falls Interaktivität nötig ist, JavaScript zusammengebaut.
  • Das serverseitige Backend befasst sich mit dem Austausch, der Verarbeitung und Speicherung von Daten auf dem Server.

Mit Node.js können Sie JavaScript auch im Backend auf dem Server nutzen.

In diesem Tutorial lernen Sie, wie Sie einen Webserver mit dem in Node.js schon enthaltenen http-Modul einrichten können. Das Beispiel basiert auf einem Konzept von Jared Wilcurt, das auf github zu finden ist.

Mein erster Webserver

Node.js hat ein eingebautes Modul namens HTTP, das es Node.js ermöglicht, Daten über das Hyper Text Transfer Protocol (HTTP) zu übertragen.

Um das HTTP-Modul einzubinden, verwende die require()-Methode.[1] Es hat sich als Konvention etabliert, dass die Variable dem Namen des eingebundenen Moduls entspricht.

 1 const http = require('http'); 
 2 var port = 8080;
 3 
 4 http.createServer((request, response) => { 
 5   response.writeHead(200, { 
 6     'Content-Type': 'text/plain' 
 7   }); 
 8   response.write('Server funzt!\n'); 
 9   response.end(); 
10 }).listen(port);

Die createServer()-Funktion erzeugt einen Server, der als Parameter ein Anfrageobjekt (request) und ein Antwortobjekt (response) enthält.

  1. Die HTTP-Anfrage wird im Anfrageobjekt erfasst.
  2. Die HTTP-Antwort wird mit weiteren Methoden erzeugt:
    1. response.writeHead() sendet einen Dokument-Header, der …
      • dem Browser mitteilt, dass die Anfrage erfolgreich war (status code 200) und Klartext übermittelt wird.
    2. response.write() übermittelt den body (Dokumentinhalt) der Seite
    3. response.end() zeigt, dass header und body der Response übermittelt worden sind.
  3. mit listen() kann der Port übermittelt werden.
Aufgabe:

Speicher das Script als server.js und rufe es im Terminal auf.

Starte deinen Browser und gib die URl: http://localhost:8080 ein:

Screenshot des Node.js-Servers in Chrome

Die Angabe localhost für die interne IP-Adresse 127.0.0.1 ist nur für den lokalen Computer verfügbar, nicht für die lokalen Netzwerke, mit denen wir verbunden sind, oder gar für das Internet.

Beachten Sie: Die Eingabeaufforderung verschwindet, da der Node.js-Server so lange läuft, bis ein Fehler zum Absturz des Servers führt, oder der Node.js-Prozess, der den Server ausführt, angehalten wird.

Um im Terminal anzuzeigen, dass der Server läuft, können wir eine Meldung ausgeben:

var port = 8080;
...

http.createServer((request, response) => { 
...
}).listen(port);

// Nachricht, die im Terminal ausgegeben wird.
console.log(WHT + 'Statischer Webserver läuft auf\n  => http://localhost:' + port + '/\nCTRL + C zum Beenden');

Ausliefern einer Webseite

In einem zweiten Schritt soll unser Webserver nicht nur einen Text, sondern eine komplette Webseite in HTML senden.

const http = require('http'); 
let port = 8080;

http.createServer((request, response) => { 
 response.writeHead(200, { 
 'Content-Type': 'text/html' 
}); 
  response.write(`<html><body><h1>Das ist HTML</h1><p>Und das ein Absatz!</p></body></html>`);
  response.end(); 
}).listen(port);

// Nachricht, die im Terminal ausgegeben wird.
console.log(WHT + 'Statischer Webserver läuft auf\n  => http://localhost:' + port + '/\nCTRL + C zum Beenden');

In response.writeHead wird der MIME-Type auf text/html geändert. response.write sendet einen langen String voller HTML-Tags. Schön ist anders.

Im Normalfall sendet ein Server als Antwort auf eine Anfrage nicht eine Zeichenkette, sondern ein HTML-Dokument und weitere Dateien wie Bilder, PDFs oder Videos. Ob diese als physische Dateien auf dem Server vorhanden sind oder vom Server aus Inhalten einer Datenbank dynamisch zusammengestellt wird, spielt dabei keine Rolle. Diese Aufgabentrennung (engl. Separation of concerns) ermöglicht es, unsere Scripte kürzer und übersichtlicher zu halten.

File System - Dateien schreiben und lesen

Unser Server wird nun so erweitert, dass er Dokumente mit dem passenden MIME-Type ausliefert. Anfragen ohne entsprechenden Inhalt sollen nicht mit 200 (ok), sondern mit einer Fehlermeldung 404 (not found) beantwortet werden.

Eigentlich kann JavaScript Dateien weder auslesen noch schreiben. Mit dem in Node.js integrierten File System ist dies mittlerweile möglich.[2]

Das Filesystem wird mit require(fs) aufgerufen.

// Require in some of the native stuff that comes with Node
var http = require('http');
var url = require('url');
var path = require('path');
var fs = require('fs');

// Port number to use
var port = 8080;
// Colors for CLI output
var WHITE = '\033[39m';
var RED = '\033[91m';
var GREEN = '\033[32m';

// Create the server
http.createServer(function (request, response) {

    // The requested URL, like http://localhost:8000/file.html => /file.html
    var uri = url.parse(request.url).pathname;
    // get the /file.html from above and then find it from the current folder
    var filename = path.join(process.cwd(), uri);

    // Setting up MIME-Type (YOU MAY NEED TO ADD MORE HERE) <--------
    var contentTypesByExtension = {
        '.html': 'text/html',
        '.css':  'text/css',
        '.js':   'text/javascript',
        '.json': 'text/json',
        '.svg':  'image/svg+xml'
    };

    // Check if the requested file exists
    fs.exists(filename, function (exists) {
        // If it doesn't
        if (!exists) {
            // Output a red error pointing to failed request
            console.log(RED + 'FAIL: ' + filename);
            // Redirect the browser to the 404 page
            filename = path.join(process.cwd(), '/404.html');
        // If the requested URL is a folder, like http://localhost:8000/catpics
        } else if (fs.statSync(filename).isDirectory()) {
            // Output a green line to the console explaining what folder was requested
            console.log(GREEN + 'FLDR: ' + WHITE + filename);
            // redirect the user to the index.html in the requested folder
            filename += '/index.html';
        }

        // Assuming the file exists, read it
        fs.readFile(filename, 'binary', function (err, file) {
            // Output a green line to console explaining the file that will be loaded in the browser
            console.log(GREEN + 'FILE: ' + WHITE + filename);
            // If there was an error trying to read the file
            if (err) {
                // Put the error in the browser
                response.writeHead(500, {'Content-Type': 'text/plain'});
                response.write(err + '\n');
                response.end();
                return;
            }

            // Otherwise, declare a headers object and a var for the MIME-Type
            var headers = {};
            var contentType = contentTypesByExtension[path.extname(filename)];
            // If the requested file has a matching MIME-Type
            if (contentType) {
                // Set it in the headers
                headers['Content-Type'] = contentType;
            }

            // Output the read file to the browser for it to load
            response.writeHead(200, headers);
            response.write(file, 'binary');
            response.end();
        });

    });

}).listen(parseInt(port, 10));

// Nachricht, die im Terminal ausgegeben wird.
console.log(WHITE + 'Static file server running at\n  => http://localhost:' + port + '/\nCTRL + C to shutdown');

Screenshot des Node.js-Servers in Chrome

Ein solcher Server könnte einfach zu einem HTTPS-Server erweitert werden. Dazu würdest Du aber noch Zertifikate benötigen.[3]

Weblinks

  • github:
    • npm-Free-Server
      This is a very tiny server. Without comments it's 50 lines of code and it's <1KB (minified).
    • local-web-server
      A lean, modular web server for rapid full-stack development.
      • Supports HTTP, HTTPS and HTTP2.
      • Small and 100% personalisable. Load and use only the behaviour required by your project.
      • Attach a custom view to personalise how activity is visualised.
      • Programmatic and command-line interfaces.

Quellen

  1. Node.js: require()
  2. Node.js: File System
  3. Node.js: How to create an https server?.