24 Juni Server Request Verarbeitung

direkt zur Praktikumsaufgabe direkt zu Q&A direkt zur Beispiellösung direkt zum Beispiel-Servercode

URL Modul

Für diese Aufgabe benötigen Sie das URL Modul von Node.js.

Die Aufgabe des URL Moduls ist es, einen URL (Adresse einer Website oder Unterseite + zusätzliche Attribute) in einzelne, les- und verwendbare Teile aufzusplitten. So können u.a. Anfragen von Nutzern die per GET über eine URL an einen Server verschickt werden besser/einfacher weiterverarbeitet werden.

Diese Methode wird oft verwendet, um zum Beispiel eine Suchanfrage in einer Datenbank durchzuführen, oder Inforamtionen an ein Skript zu senden.

Hinweis Node.js Module funktionieren ausschließlich serverseitig. Wenn Sie versuchen Node.js Module in Ihrem Client zu verwenden wird das nicht funktionieren.

Um einen Server zu entwickeln, der Anfragen von Clients verarbeiten kann, brauchen Sie zunächst immer (wie in Aufgabe 8) das Modul http, damit Ihr Server über das HTTP Protokoll erreicht werden kann. Das Modul url hilft Ihnen, den query-String zu extrahieren und zu interpretieren. Beide Module können mit dem Schlüsselwort import geladen und einer Variablen zugewiesen werden, über welche auf die Funktionen und Objekte der jeweiligen Module zugegriffen werden kann. Das Symbol * gibt dabei an, dass sämtliche Funktionalität der Module importiert werden soll, hier könnte auch eine einschränkendere Auswahl getroffen werden, was die allgemeine Performance steigert (da dann nicht alle Teilmodule eines Moduls geladen werden).

Sie benötigen also in Ihrer Serverklasse http und url:

import * as Http from "http";
import * as Url from "url";

export namespace ... {
    Http.createServer(...);
}

Achtung: Wird import verwendet, geht TypeScript davon aus, dass ein eigenes, neues Modul erzeugt werden soll und fordert ggf. das Schlüsselwort export vor namespace, auch wenn es hier eigentlich bedeutungslos ist. Ein Fall ist bekannt bei dem dieses export eine Fehlerhafte js Datei erzeugt hat. Wenn das bei Ihnen auch der Fall ist, melden Sie sich bitte.

Viele der Standardmodule, wie http und url, sind in der Node-Dokumentation beschrieben.

Wo soll ich den Code testen? Zunächst einmal lokal über einen im Terminal gestarteten node server. Fertige Anwendungen dann nochmal auf Ihrem Heroku Server. Hier finden Sie noch einmal den Node-Server-Beispielcode aus der letzten Aufgabe der größtenteils Ihrem Heroku Server entsprechen sollte. Für Beispielcode wie den folgenden, bietet es sich auch immer an, eine eigene Datei anzulegen und so ohne die Umstände des eigentlichen Codes ein wenig herumprobieren zu können.

Import des URL Moduls:

//Diese Zeile bei den Import Statements hinzufügen:
import * as url from "url";

URL Anlegen & Parsen

//Diesen Code innerhalb von einem aktiven Server testen:

let adresse: string = 'http://localhost:8080/default.htm?jahr=2017&monat=february';
//Adresse parsen (umwandeln):
let q = url.parse(adresse, true);

/*Die parse Methode gibt ein Objekt zurück, dass die URL Eigenschaften enthält. So können die fest definierten Eigenschaften einer URL ausgelesen werden:*/
console.log(q.host);
console.log(q.pathname);
console.log(q.search);

/*Die query Eigenschaft gibt ein Ojekt zurück, dass alle query-string Parameter als Eigenschaften besitzt. So können beliebig gesendete Attribute ausgelesen werden:*/
var qdata = q.query;
console.log(qdata.monat);

Eigenschaften des URL Objektes:

Siehe auch nochmal das Diagramm zum URL aus A08

properties of URL

Hinweis Es ist hilfreich auch den folgenden Absatz zu lesen bevor Sie mit dem Testen auf Ihrem Server anfangen.

Handle Request

