
Ostatnio uruchamiałem prosty system raportowania pomiarów energii przez sieć WiFi ze "smart" gniazdka elektrycznego i potrzebowałem wygodnego sposobu na testowanie odbioru zapytań HTTP GET i POST. Pokażę tutaj jak można wykorzystać Node.js do tego celu. Node.js pozwala szybko i sprawnie postawić mini-serwerek HTTP na naszej maszynie, zdolny do przetwarzania tych właśnie zapytań i odpowiadania na nie w określony przez nas sposób. Przy okazji też pokażę jak można obsłużyć zapytanie POST z zawartością w formacie JSON oraz umieszczę tu krótkie przykłady wysyłania GET i POST z poziomu OpenBeken
UWAGA: Temat zakłada, że czytelnik posiada co najmniej minimalną wiedzę jak korzystać z konsoli, jak zainstalować Node.js, czym jest serwer, HTTP, i tak dalej...
Wysyłanie żądań HTTP
W tym temacie zakładam, że kod wysyłki żądań (tj. klienta) już mamy, a potrzebujemy utworzyć mini serwer do testów, ale mimo to warto zaznaczyć, jak można te żądania wysyłać.
Przykładowo można użyć biblioteki curl, która jest dostępna na wielu platformach:
https://curl.se/
Innym sposobem może być wysyłanie bezpośrednio z Javascript, chociażby wykonywanego w przeglądarce, możemy utworzyć plik HTML i w nim się bawić w XMLHttpRequest bądź fetch i tak dalej.
Jeszcze innym, wyjątkowo skomplikowanym sposobem jest wysyłanie zapytań z własnego środowiska, przykładowo u mnie w OpenBeken są funkcje do wysyłania GET i POST, to właśnie te funkcje przy tworzeniu tego tematu testowałem.
Bez względu na wybór klienta, w tym temacie przedstawię jak utworzyć prosty serwer HTTP w Node.js, zdolny do odbioru wspomnianych GET i POST.
Obsługa HTTP GET
Zapytanie GET jest chyba najpopularniejsze w sieci, pozwala ono zakodować argumenty w samym URL strony, nawet na naszym forum w trakcie pisania postu widzimy:
https://www.elektroda.pl/rtvforum/posting.php?mode=reply&t=3977701&p=20578056
Argumenty GET są po pytajniku, widzimy tutaj, że klucz "mode" ma wartość "reply", a klucz "t" ma wartość "3977701", itd.
W ramach przykładu zrobimy prosty kalkulator. Jako argumenty będzie a i b, serwer nam zwróci ich sumę. Tworzymy plik server.js i zapisujemy:
Code: javascript
Wywołanie app.get w powyższym kodzie nie jest wysyłaniem żądania GET, leczu tworzeniem callbacka, który je obsłuży. W nim odbieramy i przetwarzamy dane. Poprzez req.query dobieramy się do argumentów z URL.
Nawigujemy w CMD do folderu gdzie jest skrypt, i uruchamiamy go poprzez node server.js, ale pewnie otrzymamy błąd - nie ma paczki express, trzeba ją zainstalować poprzez npm install express, oto cały log:

Potem już node server.js poprawnie się wykonuje.
Teraz trzeba jakoś wysłać do niego dane, sposób pierwszy - przeglądarka, otwieramy URL:
http://127.0.0.1:3000/?a=13&b=87
Działa:

W logu serwera też widzimy, że coś się dzieje:

To teraz może wyślijmy zapytanie GET przez CURL:

Oczywiście CURL musi być wcześniej zainstalowane.
No i w ramach ciekawostki - to samo z OpenBeken:
backlog setChannel 10 13; setChannel 11 87; SendGET http://localhost:3000/?a=$CH10&b=$CH11

