1
0
Fork 0
mirror of https://github.com/TheTaz25/denis.ergin.git synced 2025-07-06 11:48:49 +00:00

feat(slides): wip: Backend-Development

This commit is contained in:
Denis Ergin 2025-02-23 18:40:07 +01:00
parent b56e5dc71d
commit 2218a4db48
7 changed files with 323 additions and 1 deletions

View file

@ -6,5 +6,6 @@
"landing",
"build",
"knowledge-base"
]
],
"typescript.tsdk": "node_modules/typescript/lib"
}

View file

@ -0,0 +1,19 @@
<section>
<section>
<h2>Bessere Webserver mit Fastify</h2>
</section>
<section>
<p>Wir haben in den vorangegenangenen Folien gesehen, wie man einen einfachen Web-Server in NodeJS erstellt.</p>
<p>Moderne Features wie Routing-Logik, Logging, Error-Handling und weitere Features waren nicht mit inbegriffen.</p>
<p>Wir wollen das auch nicht selber schreiben. Hierfür wurde das Rad unzählige male für verschiedenste Problemstellungen neu Entwickelt.</p>
</section>
<section>
<p>Eines dieser vielen Räder schauen wir uns genauer an: Fastify</p>
<p>Fastify ist ein modernes Web-Framework um seinen eigenen Web-Server zu bauen. Es bietet die vorher erwähnten Features und hat darüber hinaus noch mehr zu bieten.</p>
<p>Das wichtigste aus meiner Sicht: Eine solide TypeScript Unterstützung.</p>
</section>
</section>

View file

@ -0,0 +1,13 @@
---
import Title from "./title.astro";
import Plain from "./plain.astro";
import Protocols from './protocols.astro';
import Fastify from "./fastify.astro";
---
<div class="slides">
<Title />
<Plain />
<Protocols />
<Fastify />
</div>

View file

@ -0,0 +1,116 @@
<section>
<section>
<p>Wir beginnen nun damit, einen (bzw. mehrere) Server mit JavaScript auf NodeJS zu implementieren.</p>
<p>NodeJS ist im Vergleich zur Umgebung im Browser anders aufgebaut. Wir haben zum Beispiel kein <code>document</code> auf das wir beispielsweise zugreifen könnten.</p>
</section>
<section>
<p>Dafür haben wir nun Zugriff auf die gesamte NodeJS-API um mit dem Betriebssystem zu interagieren (Dateizugriffe, Netzwerk-Ports öffnen und so weiter).</p>
<p>Wenn Node installiert ist, können wir eine JavaScript Datei mit <code>node name-der-datei.js</code> ausführen.</p>
</section>
<section>
<p>Legen wir nun eine erste Datei <code>server.js</code> an:</p>
<pre class="js"><code data-trim data-line-numbers="1|3-5" is:raw>
const http = require("node:http");
http.createServer(function(req, res) {
res.end();
}).listen(8080);
console.log("Server listening on port 8080!");
</code></pre>
</section>
<section>
<p>Funktionalitäten in NodeJS sind in <strong>Modulen</strong> geschrieben. Wir können auf diese jederzeit zugreifen.</p>
<p>Je nachdem wie das Projekt aufgebaut ist, müssen wir auf diese Module anders zugreifen.</p>
<p>In nicht näher konfigurierten Projekten müssen wir mittels <code>require("modulname")</code> auf diese Sachen zurgeifen.</p>
</section>
<section>
<p>In moderneren Projekten, benutzen wir die neuere Modul-Syntax die mittels den keywords <code>import something from 'modul';</code> aufgerufen wird.</p>
<p>Das aktuelle Setup macht nicht viel... Senden wir mal etwas an den Sender zurück!</p>
</section>
<section>
<p>Wir nutzen <code>res.write()</code> um Inhalte zum Client zurück zu senden</p>
<pre class="js"><code data-trim data-line-numbers="2" is:raw>
http.createServer(function(req, res) {
res.write("Hallo vom Server!");
res.end();
}).listen(8080);
</code></pre>
</section>
<section>
<h3>Request &amp; Response</h3>
</section>
<section>
<p>Wenn der Server startet, wird bei jedem Request zum Server die Callback-Funktion ausgeführt.</p>
<p>Diese Funktion erhält zum einen ein Request-Objekt und zum zweiten ein Response-Objekt.</p>
</section>
<section>
<p>Mit dem Request-Objekt können wir alle Informationen aus der vom Client gesendeten Anfrage extrahieren. Das Objekt ist (ähnlich zum Reponse-Objekt) recht komplex gestaltet.</p>
<p>Im Request finden wir die URL (den Pfad) über den wir die Anfrage erhalten haben, ggf. den Body, welche Methode, und mehr.</p>
</section>
<section>
<p>Das Response-Objekt beinhaltet Funktionalität um Daten zurück zu senden. Wichtig ist dabei zu wissen das wir mit einem NodeJS-Stream Objekt interagieren.</p>
<p>Streams sind Lesbar, Schreibbar oder beides. Sie dienen dazu mit verschiedenen Dingen zu interagieren (wie zum Beispiel Netzwerk-Streams, Interkation mit Dateien und mehr).</p>
</section>
<section>
<p>Für uns wichtig ist erstmal der Umstand, das wir in das response-Objekt mittels <code>.write()</code> Daten in den Stream hinein schreiben können, und dass wir mit <code>.end()</code> den Stream schließen können (und damit ultimativ den Request "beenden" oder schließen).</p>
</section>
<section>
<p>Geben wir ein paar Infos zum <em>testen</em> zurück.</p>
<pre class="js"><code data-trim data-line-numbers="3-4" is:raw>
http.createServer(function(req, res) {
res.write("Hallo vom Server!&lt;br /&gt;");
res.write(`Request unter dem Pfad ${req.url} aufgerufen.
Verwendete Methode: ${req.method}`);
res.end();
}).listen(8080);
</code></pre>
</section>
<section>
<p>Nun erhalten wir ein paar Informationen im Browser (Pfad + Methode). Aber offensichtlich denkt der Browser nicht, dass wir hier mit HTML arbeiten..</p>
<p>Wir arbeiten auch nicht wirklich mit HTML, aber wir können dem Browser mitteilen, dass das was wir versenden HTML ist und vom Browser entsprechend interpretiert werden soll.</p>
</section>
<section>
<pre class="js"><code data-trim data-line-numbers="2" is:raw>
http.createServer(function(req, res) {
res.writeHead(200, { 'Content-Type': 'text/html' });
res.write("Hallo vom Server!&lt;br /&gt;");
res.write(`Request unter dem Pfad ${req.url} aufgerufen.
Verwendete Methode: ${req.method}`);
res.end();
}).listen(8080);
</code></pre>
</section>
<section>
<p>Damit sollte der Browser die Empfangenen Daten als HTML erkennen und sein möglichstes Versuchen um dieses korrekt zu rendern (also ohne, dass wir extra den Kompletten Rahmen mitsenden müssten.)</p>
</section>
<section>
<p>Wenn wir nun mehr daraus machen wollen, müssten wir ein paar Dinge implementieren:</p>
<ul>
<li>Routing</li>
<li>Header-Logik</li>
<li>Middleware-Systeme</li>
<li>Und mehr...</li>
</ul>
</section>
<section>
<p>Aber bevor wir uns damit auseinander setzen, verwenden wir lieber bereits existierende Frameworks die uns all diesen Aufwand ersparen.</p>
<p>Bevor wir aber dazu kommen, sehen wir uns die darunter liegenden Protokolle an, die wir hier verwenden.</p>
</section>
</section>

