Pisanie middleware do wykorzystania w aplikacjach Express

Przegląd

Funkcje middleware to funkcje, które mają dostęp do obiektu żądania (req), obiektu odpowiedzi (res), oraz funkcji next w cyklu żądanie-odpowiedź aplikacji. Funkcja next jest funkcją w routerze Express, której wywołanie powoduje wykonanie oprogramowania pośredniczącego następującego po bieżącym oprogramowaniu pośredniczącym.

Funkcje oprogramowania pośredniczącego mogą wykonywać następujące zadania:

  • Wykonanie dowolnego kodu.
  • Wprowadzenie zmian w obiektach żądania i odpowiedzi.
  • Zakończyć cykl żądanie-odpowiedź.
  • Wywołać następne oprogramowanie pośredniczące w stosie.

Jeśli aktualna funkcja oprogramowania pośredniczącego nie zakończy cyklu żądanie-odpowiedź, musi wywołać next() aby przekazać kontrolę do następnej funkcji oprogramowania pośredniczącego. W przeciwnym razie żądanie pozostanie zawieszone.

Następujący rysunek przedstawia elementy wywołania funkcji oprogramowania pośredniczącego:

MetodaHTTP, której dotyczy funkcja oprogramowania pośredniczącego.
Ścieżka (trasa), dla której ma zastosowanie funkcja oprogramowania pośredniczącego.
Funkcja oprogramowania pośredniczącego.
Callback argument funkcji oprogramowania pośredniczącego, zwany umownie „next”.
Tryb odpowiedziHTTP do funkcji oprogramowania pośredniczącego, zwany umownie „res”.
Tryb żądaniaHTTP do funkcji oprogramowania pośredniczącego, zwany umownie „req”.

Począwszy od Express 5, funkcje oprogramowania pośredniczącego, które zwracają obietnicę, będą wywoływać next(value) gdy odrzucają lub rzucają błąd. next zostanie wywołany z odrzuconą wartością lub rzuconym błędem.

Przykład

Przykładem jest prosta aplikacja Express „Hello World”.W dalszej części tego artykułu zdefiniujemy i dodamy do aplikacji trzy funkcje middleware: jedną o nazwie myLogger, która drukuje prosty komunikat dziennika, jedną o nazwie requestTime, która wyświetla znacznik czasu żądania HTTP, oraz jedną o nazwie validateCookies, która sprawdza poprawność przychodzących ciasteczek.

var express = require('express')var app = express()app.get('/', function (req, res) { res.send('Hello World!')})app.listen(3000)

Funkcja middleware myLogger

Oto prosty przykład funkcji middleware o nazwie „myLogger”. Ta funkcja po prostu drukuje „LOGGED”, gdy żądanie do aplikacji przechodzi przez nią. Funkcja middleware jest przypisana do zmiennej o nazwie myLogger.

var myLogger = function (req, res, next) { console.log('LOGGED') next()}

Zauważ powyższe wywołanie funkcji next(). Wywołanie tej funkcji wywołuje kolejną funkcję middleware w aplikacji.Funkcja next() nie jest częścią API Node.js czy Express, ale jest trzecim argumentem przekazywanym do funkcji middleware. Funkcja next() może mieć dowolną nazwę, ale umownie zawsze jest nazywana „next”.Aby uniknąć zamieszania, zawsze używaj tej konwencji.

Aby załadować funkcję middleware, wywołaj app.use(), określając funkcję middleware.Na przykład, poniższy kod ładuje funkcję oprogramowania pośredniczącego myLogger przed trasą do ścieżki głównej (/).

var express = require('express')var app = express()var myLogger = function (req, res, next) { console.log('LOGGED') next()}app.use(myLogger)app.get('/', function (req, res) { res.send('Hello World!')})app.listen(3000)

Za każdym razem, gdy aplikacja otrzymuje żądanie, drukuje komunikat „LOGGED” do terminala.

Porządek ładowania oprogramowania pośredniczącego jest ważny: funkcje oprogramowania pośredniczącego, które są ładowane jako pierwsze, są również wykonywane jako pierwsze.

