CRUD API mit JSON¶
📌 1. Ziel der Aufgabe¶
In diesem Auftrag ging es darum, auf Grundlage der Theorie eine API zu bauen, welche Daten erstellen, lesen, aktualisieren und löschen (CRUD) kann. Da wir hier nur mit einer JSON-Datei arbeiten, werden die Daten nicht in einer echten Datenbank gespeichert, sondern direkt in einer lokalen Datei (data.json) manipuliert.
Anschliessend wird der Code auf den Raspberry Pi transferiert, damit die API im Schulnetzwerk (KSBLab) erreichbar ist.
✏️ 2. Umsetzung: Der Code¶
Ich habe das Projekt lokal unter projects/node-crud-api erstellt und das Framework Express sowie CORS verwendet.
data.json¶
Diese Datei dient als unser Datenspeicher. Sie enthält initial ein Array von Filmen.
[
{ "id": 1, "title": "Inception", "year": 2010 },
{ "id": 2, "title": "The Matrix", "year": 1999 },
{ "id": 3, "title": "Interstellar", "year": 2014 }
]
server.js¶
In dieser Datei wurde die eigentliche Logik für die REST-Schnittstelle programmiert. Sie stellt die Endpunkte für GET, POST, PUT und DELETE zur Verfügung und aktualisiert unsere data.json-Datei über das fs-Modul.
const express = require('express');
const fs = require('fs');
const path = require('path');
const cors = require('cors');
const app = express();
const PORT = 3000;
const DATA_FILE = path.join(__dirname, 'data.json');
app.use(express.json());
app.use(cors());
// Hilfsfunktionen zum Lesen und Schreiben der Daten
const readData = () => {
try { return JSON.parse(fs.readFileSync(DATA_FILE, 'utf8')); }
catch (err) { return []; }
};
const writeData = (data) => {
fs.writeFileSync(DATA_FILE, JSON.stringify(data, null, 2), 'utf8');
};
// 1. READ ALL (GET)
app.get('/movies', (req, res) => res.json(readData()));
// 2. READ ONE (GET)
app.get('/movies/:id', (req, res) => {
const movie = readData().find(m => m.id === parseInt(req.params.id));
if (!movie) return res.status(404).json({ error: "Movie not found" });
res.json(movie);
});
// 3. CREATE (POST)
app.post('/movies', (req, res) => {
const movies = readData();
const newMovie = {
id: movies.length > 0 ? Math.max(...movies.map(m => m.id)) + 1 : 1,
title: req.body.title,
year: req.body.year
};
if (!newMovie.title || !newMovie.year) return res.status(400).json({ error: "Title and year are required" });
movies.push(newMovie);
writeData(movies);
res.status(201).json(newMovie);
});
// 4. UPDATE (PUT)
app.put('/movies/:id', (req, res) => {
const movies = readData();
const index = movies.findIndex(m => m.id === parseInt(req.params.id));
if (index === -1) return res.status(404).json({ error: "Movie not found" });
movies[index] = { ...movies[index], title: req.body.title || movies[index].title, year: req.body.year || movies[index].year };
writeData(movies);
res.json(movies[index]);
});
// 5. DELETE (DELETE)
app.delete('/movies/:id', (req, res) => {
const movies = readData();
const index = movies.findIndex(m => m.id === parseInt(req.params.id));
if (index === -1) return res.status(404).json({ error: "Movie not found" });
const deleted = movies.splice(index, 1);
writeData(movies);
res.json(deleted[0]);
});
app.listen(PORT, '0.0.0.0', () => console.log(`Server läuft auf Port ${PORT}`));
🚀 3. Deployment auf dem Raspberry Pi¶
Die Dateien müssen nun auf den Raspberry Pi kopiert werden, um dort im Schulnetz erreichbar zu sein.
Schritt 1: Transfer via SCP¶
# Wechsel in das entsprechende Verzeichnis im PowerShell / Terminal
cd "C:\Users\joelm\OneDrive - Kt. SG BLD\2. Schuljahr\1. Semester\Module\V293\meine-dokumentation"
# Kopieren der Dateien auf den Pi (direkt in deinen Ordner: /home/m295/class/joel)
# WICHTIG: In Windows PowerShell funktioniert das * Zeichen oft nicht beim SCP Befehl, deswegen kopieren wir die Dateien einzeln:
scp projects/node-crud-api/server.js projects/node-crud-api/package.json projects/node-crud-api/data.json m295@10.27.160.16:/home/m295/class/joel/
Schritt 2: Server starten¶
Via SSH auf den Pi verbinden, in den Ordner wechseln, Dependencies installieren und Server starten:
ssh m295@10.27.160.16
cd /home/m295/class/joel
npm install
# Anschliessend den Docker-Container neu laden:
./stop.sh
./start.sh
(Hinweis: Falls alte Node-Prozesse den Port blockieren, kannst du sie mit pkill -u root node beenden. Der Docker-Container selbst kann mit ./stop.sh und ./start.sh im Verzeichnis /home/m295/class/joel/ neu geladen werden.)
🌐 4. Zugriff durch andere Lernende¶
Wenn der Server im Docker-Container auf dem Pi (intern Port 3000) läuft, ist er von aussen über den gemappten externen Port 4011 erreichbar. Ein Test-Aufruf sieht so aus:
Test-Link (GET alle Filme): http://10.27.160.16:4011/movies
Zusätzlich können über HTTP-Clients wie Postman, Insomnia oder via cURL im PowerShell/Terminal auch die POST, PUT und DELETE Anfragen unter dieser URL (mit Port 4011) getestet werden.
Anforderungs-Checkliste¶
- CRUD-Schnittstelle ohne echte DB erstellt
- Datenmanipulation per JSON umgesetzt
- Code für das Deployment und den Start auf dem Raspberry PI dokumentiert
- Dokumentation in MkDocs eingefügt