Wir haben bereits eine Wortkartei-App mit OO gebaut:

  • eine Klasse, die eine einzelne Übersetzung beschreibt, zum Beispiel Word.
  • eine Klasse, die eine Sammlung von Words bereitstellt, zum Beispiel Unit.
  • eine Klasse, um den Lernerfolg zu erfassen, z.B. Stats.

Ein Konsolen-Programm liest Daten im CSV-Format ein, erfragt Übersetzungen, und speichert die Resultate wieder ab.

Das ist schön und gut, aber wir möchten ja eine App bauen, die nicht nur für uns selbst zugänglich ist, sondern für jedermann über das Internet verwendet werden kann:

Das HyperText Transfer Protocol wird benützt, um Webseiten (und CSS und JS und Bilder…) zwischen einem Client (z.B. dem Browser) und einem Server auszutauschen. Wir schauen uns an, was passiert, wenn wir auf eine Webseite zugreifen. In den DevTools zeigen wir den Network Tab, wo die Folge der HTTP Requests angezeigt werden.

Ressourcen & URLs

HTTP dient dazu, Ressourcen über das Internet zu übertragen. Ressourcen sind zum Beispiel Dateien, die vom Server zum Client übertragen werden:

  • HTML (HyperText Meta Language): die Sprache, um Webseiten zu schreiben. Im wesentlichen Text, der mit <b>Tags</b> versehen wird, um <i>Struktur</i> darzustellen.
  • CSS (Cascading Style Sheets): Formatierungsregeln, um HTML ansprechend darzustellen.
  • JS (JavaScript): Programmcode, der vom Browser ausgeführt wird.
  • PNG & JPG: Bilddateien

Damit erstellen wir das Grundgerüst für unsere Web-App.

Mehr zu diesen Sprachen im Grundlagenfach Informatik 2.

Statt ganzen Dateien können wir aber als Ressourcen auch Daten übertragen, die „on-the-fly“ auf dem Server erzeugt werden. Beispielsweise können wir C#-Code schreiben, um dynamisch ein zufälliges Wort zur Übersetzung zu liefern.

Jede Ressource wird durch einen Uniform Resource Locator (URL) identifiziert. Die URL ist genau das, was in der Adresszeile des Browsers angezeigt wird. Beispiel für URLs in unserer App:

  • http://localhost:1234/website/index.html - die URL für die HTML-Datei.
  • http://localhost:1234/random - die URL, um ein zufälliges Wort zurückzugeben.

Die URL besteht aus:

  • dem Protokoll: http
  • dem Servernamen und optional einem Port: localhost:1234
  • dem Pfad der Ressource auf dem Server: /website/index.html

Request & Response

Jeder Request verlangt eine bestimmte Ressource mit einer bestimmten Method. Die Method beschreibt die Aktion, typischerweise GET, um eine Ressource zu holen, POST um eine Ressource auf dem Server zu verändern.

Der Request enthält eine Anzahl zusätzlicher Informationen als Headers, insbesondere:

  • If-modified-since: <timestamp>
    • Das Dokument nur zurückgeben, wenn es seit dem Zeitstempel verändert wurde.
    • Sonst antwortet der Server mit einem 304, um Caching zu ermöglichen, so dass nicht immer die ganze Seite übertragen werden muss.
  • Referer: Welche Seite oder Host hat die Anfrage ausgelöst.
    • wird dazu verwendet, das Surfverhalten von Nutzern zu analysieren
  • User-agent:
    • Enthält Informationen zum Browser des Benutzers.
    • Kann zum Beispiel verwendet werden, um ein Mobiltelefon von einem Desktop-Computer zu unterscheiden.

Der Server antwortet mit einem Response Code und zusätzlichen Informationen, zum Beispiel der angeforderten Ressource. Die wichtigsten Codes sind:

  • 200 (OK): Anfrage ist erfolgreich, die Ressource ist im Response Body enthalten.
  • 304 (UNMODIFIED): Anfrage ist in Ordnung, die Ressource ist unverändert und wird darum nicht zurückgegeben (Nur bei GET, nicht bei POST)
  • 404 (NOT FOUND): Die Ressource wurde nicht gefunden.
  • 500 (SERVER ERROR): Ein Fehler auf dem Server ist passiert.

Cookies

Zusätzlich kann der Server noch Cookies mitliefern, die der Browser speichert und beim nächsten Request an den gleichen Server im Request mitgeliefert werden.