Hinweis Im Praktikum wurde angesprochen, dass Sie zusätzliche Videoressourcen hilfreich fänden. Folgende Videos von Prof. Jirka Dell’Oro Friedel beschäftigen sich mit dieser Thematik und helfen ein besseres Verständnis für die Serverseitige Verarbeitung von GET Anfragen aufzubauen, sind jedoch in dem bestehenden Kontext einer anderen Aufgabe eingebettet.

Um Anfragen von Nutzern auf einem Server verarbeiten zu können, wurde auf dem Beispiel-Node-Server der letzten Aufgabe folgender Event-Listener installiert:

server.addListener("request", handleRequest);

Dieser Listener ruft für jede eingehende Anfrage eines Nutzers die Funktion handleRequest auf, in der die Anfragen von Nutzern verarbeitet werden. Das Ganze erinnert an die Events die Sie aus dem DOM und den letzten Aufgaben gewöhnt sind.

Die Events die auf einem Node Server ankommen und verarbeitet werden sind jedoch keine DOM-Events! Schließlich ist HTML nicht die Grundlage auf der Serverseite, sondern Node.js. Deswegen folgen die Events in Node.js auch nicht der gewohnten Konvention, dass immer ein Event-Objekt an den Handler übergeben wird.

Der Handler zum Request-Event der Funktion handleRequest erwartet zwei Parameter:

IncomingMessage liefert Informationen zum eingegangenen Request Objekt, zum Beispiel die URL als String. Um daraus bequem den Query-Teil zu extrahieren, bietet das url-Modul hilfreiche Methoden. parse interpretiert die URL und erzeugt daraus ein neues Objekt, dessen Eigenschaft query nun wieder ein assoziatives Array darstellt.

ServerResponse ist ein Objekt, welches Informationen für die Antwort sammelt. Dabei wird, wie bei Kommunikationsprotokollen üblich, diese Information in zwei grundlegende Kategorien aufgeteilt:

Header-Informationen integrieren Sie mit der Methode setHeader(...) des ServerResponse-Objektes. Mit write(...) können Sie ganz einfach Zeichenketten dem Nachrichten-Body anfügen und mit end() die Antwort an den Klienten verschicken lassen. Eine simple Antwort kann man also so zusammenbauen:

function handleRequest(_request: Http.IncomingMessage, _response: Http.ServerResponse): void {
    _response.setHeader("content-type", "text/html; charset=utf-8");
    _response.setHeader("Access-Control-Allow-Origin", "*");
    _response.write("Was geht?");
    _response.end();
}

In diesem Beispiel verschickt der Server lediglich die Antwort mit dem Inhalt "Was geht?". Der Header gibt an, dass die Antwort ein mit utf-8 kodierter Text ist, also z.b. kein Bild, und dass sie von jedem geöffnet werden darf. Auch hier bedeutet der Asterisk * wieder “alles”.

Post Anfrage Serverseitig auslesen (für Bonusaufgabe relevant)

Dieser Abschnitt ist weder Prüfungsrelevant, noch für die normalen Aufgaben -> Er soll für ein verbessertes Verständnis zu serverseitiger POST-Verarbeitung für alle an der Bonusaufgabe Interessierten geben.

Die Methode POST in serverseitigen Anfragen zu verwenden bietet einige Vorteile (es kann trotzdem sinnvoll sein in manchen Fällen GET zu verwenden):

Die Verarbeitung von POST Anfragen in Node.js ist jedoch nicht ganz einfach. Hier sind zwei hilfreiche Ressourcen, um POST-Anfragen serverseitig verabeiten zu können, ansonsten können Sie sich auch direkt den weiter unten stehenden Beispielcode ansehen.

Hinweis Der Vollständigkeit halber soll an dieser Stelle nicht unerwähnt bleiben, dass es neben GET und POST noch weitere, teilweise ähnlich funktionierende Serveranfragen gibt, welche für spezielle Anfragen genutzt werden können: HEAD, PUT, PATCH, DELETE, OPTIONS, etc. Will man z.B. wie oben erwähnt eine Löschanweisung an den Server senden, so könnte man dies über POST machen, noch besser wäre es aber, eine DELETE Anfrage zu verwenden. Diese verschiedenen Arten von Anfragen sind auch als das REST Modell (Representational State Transfer) bekannt.

Beispielcode Clientseite

