Zum Inhalt springen

Aufgabe 05-1a - API-Konsument

Zu Zen-Modus wechseln
  • Du liest HTTP-Verkehr im Netzwerk-Tab und stellst Anfragen von Hand.
  • Du konsumierst eine fremde API anhand ihrer Dokumentation mit fetch und typisierst den Datenvertrag.
  • Du behandelst die drei Fehlerklassen an der Netzwerkgrenze benutzergerecht.
  • Du fragst mehrere Eingaben gleichzeitig ab und sicherst jede Anfrage mit einem Timeout ab.

Eine Wetter-App, die “undefined °C” anzeigt oder bei einem Tippfehler mit einem Stacktrace abstürzt, löscht man schnell wieder. Du baust es besser: ein kleines Programm, das zum ersten Mal mit einem fremden Server spricht und mit allem zurechtkommt, was dabei schiefgehen kann (siehe Kapitel HTTP und Schnittstellen, Einheit 5.1 für die Stufe Wesentlich_überwiegend, Einheit 5.2 ab Wesentlich_vollständig).

Du arbeitest mit einer öffentlichen API ohne Anmeldung, die im Unterricht festgelegt wird. Drei bewährte Beispiele:

  • Open-Meteo (https://open-meteo.com): Wetterdaten für beliebige Koordinaten, ein eigener Dienst sucht die Koordinaten zu einem Ortsnamen.
  • REST Countries (https://restcountries.com): Länderdaten wie Hauptstadt, Einwohnerzahl und Sprachen.
  • PokéAPI (https://pokeapi.co): umfangreiche Daten zu Pokémon, gut zum Üben verschachtelter JSON-Strukturen.

Projektordner anlegen siehe https://qiz.at/projektordner

  • Lies vorher kurz https://qiz.at/assignmentsabgabe durch.
  • Nur vollständige Abgaben (siehe https://qiz.at/rules) können positiv bewertet werden.
  • Abgabe- und Testdetails siehe https://qiz.at/assignmentsabgabe
  • Die Übung liegt als Unterordner uebung-05-1a in deinem Jahres-Repository SJ26_27_4AHITM_SEW_<Benutzername>_exercises, eingerichtet wie in Aufgabe 03-2a. Notizen stehen in notes.md, der Code in consumer.ts. Du arbeitest allein.
  • Öffne eine beliebige Webseite mit offenem Netzwerk-Tab (F12). Finde einen GET-Request, einen mit Status 200 und einen mit 3xx oder 4xx.
  • Notiere für einen Request: Methode, vollständige URL, drei Request-Header, Statuscode und Content-Type der Antwort.
  • Erklär in zwei Sätzen, was 404 von 500 unterscheidet und wer jeweils etwas ändern muss.
  • Lies die Dokumentation der vereinbarten API und stell zwei erfolgreiche Anfragen von Hand (Browser-Adresszeile oder curl). Notiere die Befehle.
  • Halte den benötigten Ausschnitt der Antwort als TypeScript-Interface fest, nur mit den Feldern, die dein Programm verwenden wird.

Tipp: In Windows PowerShell 5.1 tippst du curl.exe statt curl. URLs mit ? und & schreibst du in Anführungszeichen, sonst versteht die Shell sie falsch. Gute API-Dokumentation zeigt zu jedem Endpunkt eine Beispielanfrage und eine Beispielantwort; fang damit an.

Vollständig, wenn:

  • die Notizen zum Request alle fünf Angaben enthalten und die Statuscodes richtig eingeordnet sind.
  • zwei Anfragen von Hand mit Befehl und sichtbarer Antwort dokumentiert sind.
  • das Interface nur die verwendeten Felder enthält, optionale als optional markiert, und fehlerfrei kompiliert.

Wie unter Allgemein.

Für alle, die in der Einheit mit den Schritten oben fertig sind bzw. optional (= freiwillig), wenn du in der Einheit nicht fertig wirst.

Erweitere (siehe Erweitern in https://qiz.at/rules) den vollständigen Teil der vorherigen Stufe dieser Datei (ändere oder lösche nur, was für diese Aufgabe unbedingt notwendig ist):

  • Schreib fetchJson<T>(url: string): Promise<T>: einen Wrapper, der bei !response.ok eine aussagekräftige Exception wirft (Statuscode und URL in der Meldung) und sonst das geparste JSON liefert.
  • Bau darauf ein kleines Konsolenprogramm: Es nimmt eine Eingabe, etwa einen Ortsnamen, fragt die API ab und zeigt ein aufbereitetes Ergebnis (“Villach: 18 °C, bewölkt”).
  • Nutze beim Zugriff auf optionale Felder ?. und ??; kein Absturz, wenn die API ein Feld weglässt.

Tipp: Die Eingabe kann für den Anfang eine Konstante im Code sein; wer will, liest sie mit process.argv[2] von der Kommandozeile. Ortsnamen gehören mit encodeURIComponent in die URL, sonst scheitern Namen mit Leerzeichen oder Umlauten.

Vollständig, wenn:

  • fetchJson generisch typisiert ist und bei einem Fehlerstatus mit Status und URL in der Meldung wirft.
  • das Programm für eine gültige Eingabe ein lesbares Ergebnis zeigt.
  • ein fehlendes optionales Feld keinen Absturz und kein undefined in der Ausgabe erzeugt.

Wie unter Allgemein.

Für alle, die in der Einheit mit den Schritten oben fertig sind bzw. optional (= freiwillig), wenn du in der Einheit nicht fertig wirst.

Erweitere (siehe Erweitern in https://qiz.at/rules) den vollständigen Teil der vorherigen Stufe dieser Datei (ändere oder lösche nur, was für diese Aufgabe unbedingt notwendig ist):

  • Chaostest: Dein Programm meldet drei Störungen unterscheidbar und verständlich, ohne Stacktrace: (a) falsche Domain (Netzwerkfehler, fetch wirft), (b) existierende Domain mit unbekanntem Endpunkt (404), (c) unsinnige Eingabe (leeres Ergebnis oder Fehlermeldung der API).
  • Führ ein Protokoll: Störung, beobachtete Meldung, bestanden ja/nein.

Tipp: Eine eigene Fehlerklasse mit dem Statuscode als Eigenschaft macht die Unterscheidung im catch einfach (error instanceof ApiError). Was nicht von fetchJson stammt, ist meist ein Netzwerkfehler.

Vollständig, wenn:

  • alle drei Störungen zu unterscheidbaren, verständlichen Meldungen führen.
  • das Protokoll alle drei Fälle mit beobachteter Meldung enthält.

Wie unter Allgemein.

Für alle, die in der Einheit mit den Schritten oben fertig sind bzw. optional (= freiwillig), wenn du in der Einheit nicht fertig wirst.

Erweitere (siehe Erweitern in https://qiz.at/rules) den vollständigen Teil der vorherigen Stufe dieser Datei (ändere oder lösche nur, was für diese Aufgabe unbedingt notwendig ist):

  • Erweitere das Programm auf drei Eingaben auf einmal, gleichzeitig abgefragt, mit Sammelbericht auch bei Teilausfällen. Begründe die Wahl des Kombinators.
  • Ergänze ein Timeout von zwei Sekunden pro Anfrage über AbortController und das signal von fetch.
  • Beurteile in drei Sätzen: Welche Störungen kann dein Programm sinnvoll selbst behandeln, welche kann es nur sauber melden, und woran machst du den Unterschied fest?

Tipp: Den passenden Kombinator kennst du aus Aufgabe 04-1a. Räum den Timer im finally auf, sonst hält er das Programm auch nach einer schnellen Antwort noch zwei Sekunden am Leben.

Vollständig, wenn:

  • drei Eingaben gleichzeitig abgefragt werden und ein Teilausfall den Bericht nicht verhindert.
  • eine Anfrage, die länger als zwei Sekunden dauert, abgebrochen und verständlich gemeldet wird.
  • die Beurteilung zwischen Behandeln und Melden begründet unterscheidet.

Wie unter Allgemein.

  1. Aus welchen Bestandteilen besteht ein HTTP-Request, aus welchen die Response?
  2. Warum ist if (!response.ok) in jedem fetch-Aufruf Pflicht?
  3. Welche drei Fehlerklassen hat jede Netzwerkgrenze?
  4. Was gehört in ein Datenvertrags-Interface für eine fremde API, und was bewusst nicht?
  5. Was bedeutet 429 Too Many Requests, und welche Disziplin aus Kapitel 4 verhindert es?

Durchschnittlich bis Wesentlich_vollständig: ca. 100 min

  • Oliver Maurhart (MAO)
  • Michael Gabriel (GAM)

CC-BY-SA

https://qiz.at/rules