Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen angezeigt.

Link zu dieser Vergleichsansicht

Beide Seiten der vorigen Revision Vorhergehende Überarbeitung
Nächste Überarbeitung
Vorhergehende Überarbeitung
modul:m290_guko:learningunits:lu16:theorie:a_intro [2025/12/14 20:58] gkochmodul:m290_guko:learningunits:lu16:theorie:a_intro [2026/01/02 22:59] (aktuell) gkoch
Zeile 3: Zeile 3:
 ===== Lernziele ===== ===== Lernziele =====
  
-  * Sie können erklären, wie eine **HTTP-Anfrage** und eine **HTTP-Antwort** funktionieren. ((HTTP = „Hypertext Transfer Protocol“: ein Regelwerk, wie Clients und Server Daten austauschen.))+  * Sie können erklären, wie eine **HTTP-Anfrage** und eine **HTTP-Antwort** funktionieren.((HTTP = „Hypertext Transfer Protocol“: ein Regelwerk, wie Clients und Server Daten austauschen.))
   * Sie können die vier wichtigsten HTTP-Methoden **GET, POST, PUT, DELETE** den CRUD-Operationen zuordnen.   * 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 verstehen, was eine **API** und was eine **Route** in Express ist.
Zeile 23: Zeile 23:
  
 Jetzt übertragen wir diese Idee auf das **Web**: Jetzt übertragen wir diese Idee auf das **Web**:
-Statt direkt SQL zu tippen, schicken wir **HTTP-Anfragen** an einen **Backend-Server** ((Backend-Server = Programm, das Anfragen entgegennimmt und Antworten zurückschickt; oft mit Datenbank-Logik dahinter.)) – bei uns: **Express (Node.js)**.+Statt direkt SQL zu tippen, schicken wir **HTTP-Anfragen** an einen **Backend-Server**((Backend-Server = Programm, das Anfragen entgegennimmt und Antworten zurückschickt; oft mit Datenbank-Logik dahinter.)) – bei uns: **Express (Node.js)**.
 Der Server führt für uns die passenden CRUD-Operationen aus und sendet eine Antwort zurück. Der Server führt für uns die passenden CRUD-Operationen aus und sendet eine Antwort zurück.
  