Jeśli myLogger zostanie załadowany po trasie do ścieżki głównej, żądanie nigdy do niego nie dotrze i aplikacja nie wydrukuje komunikatu „LOGGED”, ponieważ obsługa trasy ścieżki głównej kończy cykl żądanie-odpowiedź.

Funkcja middleware myLogger po prostu drukuje komunikat, a następnie przekazuje żądanie do następnej funkcji middleware w stosie, wywołując funkcję next().

Funkcja middleware requestTime

Następnie utworzymy funkcję middleware o nazwie „requestTime” i dodamy właściwość o nazwie requestTime do obiektu żądania.

var requestTime = function (req, res, next) { req.requestTime = Date.now() next()}

Aplikacja używa teraz funkcji oprogramowania pośredniczącego requestTime. Również funkcja wywołania zwrotnego trasy ścieżki korzenia wykorzystuje właściwość, którą funkcja oprogramowania pośredniczącego dodaje do req (obiekt żądania).

var express = require('express')var app = express()var requestTime = function (req, res, next) { req.requestTime = Date.now() next()}app.use(requestTime)app.get('/', function (req, res) { var responseText = 'Hello World!<br>' responseText += '<small>Requested at: ' + req.requestTime + '</small>' res.send(responseText)})app.listen(3000)

Gdy użytkownik zgłasza żądanie do korzenia aplikacji, aplikacja wyświetla teraz znacznik czasu żądania w przeglądarce.

Funkcja middleware validateCookies

Na koniec stworzymy funkcję middleware, która waliduje przychodzące ciasteczka i wysyła odpowiedź 400, jeśli ciasteczka są nieprawidłowe.

Oto przykład funkcji, która waliduje ciasteczka za pomocą zewnętrznej usługi async.

async function cookieValidator (cookies) { try { await externallyValidateCookie(cookies.testCookie) } catch { throw new Error('Invalid cookies') }}

Użyjemy tutaj oprogramowania pośredniczącego cookie-parser do parsowania przychodzących ciasteczek z obiektu req i przekazania ich do naszej funkcji cookieValidator. Funkcja validateCookies middleware zwraca Promise, który po odrzuceniu automatycznie wywoła nasz error handler.

var express = require('express')var cookieParser = require('cookie-parser')var cookieValidator = require('./cookieValidator')var app = express()async function validateCookies (req, res, next) { await cookieValidator(req.cookies) next()}app.use(cookieParser())app.use(validateCookies)// error handlerapp.use(function (err, req, res, next) { res.status(400).send(err.message)})app.listen(3000)

Zauważ, jak next() jest wywoływany po await cookieValidator(req.cookies). Gwarantuje to, że jeśli cookieValidator się rozwiąże, zostanie wywołane następne oprogramowanie pośrednie w stosie. Jeśli przekażemy cokolwiek do funkcji next() (z wyjątkiem łańcucha 'route' lub 'router'), Express uzna bieżące żądanie za błąd i pominie wszystkie pozostałe funkcje routingowe i middleware nie obsługujące błędów.

Ponieważ masz dostęp do obiektu żądania, obiektu odpowiedzi, następnej funkcji middleware w stosie i całego API Node.js, możliwości z funkcjami middleware są nieograniczone.

Więcej informacji o Express middleware, zobacz: Korzystanie z Express middleware.

Konfigurowalne middleware

Jeśli potrzebujesz, aby twoje middleware było konfigurowalne, wyeksportuj funkcję, która przyjmuje obiekt opcji lub inne parametry, która, następnie zwraca implementację middleware na podstawie parametrów wejściowych.

Plik: my-middleware.js

module.exports = function (options) { return function (req, res, next) { // Implement the middleware function based on the options object next() }}

Oprogramowanie pośredniczące może być teraz używane jak pokazano poniżej.

var mw = require('./my-middleware.js')app.use(mw({ option1: '1', option2: '2' }))

Przykłady konfigurowalnego oprogramowania pośredniczącego można znaleźć w cookie-session i kompresji.

Przykłady konfigurowalnego oprogramowania pośredniczącego można znaleźć w cookie-session i kompresji.

Dodaj komentarz

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