====== LU16 – HTTP, CRUD & Postman ====== ===== Learning Objectives ===== * Sie können grob erklären, wie eine **HTTP-Anfrage** und eine **HTTP-Antwort** funktionieren. * Sie können die vier wichtigsten HTTP-Methoden **GET, POST, PUT, DELETE** den CRUD-Operationen zuordnen. * Sie verstehen, was eine **API** und was eine **Route** in Express ist. * Sie können mit **Postman** einfache Requests an Ihren Express-Server schicken. * Sie können erste **CRUD-Routen** für ''posts'' mit einer einfachen In-Memory-Liste erstellen (ohne Datenbank). ===== Von SQL-CRUD zu Web-CRUD ===== Bisher im Modul M290: * Sie haben in **MySQL** Tabellen erstellt, Daten importiert und Abfragen geschrieben. * Sie kennen **CRUD**: - **C**reate → ''INSERT'' - **R**ead → ''SELECT'' - **U**pdate → ''UPDATE'' - **D**elete → ''DELETE'' Jetzt übertragen wir diese Idee auf das **Web**: Statt direkt SQL zu tippen, schicken wir **HTTP-Anfragen** an einen **Backend-Server (Express)**, und dieser Server führt für uns die passenden CRUD-Operationen aus. Wir bauen zuerst eine **Mini-API für Social-Media-Posts**, noch ohne Datenbank – nur mit Daten im Speicher. So können Sie in Ruhe **HTTP, Routen und Postman** verstehen, bevor wir in LU17 MySQL anschliessen. ===== HTTP in einfachen Worten – Restaurant-Vergleich ===== Stellen Sie sich das so vor: * **Client** (Browser oder Postman) = Gast im Restaurant * **Server** (Express/Node.js) = Küche * **HTTP-Anfrage** = Bestellung, die der Kellner zur Küche bringt * **HTTP-Antwort** = fertiges Gericht, das der Kellner zurückbringt Jede HTTP-Anfrage hat unter anderem: * eine **Methode** (z.B. ''GET'', ''POST'', ''PUT'', ''DELETE''), * einen **Pfad** (z.B. ''/posts'', ''/posts/3''), * optional einen **Body** (z.B. JSON-Daten bei ''POST''/''PUT''). Der Server reagiert auf eine Anfrage, indem er: 1. eine passende **Route** findet (z.B. ''app.get('/posts', ...)''), 2. etwas ausführt (z.B. Daten holen oder speichern), 3. genau **eine** Antwort zurückschickt (z.B. JSON oder Text). ===== CRUD & HTTP-Methoden ===== CRUD-Operationen werden bei Web-APIs typischerweise folgenden HTTP-Methoden zugeordnet: ^ CRUD ^ HTTP-Methode ^ Typisches Beispiel einer Route ^ | Create | **POST** | ''POST /posts'' → Neuer Post wird angelegt | | Read | **GET** | ''GET /posts'' → Alle Posts anzeigen; ''GET /posts/5'' → Post mit ID 5 anzeigen | | Update | **PUT** | ''PUT /posts/5'' → Post mit ID 5 vollständig aktualisieren | | Delete | **DELETE** | ''DELETE /posts/5'' → Post mit ID 5 löschen | Später werden Sie für Ihre eigenen Use Cases (Reisen, Filme, Bücher, …) genau solche Routen definieren, z.B. ''GET /trips'', ''POST /books'', usw. ===== Postman – unser „Frontend-Ersatz“ ===== Im Modul M290 programmieren wir **kein eigenes Browser-Frontend**. Stattdessen benutzen wir **Postman** als Client: * Postman kann ''GET'', ''POST'', ''PUT'', ''DELETE''-Requests an Ihre API senden. * Sie sehen direkt: - den **Statuscode** (z.B. 200, 201, 400, 404, 500), - die **Response-Header**, - den **Response-Body** (Text oder JSON). * Sie können im Body bequem JSON eingeben (z.B. neuen ''post'' anlegen). So können Sie Ihre API testen, als wäre schon ein fertiges Frontend vorhanden – nur viel einfacher und kontrollierter. ===== Beispiel-API: Social-Media-Posts (ohne Datenbank) ===== Wir verwenden das vereinfachte ''post''-Modell aus Ihrem Social-Media-ERD: * ''post_id'' (PK, Nummer) * ''user_id'' (FK zum User – hier nur als Zahl) * ''title'' (Titel des Posts) * ''image_url'' (Bild-URL) * ''description'' (Beschreibungstext) * ''likes'' (Anzahl Likes) Ziel von LU16: * Einen kleinen Express-Server mit einer **In-Memory-Liste** von Posts erstellen. * Erste Routen: - ''GET /posts'' → alle Posts - ''GET /posts/:id'' → ein Post - ''POST /posts'' → neuen Post hinzufügen ==== 1. Start: Minimale Express-API für Posts ==== Wir bauen auf Ihrem bekannten Grundserver aus LU15 auf. import express from 'express'; const app = express(); const port = 3000; // Middleware: JSON-Body einlesen (für POST/PUT) app.use(express.json()); // "Fake-Datenbank" im Arbeitsspeicher let posts = [ { post_id: 1, user_id: 1, title: 'Erster Post', image_url: 'https://example.com/image1.jpg', description: 'Hallo Welt aus unserem Backend!', likes: 10 }, { post_id: 2, user_id: 2, title: 'Zweiter Post', image_url: 'https://example.com/image2.jpg', description: 'Noch ein Test-Post.', likes: 5 } ]; // TEST-Route app.get('/', (req, res) => { res.send('API ist online'); }); app.listen(port, () => { console.log(`API läuft auf http://localhost:${port}`); }); Wenn Sie diesen Server mit ''npm run dev'' starten, sollten Sie im Browser unter ''http://localhost:3000/'' den Text **„API ist online“** sehen. ==== 2. READ – Alle Posts abfragen: ''GET /posts'' ==== Jetzt fügen wir eine Route hinzu, die alle Posts zurückliefert: // READ – alle Posts app.get('/posts', (req, res) => { res.status(200).json(posts); }); **Test mit Postman oder Browser** * Methode: ''GET'' * URL: ''http://localhost:3000/posts'' * Erwartung: - Status ''200 OK'' - JSON-Array mit den zwei Beispiel-Posts ==== 3. READ – Einzelnen Post nach ID abfragen: ''GET /posts/:id'' ==== Wir möchten einen einzelnen Post anhand der ''post_id'' holen. // READ – einzelner Post nach ID app.get('/posts/:id', (req, res) => { const id = Number(req.params.id); // Pfad-Parameter holen und in Zahl umwandeln const post = posts.find(p => p.post_id === id); if (!post) { return res.status(404).send('Post nicht gefunden'); } res.status(200).json(post); }); **Test mit Postman** * Methode: ''GET'' * URL: ''http://localhost:3000/posts/1'' * Erwartung: - Status ''200 OK'' - JSON-Objekt mit ''post_id: 1'' * URL: ''http://localhost:3000/posts/999'' - Status ''404 Not Found'' - Body: ''Post nicht gefunden'' ==== 4. CREATE – Neuen Post anlegen: ''POST /posts'' ==== Nun soll ein neuer Post erstellt werden. Dazu schicken wir einen JSON-Body mit den notwendigen Feldern. // CREATE – neuen Post anlegen app.post('/posts', (req, res) => { const { user_id, title, image_url, description } = req.body; // ganz einfache Validierung if (!user_id || !title) { return res.status(400).send('Bitte mindestens user_id und title angeben.'); } // neue ID bestimmen (hier: max + 1) const newId = posts.length > 0 ? Math.max(...posts.map(p => p.post_id)) + 1 : 1; const newPost = { post_id: newId, user_id, title, image_url: image_url || '', description: description || '', likes: 0 }; posts.push(newPost); res.status(201).json(newPost); }); **Test mit Postman** 1. Methode: ''POST'' 2. URL: ''http://localhost:3000/posts'' 3. Tab ''Body'' → ''raw'' → ''JSON'' auswählen 4. Beispiel-Body: { "user_id": 3, "title": "Mein erster echter Post", "image_url": "https://example.com/image3.jpg", "description": "Gerade mit Postman erstellt!" } 5. ''Send'' klicken * Erwartung: - Status ''201 Created'' - JSON-Objekt mit neuer ''post_id'' (z.B. 3) 6. Anschliessend ''GET /posts'' erneut ausführen → der neue Post sollte in der Liste sein. ===== Ausblick auf LU17 ===== In dieser Learning Unit haben Sie: * die **HTTP-Methoden** im Kontext von CRUD kennengelernt, * mit **Postman** einfache Requests an Ihren Express-Server geschickt, * eine kleine API mit einer In-Memory-Liste von ''posts'' erstellt (''GET /posts'', ''GET /posts/:id'', ''POST /posts''). In **LU17**: * ersetzen wir die In-Memory-Liste durch eine **echte MySQL-Tabelle ''post''**, * ergänzen **Update (PUT)** und **Delete (DELETE)** für vollständiges CRUD, * bauen einfache **Validierung** und **Fehlerbehandlung** (HTTP-Statuscodes) ein, * damit Sie diese Struktur für Ihren eigenen Projekt-Use-Case übernehmen können. ==== Vocabulary ==== ^ English ^ Deutsch ^ | request | Anfrage | | response | Antwort | | endpoint / route | Endpunkt / Route | | status code | Statuscode | | body (request body) | (Request-)Body, Datenkörper | | to validate | validieren, überprüfen |