await fetch(serverAddress, {
  method: "POST",
  headers: {
    "Content-Type": "text/plain",
  },
  body: JSON.stringify(data)
});

Beispielcode Serverseite

if (_request.method == "POST") {
  let body = "";
  _request.on("data", data => {
    body += data;
  });
  _request.on("end", async () => {
    let post: any = JSON.parse(body);
  });
}

Was Sie jetzt im Prinzip können:

Diese Tools sind bereits sehr mächtig und die Grundlage fast jeder App, Webseite u.ä.
Mit diesem Wissen könnten Sie jetzt beginnen, ihre eigenen Webapps zu schreiben.

Typescript Dokumentation

https://www.typescriptlang.org/

A Praktikumsaufgabe

Bei Problemen/Unklarheiten: können Sie ins Praktikum kommen oder per Discord/Mail Fragen stellen.

Aufgabe

Ändern Sie den Servercode dahingehend, dass er statt einfach nur einem URL Bounce die in der URL (im query Teil / über eine GET Anfrage) übergebenen Variablen und Werte zunächst in ein Javascript Objekt / Assoziatives Array umwandelt, bzw diese aus der URL ausließt (s. Url.parse()). Geben Sie nun unter verschiedenen Pfaden die Informationen auf verschidene Weisen zurück:

Verlinken Sie beide Anfragen in einer HTML Seite, entweder über unterschiedliche Buttons bei gleichem Formular oder nutzen Sie zwei Formulare. Nutzen Sie weiterhin fetch() um Ihre Anfragen zu versenden und die Antworten zu empfangen, sonst können Sie die Antworten nicht auf ihrer eigenen Seite darstellen.

Bonusaufgabe

Versuchen Sie, statt über GET über POST eine Anfrage zu verschicken und auszulesen. Legen Sie dazu am besten eine neue HTML Seite an, mit einem ganz simplen “Login” Bereich (Benutzername/Email, Passwort, Button). Verschicken Sie die Daten mit fetch(), lesen sie die Daten auf der Serverseite aus, und schicken Sie diese in einer gut formatierten Form zurück (um überprüfen zu können, dass die Daten auch wirklich angekommen sind). Alternativ können Sie die übergebenen Daten auch mit (vorher festgelegten) “korrekten” Logindaten auf der Serverseite überprüfen und dann stattdessen als Serverantwort das Ergebnis des Loginversuchs zurückgeben.

Achtung!: Beachten Sie die Coding Style Guidelines. Code der diesen Guidelines nicht entpricht wird nicht akzeptiert! Code der W3 Errors oder JS-Errors aufweist wird ebenfalls nicht akzeptiert! Verstöße führen zu einer Ampelstufe 🚦

Abgabetermin: 28.06.2020 um 18:00!

Bitte erstellen Sie nach Fertigstellung einen Link als oberstes Element (unter dem GitHub issues link) in Ihrer Steckbrief.htm, der auf das Ergebnis verweist (bspw. nutzername.github.io/GIS-SoSe-2020/Aufgabe_9). Außerdem einen github.com Link zur Ihrer server.ts Datei.

Achtung!: Eine fehlerhafte Abgabe fürt zu einer 🚦 die im Praktikum verteidigt werden muss. Keine Abgabe zu 2 🚦 von denen nur 1e 🚦 verteidigt werden kann.


?! Q&A Fragen und Antworten

(die Publikation der Zusammenfassung erfolgt nach dem Q&A Termin)

Zusammenfassung von: <GitHub Nutzername>

Erste Frage?

LoremLabore labore cillum mollit pariatur reprehenderit dolor laboris reprehenderit dolor sit officia ea non. Lorem reprehenderit exercitation labore eiusmod aute do nostrud officia aute proident sunt. Labore non tempor aliqua voluptate. Exercitation culpa officia ut aliqua nostrud laborum irure est. Minim eu sunt culpa adipisicing laborum consectetur aliqua quis.

Zweite Frage?

Mollit aliquip veniam sit eiusmod tempor anim ipsum tempor. Aliqua sunt voluptate ea dolor. Nulla est mollit consectetur cupidatat ut cillum ipsum minim. Est ex et nulla laborum fugiat dolore. Aliquip laboris sint exercitation commodo dolor sint mollit qui sunt ipsum fugiat occaecat id enim.