Zum Inhalt

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}`);
});

Bildschirmfoto 2026-02-10 um 15.05.19.png

Bildschirmfoto 2026-02-10 um 15.06.07.png

Bildschirmfoto 2026-02-10 um 15.06.34.png

Bildschirmfoto 2026-02-10 um 15.07.53.png

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 handyModelle liegt 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

Bildschirmfoto 2026-02-10 um 15.34.48.png

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

npm install

Starten

node app.js

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

{

"id": 1,

"name": "Räucherlachs",

"price": "€12.99 pro Kg",

"origin": "Norwegen"

}

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

Bildschirmfoto 2026-02-10 um 17.50.42.png

so sieht das JSON FIle aus:

Bildschirmfoto 2026-02-10 um 17.51.28.png

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:

  1. Templating & Rendering: Er liest HTML-Templates und füllt diese dynamisch mit Daten aus einer JSON-Datei.

  2. Routing: Er unterscheidet verschiedene URLs (Overview, Product, API).

  3. 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

  1. Kopieren Sie die Projektdateien auf den Server.

  2. Navigieren Sie im Terminal in den Projektordner.

  3. Starten Sie den Server mit:

Bash

node index.js
  1. Der Server ist nun unter http://127.0.0.1:8001 erreichbar.

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, wenn organic: 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);
}

6. Bilder auf Server

Bildschirmfoto 2026-02-17 um 15.46.02.png