-Wir bauen zuerst eine **API für Social-Media-Posts**, noch ohne Datenbank – nur mit Daten in einem Javascript-Objekt.+Wir bauen zuerst eine **API für Social-Media-Posts**, noch ohne Datenbank – nur mit Daten in einem Javascript-Array.
 So können wir **HTTP, Routen und Postman** kennenlernen, bevor wir in in der nächsten Unterrichtseinheit MySQL an Express anbinden. So können wir **HTTP, Routen und Postman** kennenlernen, bevor wir in in der nächsten Unterrichtseinheit MySQL an Express anbinden.
 +
 +<WRAP center round tip 70%>
 +Schauen Sie sich das Video zum Unterricht an – Einführung in APIs und Umsetzung von CRUD mit express: [[https://bzzch-my.sharepoint.com/:v:/g/personal/guido_koch_bzz_ch/IQB1YVY2gQOpRLq-MepYlD29AYjnx6mzg2ci28avf1XljGA?nav=eyJyZWZlcnJhbEluZm8iOnsicmVmZXJyYWxBcHAiOiJPbmVEcml2ZUZvckJ1c2luZXNzIiwicmVmZXJyYWxBcHBQbGF0Zm9ybSI6IldlYiIsInJlZmVycmFsTW9kZSI6InZpZXciLCJyZWZlcnJhbFZpZXciOiJNeUZpbGVzTGlua0NvcHkifX0&e=6g0Jem|Einführungs-Video API/CRUD]]
 +</WRAP>
  
 ===== HTTP-Methoden – wie Bestellungen in einem Restaurant ===== ===== HTTP-Methoden – wie Bestellungen in einem Restaurant =====
Zeile 33: Zeile 37:
 Stellen Sie sich das so vor: Stellen Sie sich das so vor:
  
-  * **Client** (Browser oder Postman) = Gast im Restaurant ((Client = Programm, das eine Anfrage sendet.)) +  * **Client** (Browser oder Postman) = Gast im Restaurant((Client = Programm, das eine Anfrage sendet.)) 
-  * **Server** (Express/Node.js) = Küche ((Server = Programm, das Anfragen empfängt und Antworten liefert.))+  * **Server** (Express/Node.js) = Küche((Server = Programm, das Anfragen empfängt und Antworten liefert.))
   * **HTTP-Anfrage** = Bestellung, die der Kellner/die Kellnerin zur Küche bringt   * **HTTP-Anfrage** = Bestellung, die der Kellner/die Kellnerin zur Küche bringt
   * **HTTP-Antwort** = fertiges Gericht, das der Kellner zurückbringt   * **HTTP-Antwort** = fertiges Gericht, das der Kellner zurückbringt
Zeile 41: Zeile 45:
  
   * eine **Methode** (z.B. ''GET'', ''POST'', ''PUT'', ''DELETE''),   * eine **Methode** (z.B. ''GET'', ''POST'', ''PUT'', ''DELETE''),
-  * einen **Pfad**((Pfad = der Teil der URL nach Domain/Port, z.B. ''/food/1''.)) (z.B. ''/api/posts'', ''/api/food/1''), +  * einen **Pfad**((Pfad = der Teil der URL nach Domain/Port, z.B. ''/api/posts'', ''/api/food/1'')), 
-  * optional einen **Body**((Body = „Datenkörper“ der Anfrage, z.B. ein JSON-Objekt.)) (z.B. JSON bei ''POST''/''PUT'')+  * optional einen **Body**((Body = „Datenkörper“ der Anfrage, z.B. ein JSON-Objekt bei ''POST''/''PUT''))
  
 Der Server reagiert auf eine Anfrage, indem er: Der Server reagiert auf eine Anfrage, indem er:
Zeile 50: Zeile 54:
   - genau **eine** Antwort zurückschickt (z.B. JSON oder Text).   - genau **eine** Antwort zurückschickt (z.B. JSON oder Text).
  
-{{:modul:m290_guko:learningunits:lu16:theorie:client_server_http_req_response_kitchen.png?direct&900|}}+{{:modul:m290_guko:learningunits:lu16:theorie:client_server_http_req_response_kitchen.png?direct&1100|}}
  
  
Zeile 109: Zeile 113:
  
 <WRAP center round info 60%> <WRAP center round info 60%>
-Postman können Sie hier downloaden → [[[https://www.postman.com/downloads/|Postman](https://www.postman.com/downloads/|Postman) App]] </WRAP>+Postman können Sie hier downloaden → [[https://www.postman.com/downloads/|Postman downloaden]
 +</WRAP> 
 + 
 +{{:modul:m290_guko:learningunits:lu16:theorie:postman-http-methods.png?direct&600| Screenshot Postman-Benutzeroberfläche mit den HTTP-Requests GET/POST/PUT/DELETE.}} 
 +//Screenshot Postman-Benutzeroberfläche mit den HTTP-Requests GET/POST/PUT/DELETE.//
  
 So können wir die API testen, als wäre schon ein fertiges Frontend vorhanden – nur viel einfacher und kontrollierter. So können wir die API testen, als wäre schon ein fertiges Frontend vorhanden – nur viel einfacher und kontrollierter.
Zeile 115: Zeile 123:
 ===== Beispiel-API: Social-Media-Posts ===== ===== Beispiel-API: Social-Media-Posts =====
  
-Wir verwenden das vereinfachte ''post''-Modell aus Ihrem Social-Media-ERD:+Wir verwenden als Beispiel eine vereinfachte ''post''-Tabelle aus einer Social-Media-Datenbank:
  
   * ''post_id'' (PK, Nummer)((PK = Primary Key / Primärschlüssel: eindeutige ID.))   * ''post_id'' (PK, Nummer)((PK = Primary Key / Primärschlüssel: eindeutige ID.))
Zeile 186: Zeile 194:
 </WRAP> </WRAP>
  
-Wenn Sie diesen Server mit ''npm run dev'' starten, sollten Sie im Browser unter ''[http://localhost:3000/](http://localhost:3000/)'' den Text **„API ist online“** sehen.+Wenn Sie diesen Server mit ''npm run dev'' starten (falls Nodemon -> s. LU15 installiert, sonst ''node index.js''), sollten Sie im Browser unter [[http://localhost:3000/]den Text **„API ist online“** sehen.
  
  
Zeile 203: Zeile 211:
  
 === Test mit Postman oder Browser === === Test mit Postman oder Browser ===
 +{{:modul:m290_guko:learningunits:lu16:theorie:get-request_all_posts.png?direct&900| Screenshot alle Posts abfragen.}}
  
   * Methode: ''GET''   * Methode: ''GET''
Zeile 217: Zeile 226:
 <WRAP box round center 80%> <code javascript> <WRAP box round center 80%> <code javascript>
 // READ – einzelner Post nach ID // READ – einzelner Post nach ID
-app.get('/posts/:id', (req, res) => { +app.get('/api/posts/:id', (req, res) => { 
-  const id = Number(req.params.id);     // Pfad-Parameter (Route-Parameter) holen+  const id = Number(req.params.id);     // Pfad-Parameter (Route-Parameter) holen. :id kommt immer als String -> Number(...) macht eine Zahl daraus
   const post = posts.find(p => p.post_id === id);   const post = posts.find(p => p.post_id === id);
  
Zeile 231: Zeile 240:
  
 === Test mit Postman === === Test mit Postman ===
 +{{:modul:m290_guko:learningunits:lu16:theorie:get-request_single_post.png?direct&900| Screenshot eines einzelnen Posts abfragen.}}
 +
   * Methode: ''GET''   * Methode: ''GET''
     * URL: ''http://localhost:3000/api/posts/1''     * URL: ''http://localhost:3000/api/posts/1''
Zeile 247: Zeile 258:
 Dazu schicken wir einen im Request einen "Body" mit den notwendigen Daten mit (im JSON-Format). Dazu schicken wir einen im Request einen "Body" mit den notwendigen Daten mit (im JSON-Format).
  
-<WRAP box round center 80%>+<WRAP box round center 85%>
 <code javascript> <code javascript>
-// CREATE – neuen Post anlegen +app.post('/api/posts', (req, res) => { 
-app.post('/posts', (req, res) => { +//Daten aus dem Anfrage-Objekt (Request) holen und in Variablen speichern 
-// Holt sich die Daten aus der Request-Anfrage +const user_id = req.body.user_id; 
-  const user_idtitleimage_urldescription = req.body; +const title = req.body.title; 
-// Checken, ob wir auch die notwendigen Daten haben, um einen neuen Post zu speichern+const image_url = req.body.image_url; 
-if (!user_id || !title) { +const description = req.body.description; 
-  return res.status(400).send('Bitte mindestens user_id und title angeben.');+ 
 +// ganz einfache Validierung (Pflichtfelder) - ohne titel oder user_id (wer post erstellt hat) können wir keinen neuen Post erstellen
 +if (!title || !user_id) { 
 +    return res.status(400).send('Please enter a title and a user_id');
 } }
  
-// neue ID bestimmen (hier: max + 1) – wird hier mathematisch gelöst -> später macht das die Datenbank selbst mit AUTO_INCREMENT +// neue post_id berechnen - das wird in Zukunft die Datenbank selbst machen. 
-const newId = posts.length > 0 ? Math.max(...posts.map(p => p.post_id)) 1 : 1;+// Letzte Post-ID aus dem Post-Array herausfinden: 
 +const lastPostId posts[posts.length - 1].post_id
 +const newPostId = lastPostId + 1;
  
 const newPost = { const newPost = {
-  post_id: newId+    post_id: newPostId
-  user_id, +    user_id: user_id, 
-  title, +    title: title, 
-  image_url: image_url || '', +    image_url: image_url || '', 
-  description: description || '', +    description: description || '', 
-  likes: 0+    likes: 0
 }; };
  
 +//neuer Post wird in Post-Array (Liste mit Posts) gespeichert
 posts.push(newPost); posts.push(newPost);
  
 +//Rückmeldung an Client: neuer Post und Status-Code 201 (Created)
 res.status(201).json(newPost); res.status(201).json(newPost);
 +
 +
 }); });
 </code> </code>
 </WRAP> </WRAP>
  
-**Test mit Postman**+==== Erklärung ==== 
 + 
 +Pflichtfelder: ''title'' und ''user_id'' müssen vorhanden sein → sonst ''400 Bad Request''
 + 
 +Neue ID: Wir nehmen die ''post_id'' des letzten Elements im Array und zählen +1. 
 + 
 +Antwort: ''201 Created'' + das neu erstellte Post-Objekt als JSON. 
 + 
 +<WRAP center round info 80%> 
 +Dieser Ansatz mit ''posts[posts.length - 1]'' funktioniert nur, wenn: 
 +  das Array mindestens 1 Element hat, und 
 +  die Posts im Array nach ''post_id'' sortiert sind (letzter Post hat die höchste ID). 
 + 
 +In echten Projekten übernimmt das später die Datenbank (AUTO_INCREMENT). 
 +</WRAP> 
 + 
 +=== Test mit Postman === 
 + 
 +{{:modul:m290_guko:learningunits:lu16:theorie:screenshot_2025-12-18_at_11.26.12.png?direct&900| Screenshot: einen neuen Post hinzufügen.}}
  
   - Methode: ''POST''   - Methode: ''POST''
-  - URL: ''http://localhost:3000/posts''+  - URL: ''http://localhost:3000/api/posts''
   - Tab ''Body'' → ''raw'' → ''JSON'' auswählen   - Tab ''Body'' → ''raw'' → ''JSON'' auswählen
   - Beispiel-Body:   - Beispiel-Body:
Zeile 294: Zeile 332:
 </WRAP> </WRAP>
   - ''Send'' klicken   - ''Send'' klicken
-  * Erwartung: +    * Erwartung: 
-    * Status ''201 Created'' +      * Status ''201 Created'' 
-    * JSON-Objekt mit neuer ''post_id'' (z.B. 3)+      * JSON-Objekt mit neuer ''post_id'' (z.B. 3)
   - Anschliessend ''GET /api/posts'' erneut ausführen → der neue Post sollte in der Liste sein.   - Anschliessend ''GET /api/posts'' erneut ausführen → der neue Post sollte in der Liste sein.
  
Zeile 302: Zeile 340:
 ===== Ausblick ===== ===== Ausblick =====
  
-In dieser Learning Unit haben Sie: +Auf der nächsten Seite sind die HTTP-Methoden PUT und DELETE am gleichen Beispiel (Social-Media-Postsausgeführt. Sie werden diese auch für Ihr Projekt brauchen.
- +
-  * die **HTTP-Methoden** im Kontext von CRUD kennengelernt, +
-  * mit **Postman** einfache Requests an Ihren Express-Server geschickt, +
-  * eine kleine API mit einer lokalen JavaScript-Liste (Array) von ''posts'' erstellt (''GET /api/posts'', ''GET /api/posts/:id'', ''POST /api/posts'').+
  
-In der nächsten Unterrichtseinheit:+In der nächsten Unterrichtseinheit (LU17):
   * ersetzen wir die JavaScript-Liste durch eine **MySQL-Tabelle ''posts''**,   * ersetzen wir die JavaScript-Liste durch eine **MySQL-Tabelle ''posts''**,
-  * ergänzen **Update (PUT)** und **Delete (DELETE)** für vollständiges CRUD, 
   * bauen einfache **Validierung** und **Fehlerbehandlung** (HTTP-Statuscodes) ein,   * bauen einfache **Validierung** und **Fehlerbehandlung** (HTTP-Statuscodes) ein,
   * damit Sie diese Struktur für Ihren eigenen Projekt-Use-Case übernehmen können.   * damit Sie diese Struktur für Ihren eigenen Projekt-Use-Case übernehmen können.
  
  
  • modul/m290_guko/learningunits/lu16/theorie/a_intro.1765742311.txt.gz
  • Zuletzt geändert: 2025/12/14 20:58
  • von gkoch