JavaScript Laufzeitumgebung basierend auf der
V8 JavaScript Engine
Im Browser öffnen: "http://localhost:8000/"
alternativ: "http://localhost:8000/trololol"
Vorteile:
Nachteile:
API für Client als auch Server Funktionalität: Docs
Server 'request' Event bei jeder Client Anfrage
'res.end' MUSS immer aufgerufen werden
Request-Listener '(req, res) => {}' einzigste Server-API
Zuordnung zu einer URL muss programmiert werden
Zuordnung zu einer HTTP-Methode muss programmiert werden
Low-Level Schnittstelle
GET /index.html HTTP/1.1
Host: example.com
HTTP/1.1 200 OK
Server: Apache/1.3.29 (Unix) PHP/4.3.4
Content-Length: 123456
Content-Type: text/html; charset=utf-8
<!DOCTYPE ...
Dokumentation: http.IncomingMessage (req)
Dokumentation: http.OutgoingMessage (res)
Dokumentation: http.OutgoingMessage (res)
Node.js v18 installieren: Downloads
Implementiere einen Echo-Server.
Bei einem GET-Request soll die URL (als plain text)
zurückgegeben werden.
Bei einem POST-Request soll der Inhalt zurückgegeben werden.
Start des Servers (bereit Anfragen entgegenzunehmen) wird auf der Konsole ausgeben
Herunterfahren des Servers wird auf der Konsole ausgeben (Tip: Strg+C -> 'SIGINT', process.on)
High-Level HTTP-Server API
'res.send' MUSS weiterhin immer aufgerufen werden
Open-Source Npm-Module 'express' (expressjs.com)
Defakto-Standard im Node.JS Universum
für Http-Server
Sinnvoller default: mit type('html') wird auch charset=utf-8 verwendet!
Egal welcher "type()" der Inhalt einer Http-Response ist immer ein string!
Erstellt einen Node.JS Server der per GET- und POST-Methode aufgerufen werden kann (z.B. via zwei Buttons in zwei Formularen)
Programmiert den Node.JS Server, sodass:
Gebt im HTML-Dokument die aktuelle Uhrzeit aus
Erstellt einen Node.JS-Server der eine Seite mit einer Überschrift und einem Formular mit einem Eingabefeld generiert.
Programmiert einen kleinen Rechner
Bei Eingabe nicht-nummerischer Werte: Passende Fehlermeldung an passender Stelle
Das erzeugen von HTML-Code ist umständlich!
<body>
Dynamisches HTML mit Server Side Includes
- Datum/Uhrzeit auf dem Server-Rechner:
-
Uhr
- Name dieser HTML-Datei:
-
- Installierte Server-Software:
-
- Ihr Web-Browser:
-
</body>
Quelle: SelfHTML
<form action="action.php" method="post">
Ihr Name:
Ihr Alter:
</form>
<p>
Hallo <?php echo $_POST['name']; ?>.
Sie sind <?php echo $_POST['alter']; ?> Jahre alt.
</p>
<body>
@{ if (IsPost) {
string companyname = Request["CompanyName"];
string contactname = Request["ContactName"];
You entered:
Company Name: @companyname
Contact Name: @contactname
} else {
} }
</body>
<form action="/action" method="post">
Ihr Name:
Ihr Alter:
</form>
<p>
Hallo <% out.println(request.getParameter("name")); %>.
Sie sind <% out.println(request.getParameter("alter")); %> Jahre alt.
</p>
Wir werden "eta" (eta.js.org) nutzen.
Im Browser öffnen: "http://localhost:8000/"
<% if(it.somevalue === 1) { %>
Display this paragraph
<% } else { %>
Display this instead paragraph instead
<% } %>
Spezialvariable: "it"
enthält das gesamte Parameterobjekt
Nach wie vor gilt: Logik von Darstellung trennen(!!)
Bisher: Reine HTML/JSON/Plain-Text antworten auf HTTP-Anfragen.
Aber: Für eine vollständige Website fehlen noch (mindestens) CSS-Dateien und Bilder
Vorsicht: Node.JS+Express sind schnarch langsam statische Dateien auszuliefern. In Produktion auch Load Balancer/Caches/Web-Server nutzen.
Im Browser öffnen: "http://localhost:8000/"
Erstellt einen Node.JS-Server der eine Seite mit einer Überschrfit und einem Formular mit einem Eingabefeld generiert.
Programmiert einen kleinen Rechner
Bei Eingabe nicht-nummerischer Werte: Passende Fehlermeldung an passender Stelle
Zählt die Anzahl der Seitenaufrufe mit einer Instanz-Variable und gebt die Anzahl auf der Seite aus.
Unterscheidet verschiedene Nutzer und gebt spezifische Anzahl an Seitenaufrufen aus (Tipp: HTTP-Header, User-Agent)
HTTP-Status Codes 3xx, Server-Antwort beinhaltet Header "Location" mit neuer URI
HTTP-Status Codes 3xx, Server-Antwort beinhaltet Header "Location" mit neuer URI
Wie lange sind Variablen gültig?
Variablen nur als Teil eines Rendervorgangs gültig
<% it.users.forEach(function(user){ %>
- <%= user.name %>
<% }) %>
Variablen nur als Teil eines Requests gültig
app.get("/result", (req, res) => {
const result = superComplicatedCalculation(req);
res.render("result.eta", { result, method: req.method });
});
Variablen gültigkeit basierend auf dem
Javascript-Blockscope, hier:
Variablen nur als Teil einer Session gültig
app.get("/", (req, res) => {
const session = getSession(req);
console.log(session);
// { id: "a1b2c3d4f5", name: "Max Müller" }
});
Sessions müssen selbst implementiert werden,
z.B.
mit Cookies
Solange Session aktiv ist, können darin Variablen gespeichert werden
Variablen nur als Teil der Server-Instanz gültig
const app = require("express")();
const port = 8000;
app.get("/", (_req, res) => {
res.send(`Server listens on ${port}`);
});
app.listen(port);
Typischerweise genutzt für z.B. Konfiguration, Cache, Startparameter
Programmiert einen kleinen Rechner
Falls einer der Operanden '42' leitet auf eine Easter-Egg-Seite weiter.
Programmiert einen kleinen Rechner
Aufgaben die sich in den Request-Handlern wiederholen:
Funktionen die Zugriff auf das request-, response-Objekt und die next Funktion haben:
(req,
res, next) => void
Mit einem Aufruf von "next" wird der nächste in der Kette aufgerufen
Programmiert einen kleinen Rechner
Problem: HTTP ist ein zustandsloses Protokoll
Bedeutet: Jede Anfrage muss alle Informationen beinhalten um die Antwort generieren zu können
?? Wie dann Sessions im Web anbieten ??
Ohne Sessions keine Warenkorb, kein Einloggen,
kein "Zuletzt betrachtet"
Client muss Info mitschicken, aber Server den Wert vorgeben
!! Cookies !!
Spezifiziert als RFC 2109:
"HTTP
State Management Mechanism"
HTTP-Header: "Set-Cookie" (2)
HTTP/1.0 200 OK
Content-type: text/html
Set-Cookie: theme=light
Set-Cookie: sessionToken=abc123; Expires=Wed, 09 Jun 2021 10:18:14 GMT
darauf folgende Anfrage (3)
GET /spec.html HTTP/1.1
Host: www.example.org
Cookie: theme=light; sessionToken=abc123
…
Einfaches Key=Value Paar, z.B.:
sessionToken=abc123
Value darf alle druckbare ASCII-Zeichen:
"!" bis "~" ohne: "," und ";"
Zusätzliche Attribute:
Domain+Path, Expires/Max-Age, Secure und
HttpOnly
werden mit ";"
hinter den Value gehängt
Nur das Key=Value Paar wird an den Server zurückgeschickt!
Setzt einen Cookie in der HTTP-Antwort
Lese Cookie aus einem HTTP-Request
Middleware um Header zu parsen und an req-Objekt anzuhängen: cookie-parser
document.cookie = "theme=light; Secure;"
document.cookie = "user=Me; Secure;"
document.cookie // theme=light; user=Me
Erweitert den Taschenrechner um ein kleines Login mit Session-spezifischer Historie
Living Standard der WHATWG: WebSockets
Nur wenige Byte Protokoll Overhead: 2 - 10 Byte
Wie kann man sich einen Socket vorstellen?
Raus: socket.send, Rein: socket.onmessage
Native Support in Browsern via "WebSocket"
// Neues WebSocket Objekt anlegen
const socket = new WebSocket('ws://localhost:8000/');
socket.onopen = function () {
// Verbindungsaufbau behandeln
};
socket.onmessage = function(event) {
console.log(event.data); // Neue Nachricht behandeln
};
socket.onclose = function(event) {
// Verbindungsabbau behandeln
};
socket.send("Hello Server");
Programmiert einen Eilmeldungs-Verteiler
Daten länger Speichern als der Server läuft
JSON-Dateien können require'd werden
Node.js-Prozess hat Zugriff auf das Dateisystem als der User der ihn startet
Sicherheitsvorkehrung: Server niemals(!!) als Root/Administrator starten
Dateisystem-API: fs
Mehrere Geschmacksrichtungen:
Callback-API,
Promise-API und
Synchrone-API
Lesen (readFile) und Schreiben (writeFile)
Lesen (readFile) und Schreiben (writeFile)
Ökosystem bietet für (fast) alle Datenbanken
eine Bibliothek:
Erweitert das Taschenrechner-Projekt, um eine JSON-basierte Konfiguration:
Persistiert die Historie in einer Datei