W OBK ten mechanizm nie wspiera na razie parsowania odpowiedzi z poziomu skryptu, służy tylko do raportowania danych do serwera.
Obsługa HTTP POST
Teraz będzie nieco trudniej, bo treść POST zawarta jest już w ciele zapytania, a nie w URL, więc zasadniczo nie widać jej na pierwszy rzut oka. Oczywiście POST też występuje nawet na naszym forum, przykładowo jak się logujemy bądź rejestrujemy, wtedy nasz login i hasło jest właśnie wysyłane zapytaniem POST.
Post dodatkowo wprowadza tzw. Content-Type, czyli typ zawartości zapytania, może to być przykładowo czysty tekst, strumień binarny bądź właśnie format JSON.
Jak wygląda JSON? Przykładowy JSON poniżej:
Code: json
JSON może przechowywać obiekty wraz z parami klucz-wartość oraz tablice.
Przepiszmy w ramach przykładu nasz kod tak, by korzystał z formatu JSON ale wciąż wykonywał tę samą operację.
Code: javascript
Tak jak wcześniej tworzyliśmy callback w app.get, tutaj tak samo tworzymy obsługę post w app.post. Teraz a i b bierzemy z tekstu w formacie JSON, z ciała zapytania.
Teraz trzeba go przetestować. Zacznijmy od metody z CURL:
curl -X POST -H "Content-Type: application/json" -d "{\"a\": 13, \"b\": 87}" http://localhost:3000/
Przełącznik X ustawia typ zapytania, H dodaje nagłówek Content-Type określający co wysyłamy, -d ustawia dane. Cudzysłów z \ to tzw. escape sequence, pozwala umieścić cudzysłów w treści zapytania bez rzeczywistego zamykania cudzysłowia określającego blok danych.
Wszystko działa:

W ramach przykładu, zobaczmy jak można to samo wysłać z samego Javascript - z prostego pliku HTML, uruchamianego w przeglądarce, bez stawiania serwera. Każdy może to wygodnie odpalić:
Code: html
Niestety ten skrypt nie wykona się poprawnie. Pojawia się tutaj problem z CORS (Cross-Origin Resource Sharing).

Treść błędu jako tekst:
p://localhost:3000/' from origin 'null' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
test.html:18
POST http://localhost:3000/ net::ERR_FAILED
sendSumRequest @ test.html:18
onclick @ test.html:23
CORS blokuje zewnętrzne zapytania Ajax w celu zwiększenia bezpieczeństwa zasobów, musimy je odblokować. Modyfikujemy serwer:
Code: javascript
Jeszcze nie odpalamy, inaczej dostalibyśmy błąd:
Error: Cannot find module 'cors'
więc instalujemy brakującą paczkę:
npm install cors

Po tej zmianie (i restarcie serwera) skrypt działa:

No i jeszcze w ramach ciekawostki to samo z OpenBeken:
backlog setChannel 10 13; setChannel 11 87; SendPOST http://localhost:3000/ 3000 "application/json" "{ \"a\":$CH10, \"b\":$CH11 }"
Kod specjalnie, w ramach demonstracji, ustawia kanały na 13 i 87 a potem wykorzystuje ich wartości przy generacji JSON.

Rezultat:

Podsumowanie
Node.js oferuje bardzo wygodny zbiór narzędzi i bibliotek do tworzenia aplikacji typu server-side w języku Javascript. Tutaj pokazałem jak można je wykorzystać do utworzenia mini-serverka do testów odbioru zapytań GET i POST, gdyż docelowo serwer zamierzam postawić na jednym z darmowych hostingów WWW dostępnych w sieci a same zapytania będę odbierać już na poziomie PHP, ale nic nie stoi na przeszkodzie by wykorzystać Node.js inaczej, wszystko wedle uznania.
W podobny sposób można też dostać się bezpośrednio do bazy danych, np. do InfluxDB, dzięki użyciu ich HTTP API:
https://archive.docs.influxdata.com/influxdb/v1.2/guides/writing_data/
Być może wkrótce pokażę jakiś konkretny przykład realizacji loggera temperatury czy tam napięcia/prądu/mocy w oparciu o pokazane tu mechanizmy.
Cool? Ranking DIY