| 1 | = Node.js = |
| 2 | |
| 3 | == Literaturhinweise == |
| 4 | |
| 5 | W3Schools [[https://www.w3schools.com/nodejs/default.asp|Node.js Tutorial]] |
| 6 | |
| 7 | Roden: [[https://ebookcentral.proquest.com/lib/hrw/reader.action?docID=1049737&ppg=52|Node.js & Co. - Kapitel 3 ff.]] |
| 8 | |
| 9 | == Einführung == |
| 10 | |
| 11 | Node.js ist ein Framework, das es erlaubt, serverseitig !JavaScript-Programme auszuführen. Mit einer Vielzahl von webspezifischen Erweiterungen bietet es einen mächtigen Funktionsumfang für die Implementierung von Webanwendungen. |
| 12 | |
| 13 | [[https://nodejs.org|Node.js Webseite]] |
| 14 | |
| 15 | Für die Entwicklung kann eine lokale Node.js-Installation als Laufzeitumgebung (Runtime) in [[http://www.eclipse.org/downloads/packages/eclipse-ide-javascript-and-web-developers/neon3|Eclipse IDE for JavaScript and Web Developers]] eingebunden werden: Einstellungen -> !JavaScript -> Runtimes -> Global Node Installation -> Edit oder Add |
| 16 | |
| 17 | Über Run As -> Standalone Node.js Application lässt sich das Programm ausführen. |
| 18 | |
| 19 | Erstes Programm: |
| 20 | {{{#!javascript |
| 21 | console.log("Hello World"); |
| 22 | }}} |
| 23 | |
| 24 | Node.js Programme haben grundsätzlich dieselbe Struktur wie clientseitige Programme. Die API ist weitestgehend identisch. Beispielsweise lassen sich auch Timeouts verwenden: |
| 25 | {{{#!javascript |
| 26 | function world() { |
| 27 | console.log("Welt"); |
| 28 | } |
| 29 | |
| 30 | setTimeout(world, 2000); |
| 31 | |
| 32 | console.log("Hallo"); |
| 33 | }}} |
| 34 | |
| 35 | Ausgabe auf der Konsole: |
| 36 | {{{ |
| 37 | Hallo |
| 38 | Welt (2 Sekunden verzögert) |
| 39 | }}} |
| 40 | |
| 41 | Für die Interaktion mit einem Client (Browser) über eine HTTP-Verbindung wird das HTTP-Modul importiert, der Server erzeugt und an einen Port (hier: 3000) gebunden: |
| 42 | {{{ |
| 43 | #!CodeExample |
| 44 | ## title = Einfachster HTTP-Server |
| 45 | ## repo = Web_Quellcode_FP |
| 46 | ## path = /vorlesung/node.js/http_hello.js |
| 47 | #!javascript |
| 48 | }}} |
| 49 | |
| 50 | Beim Erzeugen des Servers mit `createServer` wird eine Funktion (hier: `serve`) übergeben, die als Eventhandler aufgerufen wird, sobald ein HTTP-Request auf Port 3000 ankommt. Über die beiden Parameter `req` und `res` hat die Funktion Zugriff auf die Daten des Requests (`req`) und kann die Antwort (Response, `res`) schreiben. |
| 51 | |
| 52 | Für Debugging-Zwecke kann es sinnvoll sein, Informationen zum Request auf der Konsole auszugeben oder ins Log zu schreiben: |
| 53 | {{{ |
| 54 | #!CodeExample |
| 55 | ## title = HTTP-Server mit Log des Requests |
| 56 | ## repo = Web_Quellcode_FP |
| 57 | ## path = /vorlesung/node.js/http_hello2.js |
| 58 | #!javascript |
| 59 | }}} |
| 60 | |
| 61 | Ausgabe auf der Konsole beim Aufruf http://localhost:3000: |
| 62 | {{{ |
| 63 | *************************** |
| 64 | { host: 'localhost:3000', |
| 65 | connection: 'keep-alive', |
| 66 | 'upgrade-insecure-requests': '1', |
| 67 | 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36', |
| 68 | accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', |
| 69 | 'accept-encoding': 'gzip, deflate, sdch, br', |
| 70 | 'accept-language': 'en-US,en;q=0.8' } |
| 71 | =========================== |
| 72 | / |
| 73 | *************************** |
| 74 | { host: 'localhost:3000', |
| 75 | connection: 'keep-alive', |
| 76 | 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36', |
| 77 | accept: 'image/webp,image/*,*/*;q=0.8', |
| 78 | referer: 'http://localhost:3000/', |
| 79 | 'accept-encoding': 'gzip, deflate, sdch, br', |
| 80 | 'accept-language': 'en-US,en;q=0.8' } |
| 81 | =========================== |
| 82 | /favicon.ico |
| 83 | }}} |
| 84 | |
| 85 | Hierbei fällt auf, dass vom Browser offenbar zwei Requests abgesetzt werden. Zusätzlich zur eigentlichen Anfrage nach dem URL `/` wird eine Anfragenach dem URL `/favicon.ico` abgesetzt. Dies ist ein Standardverhalten der Browser, das sich clientseitig nur durch eine Präparation der HTML-Seite deaktivieren lässt, z. B. mit der folgenden Angabe im `head` (Quelle: [[https://stackoverflow.com/questions/1321878/how-to-prevent-favicon-ico-requests|stackoverflow]]): |
| 86 | |
| 87 | {{{ |
| 88 | #!htm |
| 89 | <link rel="icon" href="data:;base64,="> |
| 90 | }}} |
| 91 | |
| 92 | Da wir momentan nur Requests über die Adresszeile eingeben, lässt sich das Verhalten clientseitig bei Verwendung einen Browsers überhaupt nicht unterdrücken. Wird ein reiner HTTP-Client wie z. B. [[#Postman|Postman]] verwendet, erfolgt diese Anfrage nicht. |
| 93 | |
| 94 | == URL analysieren == |
| 95 | In der Ausgabe lässt sich darüberhinaus erkennen, dass das Request-Objekt umfangreiche Informationen über die Anfrage enthält, darunter den URL. Auf diesem kann mit dem Attribut `url` zugegriffen werden. Damit lassen in Abhängigkeit des URL verschiedene Aktionen ausführen: |
| 96 | {{{ |
| 97 | #!CodeExample |
| 98 | ## title = URL-abhängige Antwort |
| 99 | ## repo = Web_Quellcode_FP |
| 100 | ## path = /vorlesung/node.js/request_url.js |
| 101 | #!javascript |
| 102 | }}} |
| 103 | |
| 104 | == Verarbeitung von favicon-Requests unterbinden == |
| 105 | Mit dem Wissen um die Eigenschaften des Request-Objekts lässt sich nun die (weitere) Verarbeitung der favicon-Requests unterbinden, indem der entsprechende URL vor allen anderen abgefangen wird: |
| 106 | {{{ |
| 107 | #!CodeExample |
| 108 | ## title = Favicon-Request abfangen |
| 109 | ## repo = Web_Quellcode_FP |
| 110 | ## path = /vorlesung/node.js/suppress_favicon.js |
| 111 | ## regex = function serve |
| 112 | ## lines = 10 |
| 113 | #!javascript |
| 114 | }}} |
| 115 | |
| 116 | == Node.js Module == |
| 117 | Hinweis zur Installation von Modulen mit npm: bei einigen Modulen (z. B. express) wird in der IDE der Syntaxfehler "Unexpected token ILLEGAL" angezeigt. Dies lässt sich umgehen, indem die Module mit der Option `--no-bin-links` installiert werden: |
| 118 | {{{ |
| 119 | > npm install --no-bin-links express |
| 120 | }}} |
| 121 | |
| 122 | [=#includejs] |
| 123 | == Aufteilen von Skripten auf mehrere Dateien == |
| 124 | Wenn das serverseitige Skript sehr umfangreich wird, teilt man es üblicherweise auf mehrere .js Dateien auf. In Node.js erfolgt dies, indem man die einzubindende Datei als Modul aufbaut und dieses mittels `require` einbindet. |
| 125 | |
| 126 | Datei, die eingebunden werden soll (helper.js im selben Verzeichnis wie die Serverapp): |
| 127 | {{{ |
| 128 | #!javascript |
| 129 | module.exports = { |
| 130 | foo: function () { |
| 131 | // ... |
| 132 | }, |
| 133 | bar: function () { |
| 134 | // ... |
| 135 | } |
| 136 | }; |
| 137 | |
| 138 | var privat = function () { |
| 139 | // ... |
| 140 | } |
| 141 | }}} |
| 142 | |
| 143 | Die Funktionen `foo` und `bar` sind jetzt extern verfügbar, die Funktion `privat` dagegen nicht. Einbinden von helper.js in die Serverapp: |
| 144 | |
| 145 | {{{ |
| 146 | #!javascript |
| 147 | var helper = require('./helper'); |
| 148 | |
| 149 | console.log(typeof helper.foo); // => 'function' |
| 150 | console.log(typeof helper.bar); // => 'function' |
| 151 | console.log(typeof helper.privat); // => undefined |
| 152 | }}} |
| 153 | |
| 154 | (Quelle: [[https://stackoverflow.com/questions/5797852/in-node-js-how-do-i-include-functions-from-my-other-files|Stack Overflow]]) |
| 155 | |
| 156 | == Postman == |
| 157 | |
| 158 | [[https://chrome.google.com/webstore/detail/postman/fhbjgbiflinjbdggehcddcbncdddomop|Postman]] ist eine Chrome-App, die als Standalone-HTTP-Client verwendet werden kann. Sie eignet sich im Entwicklungsprozess insbesondere zum Testen von HTTP-Servern und REST-Interfaces. |