View file

@ -0,0 +1,162 @@
<section>
<section>
<h2>Protokolle</h2>
</section>
<section>
<p>Wir betrachten nun in den Nachfolgenden Slides was passiert wenn wir eine URL im Browser angeben bis zu dem Zeitpunkt an dem wir alle Daten empfangen haben.</p>
</section>
<section>
<h3>DNS</h3>
</section>
<section>
<p>Wenn wir eine URL wie "google.de" haben, weiß unser PC nicht, wohin der Request gesendet werden muss. Dazu benötigt der PC die IP-Adresse des Ziels.</p>
<p>IP-Adressen sind heutzutage entweder in der Version 4 oder Version 6 vorhanden. Version 6 wurde primär dazu erfunden, weil es keine Verfügbaren IPv4 Adressen mehr gab.</p>
</section>
<section>
<p>Um einen Namen wie "google.de" in eine für den Computer / das Netzwerk interpretierbare Adresse umzuwandeln, frägt der Computer bei einem DNS-Server nach.</p>
<p>Der Namens-Server gibt uns eine IP-Adresse zu der dann der Request gesendet werden kann.</p>
</section>
<section>
<p>Die Info, unter welcher IP der Namensserver zu finden ist, erhalten wir durch unseren Internet-Service-Provider (Über den Router des Providers).</p>
<p>Es gibt ein paar Schritte die bei einem DNS-Lookup geschehen:</p>
</section>
<section>
<h4>Anfrage beim "Recursive Resolver"</h4>
</section>
<section>
<p>Die IP vom DNS-Server die wir "haben", ist die eines "DNS Recursive Resolvers". Dieser ist der "Einstiegspunkt" in der Suche eines Namenseintrages.</p>
<p>DNS-Server bestehen nicht nur aus einzelnen Servern sondern sind einer Verkettung von mehreren Namens-Servern die jeweils einen kleineren Teil des Namens-Raums kennen.</p>
</section>
<section>
<h4>Anfrage beim Root-Server</h4>
</section>
<section>
<p>Der DNS-Root-Server ist die erste Übersetzungs-Ebene im DNS-System.</p>
<p>Der Root-Server kennt dabei den "nächsten" Ansprechpartner (Server), der die Adresse kennt.</p>
<p>Im Normalfall ist dies ein Top-Level-DNS-Server</p>
</section>
<section>
<h4>Anfrage beim TLD-DNS-Server</h4>
</section>
<section>
<p>Der Recursive Resolver frägt nun beim TLD-DNS-Server nach der IP des gesuchten Ziels.</p>
<p>Überlicherweise erhält der Resolver die IP des <strong>Authorative Nameserver</strong>.</p>
</section>
<section>
<h4>Anfrage beim Authorative Nameserver</h4>
</section>
<section>
<p>Der Authorative Nameserver hat die Einträge der gesuchten Domains (Name zu IP-Mapping)</p>
<p>Der Recursive Resolver kann uns nun mit der gesuchten IP Antworten.</p>
</section>
<section>
<h3>http</h3>
</section>
<section>
<p>Jeder Gängige Web-Request wird über das HTTP-Protokol versendet.</p>
<p>Über die Jahre hat sich das HTTP-1 Protokol entwickelt (HTTP2 und HTTP3). Der Inhalt eines jeden Requests ist aber zunächst gleich/ähnlich.</p>
</section>
<section>
<p>Ein HTTP-Request besteht aus mehreren Informationen:</p>
<ol>
<li>Versions-Information (HTTP)</li>
<li>Ziel-URL</li>
<li>HTTP-Methode</li>
<li>Request-Header</li>
<li>(optionaler) Body</li>
</ol>
</section>
<section>
<h4>HTTP-Methode</h4>
</section>
<section>
<p>Die HTTP-Methode definiert die Aktion die wir auf einer URL (auch genannt Resource) ausführen wollen.</p>
<p>Der Browser sendet im ohne Information "by default" ein GET bei allen Requests</p>
</section>
<section>
<ul>
<li><strong>GET</strong> um Inhalte zu erhalten</li>
<li><strong>POST</strong> um Inhalte anzulegen</li>
<li><strong>PUT</strong> um Inhalte zu modifizieren</li>
<li><strong>DELETE</strong> um Inhalte zu löschen</li>
</ul>
</section>
<section>
<p>Es gibt noch weitere Methoden wie OPTIONS, aber diese werden seltener direkt in der Webentwicklung genutzt.</p>
</section>
<section>
<h4>Headers</h4>
</section>
<section>
<p>Header im HTTP-Request enthalten zusätzliche Informationen als Key-Value-Paare.</p>
<p>Header können entweder durch Code gesetzt werden (also durch den Entwickler) als auch durch den User-Agent (Web-Browser)</p>
</section>
<section>
<p>Beispielhafte Inhalte</p>
<ul>
<li><strong>accept</strong>: Welche Datentypen als Antwort akzeptiert werden</li>
<li><strong>Auhtorization</strong>: Optionale Angabe von Informationen zum verifizieren von Nutzern.</li>
<li><strong>User-Agent</strong>: Informationen zum User-Agent (Browser zum Beispiel)</li>
<li><strong>Cache-Control</strong>: Informationen wie Inhalte gecached werden sollen</li>
<li><strong>Cookie</strong></li>
</ul>
</section>
<section>
<h4>Body</h4>
</section>
<section>
<p>Im Body eines Requests stehen die zu übertragenden Informationen der jeweiligen Seite.</p>
<p>Der Body kann bei GET-Requests von der Sendenden Partei nicht gesetzt werden.</p>
<p>Im Body befindet sich bei einer Anfrage mittels Post zum Beispiel die Information für die zu anlegende Resource.</p>
</section>
<section>
<h4>HTTP-Responses</h4>
</section>
<section>
<p>Sobald / Während der Bearbeitung kann der Server in einer Response einen StatusCode festlegen, die dem Client mitteilen soll, wie der Status zur Bearbeitung der Anfrage ist.</p>
<p>Diese Responses sind eine Zahl im Bereich zwischen 100 und 599. Wobei jede "100-er" Kategorie einen anderen Allgemeinen Zustand definiert:</p>
</section>
<section>
<ol>
<li><strong>1xx</strong> Information</li>
<li><strong>2xx</strong> Success</li>
<li><strong>3xx</strong> Redirect</li>
<li><strong>4xx</strong> Client Error</li>
<li><strong>5xx</strong> Server Error</li>
</ol>
<p>Eine Ausführliche Erklärung (mit Katzen) ist <a href="https://http.cat/" rel="noopener noreferrer">hier</a> zu finden</p>
</section>
<!-- TODO: TCP/IP -->
<!-- <section>
<h3>TCP/UDP</h3>
</section> -->
</section>

View file

@ -0,0 +1,3 @@
<section>
<h1>Backend-Entwicklung mit NodeJS (und Fastify)</h1>
</section>

View file

@ -0,0 +1,8 @@
---
import Reveal from "../../../layouts/Reveal.astro";
import Slides from "../../../components/slides/node-backend/index.astro";
---
<Reveal title="Backend Entwicklung mit NodeJS">
<Slides />
</Reveal>