Articles

Zbuduj i zrozum Express Middleware na przykładach

Posted on

Jeśli w ciągu ostatnich siedmiu lub ośmiu lat zajmowałeś się jakimkolwiek znaczącym rozwojem Node, prawdopodobnie używałeś Express do zbudowania serwera WWW w pewnym momencie. Podczas gdy możesz stworzyć serwer w Node bez użycia biblioteki, nie daje ci to zbyt wiele po wyjęciu z pudełka i może być dość kłopotliwe w dodawaniu funkcjonalności. Express jest minimalistyczną, „nieopartą na opiniach” biblioteką serwerową i stał się de facto standardem budowania aplikacji webowych w Node. Aby zrozumieć Express, musisz zrozumieć Express Middleware.

Co to jest Express Middleware?

Middleware oznacza dosłownie wszystko, co umieszcza się w środku jednej warstwy oprogramowania i drugiej. Oprogramowanie pośredniczące Express to funkcje, które są wykonywane podczas cyklu życia żądania do serwera Express. Każde oprogramowanie pośredniczące ma dostęp do danych HTTP request i response dla każdej trasy (lub ścieżki), do której jest dołączone. W rzeczywistości, sam Express składa się w całości z funkcji middleware. Dodatkowo, oprogramowanie pośredniczące może albo zakończyć żądanie HTTP, albo przekazać je do innej funkcji oprogramowania pośredniczącego za pomocą next (więcej na ten temat wkrótce). To „łańcuchowanie” oprogramowania pośredniczącego pozwala na podział kodu na kategorie i tworzenie oprogramowania pośredniczącego wielokrotnego użytku.

W tym artykule wyjaśnię, czym jest oprogramowanie pośredniczące, dlaczego warto z niego korzystać, jak używać istniejącego oprogramowania pośredniczącego Express oraz jak napisać własne oprogramowanie pośredniczące dla Express.

Wymagania do napisania oprogramowania pośredniczącego Express

Jest kilka rzeczy, które będą potrzebne do tworzenia, używania i testowania oprogramowania pośredniczącego Express. Po pierwsze, będziesz potrzebował Node i NPM. Aby upewnić się, że są one zainstalowane, możesz uruchomić:

npm -v && node -v

Powinieneś zobaczyć wersje Node i NPM, które masz zainstalowane. Jeśli otrzymasz błąd, musisz zainstalować Node. Używam najnowszej wersji obu w momencie pisania tego artykułu, czyli Node 10.9.0 i NPM 6.4.1, ale wszystkie przykłady powinny działać z Node w wersji 8+ i NPM w wersji 5+.

Będę również używał Express w wersji 4.x. Jest to ważne, ponieważ w wersji 3.x wprowadzono duże zmiany w stosunku do wersji 4.x.

Pomocne będzie również posiadanie zainstalowanego Postmana, aby testować trasy używające jakichkolwiek czasowników HTTP innych niż GET.

Express Middleware: The Basics

Na początek użyjemy najbardziej podstawowego z wbudowanych w Express middleware’ów. Pozwoli to zobaczyć, w jaki sposób oprogramowanie pośredniczące jest używane i jak jest zbudowane oprogramowanie pośredniczące Expressu.

Utwórz nowy projekt i npm init go…

npm initnpm install express --save

Utwórz server.js i wklej następujący kod:

const express = require('express');const app = express();app.get('/', (req, res, next) => { res.send('Welcome Home');});app.listen(3000);

Uruchom serwer poprzez node server.js, wejdź na http://localhost:3000, a w przeglądarce powinieneś zobaczyć wydrukowany napis „Welcome Home”.

Funkcja app.get() jest Application-level Middleware. Zauważysz, że parametry przekazywane do metody to reqres, oraz next. Są to: przychodzące żądanie, zapisywana odpowiedź oraz metoda, którą należy wywołać, aby przekazać wywołanie do następnej funkcji oprogramowania pośredniczącego po zakończeniu bieżącego oprogramowania pośredniczącego. W tym przypadku, gdy odpowiedź zostanie wysłana, funkcja kończy działanie. Możesz także połączyć tutaj inne middleware, wywołując metodę next().

Przyjrzyjrzyjmy się jeszcze kilku przykładom różnych typów middleware.

Przykład Middleware’u logowania żądań Express

W Expressie możesz ustawić middleware jako „globalny” middleware, co oznacza, że będzie on wywoływany dla każdego przychodzącego żądania.

Zmień zawartość server.js na:

const express = require('express');const app = express();app.use((req, res, next) => { console.log(req); next();});app.get('/', (req, res, next) => { res.send('Welcome Home');});app.listen(3000);