Session-Cookies leben nur, solange das Browser-Fenster offen ist und sind in der Regel unproblematisch. Long-lived cookies können über Jahre installiert bleiben und bei jedem Seitenbesuch erneuert werden. Sie werden zum Teil benützt, um Benutzer über Webseiten hinweg zu verfolgen, und haben zur ganzen Diskussion um Cookies geführt. Um den Benutzer zu identifizieren (zum Beispiel nach erfolgreichem Login) sind Session-Cookies aber unverzichtbar.

Wir verwenden das Grapevine-Framework, um einen einfachen Webserver zu bauen.

Wir fügen das Framework zu unserem Projekt hinzu:

dotnet add package Grapevine --version 5.0.0-rc.10

Dann starten wir einen Server, der Dateien im Ordner website als Dateien überträgt:

server.cs
using Grapevine;
 
// Start the standalone REST server.
using (var server = RestServerBuilder.UseDefaults().Build()) {
    // We want to serve static content (HTML, CSS, JS that is not modified
    // but transferred to the client as is from the "website" folder.
    string staticPath = Path.Combine(Directory.GetCurrentDirectory(), "website");
    server.ContentFolders.Add(staticPath);
    server.UseContentFolders();
 
    // Start the server.
    // The server will scan the entire assembly for RestResource annotations
    // and add them to the served prefixes.
    server.Start();
 
    // Block the thread to keep the process from terminating.
    Console.WriteLine("Press enter to stop the server");
    Console.ReadLine();
}

Wenn wir ihn starten mit dotnet run, können wir alle Dateien im website Ordner übertragen.

Aufgabe: Statische Webseite

  • Binde grapevine in deinen Code ein.
  • Füge einen Ordern website in den Projekt ein und füge eine leere Website als Datei website/index.html hinzu.
  • Starte den Server mit dotnet run und rufe http://localhost:1234/index.html auf - die Datei sollte im Browser angezeigt werden.

REST

Um dynamische Daten zu übertragen, müssen wir noch Server-Code schreiben, der weiss, wie er auf bestimmte URLs reagieren soll. Dazu verwenden wir Annotations, die vom Server automatisch erkannt werden:

rest.cs
using voci;
using System.Net;
using Microsoft.Extensions.DependencyInjection;
using Grapevine;
 
/**
 * A resource is something that matches a web address (URL). 
 * The UnitResource contains routes for serving words.
 *
 * ServiceLifetime.Singleton tells the server to keep the same
 * resource around for the entire time the application runs, instead
 * of creating a fresh resource for every request.
 */
[RestResource]
[ResourceLifetime(ServiceLifetime.Singleton)]
public class UnitResource
{
    private Unit unit = UnitReader.readFromCsv("data/de_en.csv");
 
    // RestRoute tells the server to connect incoming requests of the given
    // pattern to this method.
    [RestRoute("Get", "/random")]
    public async Task Random(IHttpContext context)
    {
        Word entry = unit.PickOne();
        await context.Response.SendResponseAsync($"{entry.Origin}");
    }
}

Wir können auch auf dynamische Parameter im URL-Pfad zugreifen:

rest.cs
    [RestRoute("Get", "/submit/{word}/{translation}")]
    public async Task Word(IHttpContext context)
    {
        // URL parameters are available from the context.
        // Since URLs are encoded, we need to decode them in order to properly
        // handle umlauts and spaces and accents.
        string word = WebUtility.UrlDecode(context.Request.PathParameters["word"]);
        string translation = WebUtility.UrlDecode(context.Request.PathParameters["translation"]);
        Word entry = unit.Find(word);
        bool correct = translation.Equals(entry.Translation);
        unit.Record(entry, correct);
        string message = correct ? $"Correct, the answer is {entry.Translation}!" : $"Incorrect! The correct answer is {entry.Translation}";
        await context.Response.SendResponseAsync(message);
    }
  • Baue Grapevine in dein Programm ein und starte einen Webserver.
    • Teste, ob du den Webserver auf http://localhost:1234 erreichts, indem du die Adresse mit dem Browser öffnest.
    • Baue eine Resource ein, ähnlich wie der Beispielcode oben.
    • Gib einen String im HTTP-Request zurück, z.B. "Hello World"
    • Teste sie mit einem Browser aus.
  • Verwende die Entwicklertools (Alt+Ctrl+I / Cmd+Alt+I), um die Requests und Responses anzusehen.
  • Baue eine Route ein (mit der RestRoute Annotation), die ein zufälliges Wort zur Übersetzung zurückgibt.
  • Baue eine einfache Webseite mit HTML & CSS (more details coming)
  • Verknüpfen von Website und dynamischen Inhalten mit Javascript (TBD)
  • ef_informatik/voci_rest.1653373444.txt.gz
  • Zuletzt geändert: 2022-05-24 06:24
  • von hof