Block 01 295¶
2.3 Aufgabe: Routing¶
Hier mein Code:
const http = require('http');
const port = 4010;
const server = http.createServer((req, res) => {
// Header setzen, damit HTML richtig gerendert wird
res.setHeader('Content-Type', 'text/html; charset=utf-8');
// Einfaches Routing basierend auf der URL
if (req.url === '/ueberblick') {
res.statusCode = 200;
res.end('<h1>ueberblick</h1>');
}
else if (req.url === '/produkte') {
res.statusCode = 200;
res.end('<h2>hier sehen Sie unsere Produkte</h2>');
}
else {
res.statusCode = 404;
res.end('Seite nicht gefunden');
}
});
// Server auf Port 4010 starten
server.listen(port, '0.0.0.0', () => {
console.log(`Webserver läuft ohne Express auf Port ${port}`);
});
API¶
const http = require('http');
const port = 4010;
const server = http.createServer((req, res) => {
const headers = { 'Content-Type': 'application/json; charset=utf-8' };
if (req.url === '/ueberblick') {
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
res.end('<h1>ueberblick</h1>');
}
else if (req.url === '/produkte') {
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
res.end('<h2>hier sehen Sie unsere Produkte</h2>');
}
// API Route: Gibt bei jedem Reload ein zufälliges Handy zurück
else if (req.url === '/api' || req.url === '/api/handys') {
res.writeHead(200, headers);
const handyModelle = [
{ id: 1, marke: "Apple", modell: "iPhone 15 Pro", speicher: "256GB" },
{ id: 2, marke: "Samsung", modell: "Galaxy S24 Ultra", speicher: "512GB" },
{ id: 3, marke: "Google", modell: "Pixel 8 Pro", speicher: "128GB" },
{ id: 4, marke: "Xiaomi", modell: "14 Ultra", speicher: "512GB" }
];
// Zufalls-Logik:
// Math.random() erzeugt eine Zahl zwischen 0 und 1.
// Multipliziert mit der Länge des Arrays und abgerundet ergibt das einen gültigen Index.
const randomIndex = Math.floor(Math.random() * handyModelle.length);
const randomHandy = handyModelle[randomIndex];
res.end(JSON.stringify(randomHandy, null, 2));
}
else {
res.writeHead(404, { 'Content-Type': 'text/plain; charset=utf-8' });
res.end('Seite nicht gefunden');
}
});
server.listen(port, '0.0.0.0', () => {
console.log(`Server läuft auf Port ${port} - Zufalls-Modus aktiv`);
});
ie API-Logik im Überblick¶
-
Pfad-Erkennung: -- Der Code prüft mit
if (req.url === '/api'), ob der User gezielt die Datenschnittstelle anspricht. -- -
Daten-Quelle: -- In der Variable
handyModelleliegt eine Liste (Array) mit verschiedenen Smartphone-Objekten. -- -
Zufalls-Berechnung: -- Die Funktion
Math.random()generiert einen Wert, der mit der Anzahl der Handys multipliziert wird -- um bei jedem Seitenaufruf einen anderen Listenplatz auszuwählen. -- -
Mathematik: -- Durch das Abrunden mit
Math.floor()entsteht ein gültiger Index -- für den Zugriff auf die Liste. -- -
Daten-Umwandlung: -- Da der Browser keinen puren Javascript-Code versteht, wird das Objekt mit
JSON.stringify()in einen Text-String umgewandelt. -- -
Ausgabe: -- Mit
res.end()wird genau dieses eine ausgewählte Handy an den Client gesendet -- und die Verbindung geschlossen
Man kann nun aktualisieren und jedes mal wird ein neues Handy angezeigt.
Fish API¶
Fish API¶
Eine einfache Fischmarkt-API mit Express und EJS.
Installation¶
Starten¶
Die API läuft auf http://localhost:3000
Endpoints¶
Homepage¶
-
URL:
http://localhost:3000/ -
Methode: GET
-
Beschreibung: Zeigt alle Fische in einer HTML-Seite mit Vintage-Design
JSON API¶
-
URL:
http://localhost:3000/api/fish -
Methode: GET
-
Beschreibung: Gibt alle Fische als JSON zurück
Daten¶
Die Fische sind in data.json gespeichert mit 4 Feldern:
-
id- Eindeutige ID -
name- Name des Fisches -
price- Preis pro Kg -
origin- Herkunftsland
Beispiel¶
Dateien¶
-
app.js- Express Server -
index.html- HTML Template mit EJS -
data.json- Fisch-Daten -
package.json- Dependencies
Design¶
Vintage Fischmarkt-Design mit:
-
Braun/Beige Farbschema
-
Grid-Layout für Fisch-Karten
-
Responsive Design
API getestet mit¶
-
curl http://localhost:3000/- HTML-Seite -
curl http://localhost:3000/api/fish- JSON-Daten
Aussehen¶
so sieht das JSON FIle aus:
2.12 Templating auf Raspi¶
1. Projektübersicht¶
Dieses Projekt ist ein eigenständiger Webserver, der auf Node.js basiert. Er kommt ohne externe Frameworks (wie Express) aus und nutzt nur native Module (http, fs, url).
Der Server erfüllt drei Hauptfunktionen:
-
Templating & Rendering: Er liest HTML-Templates und füllt diese dynamisch mit Daten aus einer JSON-Datei.
-
Routing: Er unterscheidet verschiedene URLs (Overview, Product, API).
-
API-Bereitstellung: Er kann die Rohdaten als JSON zurückgeben.
2. Voraussetzungen & Installation¶
Voraussetzungen¶
-
Node.js: Muss auf dem System (z.B. Raspberry Pi) installiert sein.
-
Dateisystem: Schreib-/Lesezugriff auf das Projektverzeichnis.
Installation & Start¶
-
Kopieren Sie die Projektdateien auf den Server.
-
Navigieren Sie im Terminal in den Projektordner.
-
Starten Sie den Server mit:
Bash
- Der Server ist nun unter
http://127.0.0.1:8001erreichbar.
3. Dateistruktur¶
Damit der Code funktioniert, muss die folgende Ordnerstruktur strikt eingehalten werden, da die Pfade im Code (${__dirname}/...) relativ gesetzt sind:
Plaintext
/projekt-root
│
├── index.js # Die Hauptlogik des Servers (siehe Code unten)
│
├── /dev-data
│ └── data.json # Die Produktdaten (JSON Array)
│
└── /templates
├── template-overview.html # Das Wrapper-HTML für die Übersicht
├── template-card.html # Das HTML-Template für eine einzelne Produktkarte
└── template-product.html # Das HTML-Template für die Detailansicht
4. Technische Funktionsweise¶
A. Server-Initialisierung¶
Der Server wird einmalig gestartet und lädt alle notwendigen Dateien synchron in den Arbeitsspeicher. Dies geschieht vor dem Start des Event-Loops, um Performance-Einbussen bei Requests zu vermeiden.
-
data.json: Wird geparst und als JavaScript-Objekt (dataObj) vorgehalten. -
HTML-Templates: Werden als Strings geladen (
tempOverview,tempCard,tempProduct).
B. Die Template-Engine (replaceTemplate)¶
Eine benutzerdefinierte Funktion ersetzt Platzhalter in den HTML-Strings mit echten Daten.
-
Funktion:
replaceTemplate(temp, product) -
Platzhalter:
-
{%PRODUCTNAME%}→ Name des Produkts -
{%IMAGE%}→ Emoji/Bild -
{%PRICE%}→ Preis -
{%FROM%}→ Herkunftsland -
{%NUTRIENTS%}→ Nährstoffe -
{%QUANTITY%}→ Menge -
{%DESCRIPTION%}→ Beschreibung -
{%ID%}→ ID -
{%NOT_ORGANIC%}→ Fügt CSS-Klasse hinzu, wennorganic: false.
C. Routing (URL-Handling)¶
Der Server prüft req.url und entscheidet anhand einer if/else-Logik, was zurückgegeben wird.
| URL Pfad | HTTP Status | Content-Type | Beschreibung |
|---|---|---|---|
/ oder /overview |
200 | text/html |
Hauptseite: Iteriert über das dataObj, erstellt für jedes Item eine HTML-Card und fügt diese in das Overview-Template ein. |
/product |
200 | text/html |
Detailseite: Aktuell ein Platzhalter ("This is the PRODUCT"). Hier könnte künftig via Query-Parameter (z.B. ?id=0) ein spezifisches Produkt geladen werden. |
/api |
200 | application/json |
API-Endpunkt: Gibt den kompletten Inhalt der data.json als rohes JSON zurück. |
| Sonstiges | 404 | text/html |
Fehlerseite: Gibt "Page not found!" zurück, wenn die Route nicht existiert. |
5. Code-Erklärung (Auszug)¶
Hier ist der Kernmechanismus für das Rendern der Übersicht:
JavaScript
// 1. Wenn der Pfad '/' oder '/overview' ist
if (pathname === '/' || pathname === '/overview') {
res.writeHead(200, {'Content-type': 'text/html'});
// 2. Erstelle für jedes Produkt im JSON ein HTML-Stück basierend auf template-card.html
const cardsHtml = dataObj.map(el => replaceTemplate(tempCard, el)).join('');
// 3. Füge alle Cards in das Haupt-Layout (template-overview.html) ein
const output = tempOverview.replace('{%PRODUCT_CARDS%}', cardsHtml);
// 4. Sende das fertige HTML an den Client
res.end(output);
}