Tym razem, po przejściu do http://localhost:3000 powinieneś zobaczyć to samo w oknie przeglądarki, ale z powrotem w oknie konsoli zobaczysz dane wyjściowe obiektu żądania przychodzącego.

Oprogramowanie pośredniczące wylogowuje obiekt żądania, a następnie wywołuje next(). Następne oprogramowanie pośredniczące w potoku obsługuje żądanie get do głównego adresu URL i odsyła odpowiedź tekstową. Użycie app.use() oznacza, że to oprogramowanie pośredniczące będzie wywoływane dla każdego wywołania aplikacji.

Przykład restrykcyjnego typu zawartości Express Request

Oprócz uruchamiania oprogramowania pośredniczącego dla wszystkich wywołań, można również określić, aby uruchamiać oprogramowanie pośredniczące tylko dla określonych wywołań.

Zmień ponownie plik server.js na:

const express = require('express');const app = express();const requireJsonContent = () => { return (req, res, next) => { if (req.headers !== 'application/json') { res.status(400).send('Server requires application/json') } else { next() } }}app.get('/', (req, res, next) => { res.send('Welcome Home');});app.post('/', requireJsonContent(), (req, res, next) => { res.send('You sent JSON');})app.listen(3000);

Tym razem uruchom serwer uruchamiając:

node server.js

Aby to przetestować, otwórz Postmana i utwórz żądanie post do http://localhost:3000. Nie ustawiaj żadnych nagłówków i uruchom żądanie. Otrzymasz z powrotem wiadomość „Serwer wymaga application/json”.

Teraz wróć i dodaj nagłówek Content-Type o wartości application/json i uruchom żądanie ponownie. Otrzymasz wiadomość „You sent JSON” z powrotem z serwera.

Ten app.post() wywołanie metody dodaje funkcję requireJsonContent() middleware, aby upewnić się, że przychodzący ładunek żądania ma wartość nagłówka Content-Type ustawioną na application/json. Jeśli nie przejdzie on kontroli, wysyłana jest odpowiedź o błędzie. Jeśli przejdzie, żądanie jest przekazywane do następnego elementu oprogramowania pośredniczącego w łańcuchu za pomocą metody next().

Third-Party Express Middleware

Zbudowałeś kilka niestandardowych programów pośredniczących, ale istnieje wiele pakietów już zbudowanych do robienia rzeczy, które normalnie chciałbyś robić. W rzeczywistości wykorzystałeś prostą bibliotekę oprogramowania pośredniczącego do routingu, używając funkcji oprogramowania pośredniczącego app.get() lub app.post(). Istnieją tysiące bibliotek middleware do robienia takich rzeczy, jak parsowanie danych przychodzących, routing i autoryzacja.

Okta ma Express middleware dla bezpieczeństwa OIDC, które pokażę Ci, aby zademonstrować użycie bibliotek middleware innych firm.

Dlaczego Okta dla Express Applications

W Okta naszym celem jest uczynienie zarządzania tożsamością o wiele łatwiejszym, bezpieczniejszym i bardziej skalowalnym niż to, do czego jesteś przyzwyczajony. Okta to usługa w chmurze, która pozwala programistom tworzyć, edytować i bezpiecznie przechowywać konta użytkowników oraz dane o kontach użytkowników, a także łączyć je z jedną lub wieloma aplikacjami. Nasze API umożliwia:

  • Uwierzytelnianie i autoryzację użytkowników
  • Przechowywanie danych o użytkownikach
  • Prowadzenie logowania opartego na haśle i logowania społecznościowego
  • Zabezpieczenie aplikacji za pomocą uwierzytelniania wieloczynnikowego
  • I wiele więcej! Zapoznaj się z naszą dokumentacją produktu

Okta’s OIDC Express Middleware

Aby zainstalować Okta’s OIDC middleware for Express, uruchom:

npm install @okta/[email protected] --save

Następnie w pliku server.js tworzymy instancję, jeśli middleware z pewnymi opcjami konfiguracyjnymi, aby Okta wiedziała, jak połączyć się z Twoją aplikacją Okta.

const oidc = new ExpressOIDC({ issuer: 'https://{yourOktaDomain}/oauth2/default', client_id: '{yourClientId}', client_secret: '{yourClientSecret}', redirect_uri: 'http://localhost:3000/authorization-code/callback', scope: 'openid profile'});

Będziesz musiał również powiedzieć Expressowi, aby używał routera middleware OIDC zamiast domyślnego routera.

app.use(oidc.router);

Wtedy używasz go jak każdego innego oprogramowania pośredniego:

app.get('/protected', oidc.ensureAuthenticated(), (req, res) => { res.send('Top Secret');});

Funkcja oidc.ensureAuthenticated() jest oprogramowaniem pośrednim w bibliotece Okta. Uruchamia funkcję, aby sprawdzić, czy bieżący użytkownik jest zalogowany. Jeśli tak, wywołuje next(), aby pozwolić funkcji app.get() kontynuować obsługę żądania. Jeśli nie są, odeśle odpowiedź HTTP 401 (Unauthorized).

Porządek oprogramowania pośredniczącego jest ważny

Kiedy żądanie jest odbierane przez Express, każde oprogramowanie pośredniczące, które odpowiada żądaniu, jest uruchamiane w kolejności, w jakiej zostało zainicjowane, dopóki nie nastąpi zakończenie działania (jak wysłanie odpowiedzi).

Przepływ oprogramowania pośredniczącego

Więc, jeśli wystąpi błąd, całe oprogramowanie pośredniczące, które jest przeznaczone do obsługi błędów, będzie wywoływane w kolejności, dopóki jedno z nich nie wywoła wywołania funkcji next().

Obsługa błędów w Express Middleware

Express posiada wbudowany domyślny mechanizm obsługi błędów, który jest wstawiany na końcu potoku oprogramowania pośredniczącego i obsługuje wszelkie nieobsługiwane błędy, które mogły wystąpić w potoku. Jego sygnatura dodaje parametr błędu do standardowych parametrów request, response i next. Podstawowa sygnatura wygląda następująco:

app.use((err, req, res, next) => { // middleware functionality here})

Aby wywołać middleware obsługujący błędy, wystarczy przekazać błąd do next(), tak jak poniżej:

app.get('/my-other-thing', (req, res, next) => { next(new Error('I am passing you an error!'));});app.use((err, req, res, next) => { console.log(err); if(!res.headersSent){ res.status(500).send(err.message); }});

W tym przypadku oprogramowanie pośredniczące obsługi błędów na końcu potoku obsłuży błąd. Możesz również zauważyć, że sprawdziłem właściwość res.headersSent. To tylko sprawdza, czy odpowiedź wysłała już nagłówki do klienta. Jeśli nie, to wysyła do klienta status 500 HTTP i komunikat o błędzie. Możesz również połączyć łańcuchowo oprogramowanie pośredniczące obsługujące błędy. Jest to powszechne, aby obsługiwać różne typy błędów na różne sposoby. Na przykład:

app.get('/nonexistant', (req, res, next) => { let err = new Error('I couldn\'t find it.'); err.httpStatusCode = 404; next(err);});app.get('/problematic', (req, res, next) => { let err = new Error('I\'m sorry, you can\'t do that, Dave.'); err.httpStatusCode = 304; next(err);});// handles not found errorsapp.use((err, req, res, next) => { if (err.httpStatusCode === 404) { res.status(400).render('NotFound'); } next(err);});// handles unauthorized errorsapp.use((err, req, res, next) => { if(err.httpStatusCode === 304){ res.status(304).render('Unauthorized'); } next(err);})// catch allapp.use((err, req, res, next) => { console.log(err); if (!res.headersSent) { res.status(err.httpStatusCode || 500).render('UnknownError'); }});

W tym przypadku, oprogramowanie pośredniczące sprawdza czy błąd 404 (not found) został rzucony. Jeśli tak, to renderuje stronę szablonu 'NotFound', a następnie przekazuje błąd do następnego elementu w oprogramowaniu pośredniczącym. Następny element middleware sprawdza, czy został rzucony błąd 304 (unauthorized). Jeśli tak, renderuje stronę 'Unauthorized' i przekazuje błąd do następnego middleware w potoku. Wreszcie, obsługa błędów „catch all” po prostu rejestruje błąd i jeśli nie została wysłana żadna odpowiedź, wysyła httpStatusCode (lub status HTTP 500, jeśli nie został podany) i renderuje szablon „UnknownError”.

Learn More About Express Middleware

Szczegółowe instrukcje dotyczące konfiguracji oprogramowania pośredniczącego Okta OIDC można znaleźć w ExpressJS Quickstart.

W tym repo na GitHubie znajduje się również lista oficjalnie obsługiwanego oprogramowania pośredniczącego Express, które można wypróbować i zgłębić, aby dowiedzieć się więcej

Wreszcie, jeśli chcesz dowiedzieć się więcej o tym, jak korzystać z Okta, dostępny jest Okta Node SDK do implementacji większej liczby funkcji zarządzania użytkownikami w Twojej aplikacji.

Więcej informacji na temat Okta Node SDK można znaleźć na stronie internetowej Okta.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *