Co w rzeczywistości oznacza oprogramowanie pośrednie i app.use w Expressjs?

228

Prawie każda aplikacja Express, którą widzę, ma app.useinstrukcję dla oprogramowania pośredniego, ale nie znalazłem jasnego, zwięzłego wyjaśnienia, czym tak naprawdę jest oprogramowanie pośrednie i co app.userobi instrukcja. Nawet same ekspresowe dokumenty są nieco niejasne. Czy możesz mi wyjaśnić te pojęcia?

iZ.
źródło
3
podobne pytanie w celach informacyjnych (chociaż to zostało utworzone wcześniej): stackoverflow.com/questions/11321635/…
ericsoco
43
^ Ha! Te dwa pytania odnoszą się do siebie w komentarzach.
Julian H. Lam
17
Więc to jest Cirular Reference.
Steve K
6
Express.js Middleware Demystified Świetny post na blogu na ten temat. To zostało wcześniej wklejone tutaj, co jest oczywiście plagiatem, ale oryginalny post jest nadal bardzo pomocny, więc zostawiam tutaj link.
totymedli
1
Napisałem artykuł na temat oprogramowania pośredniego express.js. Oto link: nodexplained.com/blog-detail/2017/12/31/…
shrawan_lakhe 10.01.2018

Odpowiedzi:

111

oprogramowanie pośrednie

Jestem w połowie drogi do rozdzielenia koncepcji oprogramowania pośredniego w nowym projekcie.

Oprogramowanie pośrednie pozwala zdefiniować stos działań, przez które należy przejść. Same serwery ekspresowe to stos oprogramowania pośredniego.

// express
var app = express();
// middleware
var stack = middleware();

Następnie możesz dodać warstwy do stosu oprogramowania pośredniego, wywołując .use

// express
app.use(express.static(..));
// middleware
stack.use(function(data, next) {
  next();
});

Warstwa w stosie oprogramowania pośredniego to funkcja, która przyjmuje n parametrów (2 dla express, req& res) i nextfunkcję.

Oprogramowanie pośrednie oczekuje, że warstwa wykona pewne obliczenia, zwiększy parametry, a następnie wywoła next.

Stos nic nie robi, chyba że sobie z tym poradzisz. Express obsłuży stos za każdym razem, gdy przychodzące żądanie HTTP zostanie przechwycone na serwerze. Dzięki oprogramowaniu pośredniczemu możesz ręcznie obsługiwać stos.

// express, you need to do nothing
// middleware
stack.handle(someData);

Bardziej kompletny przykład:

var middleware = require("../src/middleware.js");

var stack = middleware(function(data, next) {
    data.foo = data.data*2;
    next();
}, function(data, next) {
    setTimeout(function() {
        data.async = true;
        next();
    }, 100)
}, function(data) {
    console.log(data);
});

stack.handle({
    "data": 42
})

W kategoriach ekspresowych po prostu definiujesz stos operacji, które ekspres ma obsługiwać dla każdego przychodzącego żądania HTTP.

Jeśli chodzi o ekspresowe (zamiast łączenia), masz globalne oprogramowanie pośrednie i konkretne oprogramowanie pośredniczące dla trasy. Oznacza to, że możesz dołączyć stos oprogramowania pośredniego do każdego przychodzącego żądania HTTP lub dołączyć go tylko do żądań HTTP, które wchodzą w interakcję z określoną trasą.

Zaawansowane przykłady ekspresowego i oprogramowania pośredniego:

// middleware 

var stack = middleware(function(req, res, next) {
    users.getAll(function(err, users) {
        if (err) next(err);
        req.users = users;
        next();  
    });
}, function(req, res, next) {
    posts.getAll(function(err, posts) {
        if (err) next(err);
        req.posts = posts;
        next();
    })
}, function(req, res, next) {
    req.posts.forEach(function(post) {
        post.user = req.users[post.userId];
    });

    res.render("blog/posts", {
        "posts": req.posts
    });
});

var app = express.createServer();

app.get("/posts", function(req, res) {
   stack.handle(req, res); 
});

// express

var app = express.createServer();

app.get("/posts", [
    function(req, res, next) {
        users.getAll(function(err, users) {
            if (err) next(err);
            req.users = users;
            next();  
        });
    }, function(req, res, next) {
        posts.getAll(function(err, posts) {
            if (err) next(err);
            req.posts = posts;
            next();
        })
    }, function(req, res, next) {
        req.posts.forEach(function(post) {
            post.user = req.users[post.userId];
        });

        res.render("blog/posts", {
            "posts": req.posts
        });
    }
], function(req, res) {
   stack.handle(req, res); 
});
Raynos
źródło
4
Hmm ... czy oprogramowanie pośrednie w tym przypadku jest Twoją własną biblioteką czy częścią ekspresu?
iZ.
5
Chłodny. Nadal jestem trochę zdezorientowany app.use()składnią. Jaka jest rzeczywista wartość zwracana oprogramowania pośredniego i co z tym usezrobić?
iZ.
9
@ iZ use dodaje go do stosu. Następnie każde żądanie przechodzi przez stos.
Raynos,
7
@Raynos, link do twojego projektu „oprogramowanie pośrednie” jest uszkodzony.
Lee
1
@Raynos, ale widzę, że oprogramowanie pośrednie jest nadal używane w Expressie? co masz na myśli, że to jest nuk
Timo Huovinen
60

Po uproszczeniu rzeczy, serwer WWW może być postrzegany jako funkcja, która przyjmuje żądanie i wysyła odpowiedź. Jeśli więc widzisz serwer WWW jako funkcję, możesz zorganizować go w kilka części i podzielić na mniejsze funkcje, aby ich skład był oryginalną funkcją.

Programy pośrednie to mniejsze funkcje, które można komponować z innymi, a oczywistą zaletą jest to, że można z nich ponownie korzystać.

Barum Rho
źródło
33

Dodaję późną odpowiedź, aby dodać coś niewymienionego w poprzednich odpowiedziach.

Do tej pory powinno być jasne, że oprogramowanie pośredniczące jest / są funkcjami uruchomionymi między żądaniem klienta a odpowiedzią serwera . Najbardziej potrzebne funkcje oprogramowania pośredniego to zarządzanie błędami, interakcja z bazą danych, uzyskiwanie informacji z plików statycznych lub innych zasobów. Aby przejść na stos oprogramowania pośredniego, należy wywołać następne wywołanie zwrotne, można to zobaczyć na końcu funkcji oprogramowania pośredniego, aby przejść do następnego kroku w przepływie.

Można użyć app.usepodejścia i posiada przepływ takiego :

var express = require('express'),
    app = express.createServer(),                                                                                                                                                 
    port = 1337;

function middleHandler(req, res, next) {
    console.log("execute middle ware");
    next();
}

app.use(function (req, res, next) {
    console.log("first middle ware");                                                                                                             
    next();
});

app.use(function (req, res, next) {
    console.log("second middle ware");                                                                                                             
    next();
});

app.get('/', middleHandler, function (req, res) {
    console.log("end middleware function");
    res.send("page render finished");
});

app.listen(port);
console.log('start server');

ale możesz także użyć innego podejścia i przekazać każde oprogramowanie pośrednie jako argumenty funkcji. Oto przykład ze strony MooTools Nodejs, gdzie oprogramowanie pośredniczące pobiera Twitter, Github i Blog, zanim responsezostanie odesłane z powrotem do klienta. Zwróć uwagę, jak funkcje są przekazywane jako argumenty w app.get('/', githubEvents, twitter, getLatestBlog, function(req, res){. Użycie app.getbędzie wywoływane tylko dla żądań GET, app.usebędzie wywoływane dla wszystkich żądań.

// github, twitter & blog feeds
var githubEvents = require('./middleware/githubEvents')({
    org: 'mootools'
});
var twitter = require('./middleware/twitter')();
var blogData = require('./blog/data');
function getLatestBlog(req, res, next){
    blogData.get(function(err, blog) {
        if (err) next(err);
        res.locals.lastBlogPost = blog.posts[0];
        next();
    });
}

// home
app.get('/', githubEvents, twitter, getLatestBlog, function(req, res){
    res.render('index', {
        title: 'MooTools',
        site: 'mootools',
        lastBlogPost: res.locals.lastBlogPost,
        tweetFeed: res.locals.twitter
    });
});
Sergio
źródło
2
Szukałem odpowiedzi na pytanie, czy Express.js obsługuje montowanie oprogramowania pośredniego w oparciu o trasy (NIE w oparciu o router)? Wygląda na to, że pokazałeś to w swojej odpowiedzi.
Selçuk
Czy możesz wyjaśnić powyższy przykład ?, w jaki sposób możesz przekazać tak wiele funkcji do app.get (...) i w jakiej kolejności są one nazywane?
Tanner Summers
2
Cześć @TannerSummers, .get()metoda przyjmuje 3 typy argumentów: pierwszy, ostatni i środkowy. Wewnętrznie wykrywa, czy argumentów jest więcej niż 2, i używa tych (środkowych) jako funkcji oprogramowania pośredniego, wywołując je od lewej do prawej.
Sergio
22

Przewodnik expressjs ma całkiem fajną odpowiedź na twoje pytanie, gorąco polecam przeczytanie go, zamieszczam krótki fragment przewodnika, przewodnik jest całkiem dobry.

Pisanie oprogramowania pośredniego do użytku w aplikacjach Express

Przegląd

Funkcje oprogramowania pośredniego to funkcje, które mają dostęp do obiektu żądania ( req ), obiektu odpowiedzi ( res ) i następnej funkcji w cyklu żądania i odpowiedzi aplikacji. Następna funkcja to funkcja w routerze Express, która po wywołaniu uruchamia oprogramowanie pośrednie po bieżącym oprogramowaniu pośrednim.

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

  • Wykonaj dowolny kod.
  • Wprowadź zmiany w żądaniu i obiektach odpowiedzi.
  • Zakończ cykl żądanie-odpowiedź.
  • Wywołaj następne oprogramowanie pośrednie na stosie.

Jeśli bieżąca funkcja oprogramowania pośredniego nie kończy cyklu żądanie-odpowiedź, musi wywołać next () w celu przekazania kontroli do następnej funkcji oprogramowania pośredniego. W przeciwnym razie żądanie pozostanie zawieszone.

wprowadź opis zdjęcia tutaj

Przykład

Oto przykład prostej aplikacji ekspresowej „Hello World”. Pozostała część tego artykułu określi i doda do aplikacji dwie funkcje oprogramowania pośredniego: jedną o nazwie myLogger, która drukuje prosty komunikat dziennika, a drugą o nazwie requestTime 1, która wyświetla znacznik czasu żądania HTTP.

var express = require('express')
var app = express()

app.get('/', function (req, res) {
  res.send('Hello World!')
})

app.listen(3000)   

Funkcja oprogramowania pośredniego myLogger

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

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

Zwróć uwagę na wywołanie powyżej do next () . Wywołanie tej funkcji wywołuje następną funkcję oprogramowania pośredniego w aplikacji. Funkcja next () nie jest częścią Node.js ani Express API, ale jest trzecim argumentem przekazywanym do funkcji oprogramowania pośredniego. Funkcja next () może mieć dowolną nazwę, ale zgodnie z konwencją zawsze nosi nazwę „next”. Aby uniknąć zamieszania, zawsze używaj tej konwencji.

Aby załadować funkcję oprogramowania pośredniego, wywołaj app.use () , określając funkcję oprogramowania pośredniego. Na przykład poniższy kod ładuje funkcję oprogramowania pośredniego 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 otrzyma żądanie, drukuje komunikat „ZALOGOWANY” na terminalu.

Kolejność ładowania oprogramowania pośredniego jest ważna: najpierw uruchamiane są funkcje oprogramowania pośredniego, które są ładowane jako pierwsze.

Jeśli myLogger jest ładowany po trasie do ścieżki głównej, żądanie nigdy go nie osiąga, a aplikacja nie drukuje komunikatu „ZALOGOWANO”, ponieważ procedura obsługi trasy głównej ścieżki kończy cykl żądanie-odpowiedź.

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


  1. Ten post będzie zawierał tylko oprogramowanie pośrednie myLogger, w celu uzyskania dalszych informacji możesz przejść do oryginalnego przewodnika expressjs tutaj .

Suraj Jain
źródło
1
Bardzo miłe wytłumaczenie.
Drumbeg
Jest dostępny na ekspresowej stronie tutaj expressjs.com/en/guide/writing-middleware.html , jest naprawdę dobry. Zastanawiam się, dlaczego do tej pory nikt o tym nie wspominał.
Suraj Jain,
2
Niezłe. To najjaśniejsze wytłumaczenie, jakie tu widziałem i tak, dziwne, że nikt się do niego nie odniósł!
Drumbeg
1
Ładnie wyjaśnione
Rehan Shikkalgar
Kolejność ładowania oprogramowania pośredniego jest ważna: najpierw uruchamiane są funkcje oprogramowania pośredniego, które są ładowane jako pierwsze. : To bardzo ważna uwaga. Żadna inna odpowiedź nie wspomina o tym. Dla początkującego, który pracował tylko nad Pythonem, jest to niezwykle ważne, ponieważ te rzeczy mogły się nigdy nie spotkać.
Tessaracter,
11

===== Bardzo bardzo proste wyjaśnienie =====

Middlewares są często używane w kontekście frameworka Express.js i są podstawową koncepcją dla node.js. Krótko mówiąc, jest to w zasadzie funkcja, która ma dostęp do obiektów żądania i odpowiedzi aplikacji. Sposób, w jaki chciałbym o tym myśleć, to seria „kontroli / wstępnych ekranów”, przez które przechodzi żądanie, zanim aplikacja obsłuży je. Na przykład, Middlewares dobrze byłoby ustalić, czy żądanie jest uwierzytelnione przed przejściem do aplikacji i zwrócić stronę logowania, jeśli żądanie nie jest uwierzytelnione, lub do logowania każdego żądania. Dostępnych jest wiele programów pośredniczących innych firm, które umożliwiają różnorodne funkcje.

Prosty przykład oprogramowania pośredniego:

var app = express();
app.use(function(req,res,next)){
    console.log("Request URL - "req.url);
    next();
}

Powyższy kod byłby wykonywany dla każdego przychodzącego żądania i rejestrowałby adres URL żądania, metoda next () zasadniczo pozwala programowi kontynuować. Jeśli funkcja next () nie zostanie wywołana, program nie będzie kontynuował działania i zatrzyma się przy wykonywaniu oprogramowania pośredniego.

Kilka Middleware Gotchas:

  1. Kolejność oprogramowania pośredniego w aplikacji ma znaczenie, ponieważ żądanie przechodzi przez każdy w kolejności sekwencyjnej.
  2. Zapomnienie o wywołaniu metody next () w funkcji oprogramowania pośredniego może zatrzymać przetwarzanie żądania.
  3. Każda zmiana obiektów wymagań i zmian w funkcji oprogramowania pośredniego spowoduje, że zmiana będzie dostępna dla innych części aplikacji korzystających z wymagań i wymagań
Vaibhav Bacchav
źródło
1
Dziękuję Ci bardzo! jest to jak dotąd najlepsze wytłumaczenie, aby to zrozumieć. Pytanie, czytam kod z oprogramowaniem pośrednim i nie wywołuje, next()ale return next(). Jaka jest różnica?
KansaiRobot
Wielkie dzięki, przyjacielu za miłe słowa ... robimy to, next()ponieważ chcemy, aby następne wywołanie oprogramowania pośredniego było wywoływane, nie sądzę next()lub return next()powinno to zrobić jakąkolwiek różnicę! Nadal zależy to od kodu ...
Vaibhav Bacchav
7

Programy pośrednie są funkcjami wykonywanymi w środku po wejściu / źródle, a następnie generują dane wyjściowe, które mogą być końcowymi danymi wyjściowymi lub mogą być używane przez następne oprogramowanie pośrednie do momentu zakończenia cyklu.

To jest jak produkt, który przechodzi przez linię montażową, gdzie jest modyfikowany w miarę przesuwania się, aż zostanie ukończony, oceniony lub odrzucony.

Oprogramowanie pośrednie oczekuje, że pewna wartość będzie działać (tj. Wartości parametrów) i na podstawie pewnej logiki oprogramowanie pośredniczące wywoła lub nie wywoła następnego oprogramowania pośredniego lub odeśle odpowiedź do klienta.

Jeśli nadal nie możesz pojąć koncepcji oprogramowania pośredniego, jest on podobny do Dekoratora lub Łańcucha poleceń.

naz
źródło
5

Oprogramowanie pośrednie to podzbiór funkcji łańcuchowych wywoływanych przez warstwę routingu Express js przed wywołaniem procedury obsługi zdefiniowanej przez użytkownika. Funkcje oprogramowania pośredniego mają pełny dostęp do obiektów żądania i odpowiedzi i mogą modyfikować dowolny z nich.

Łańcuch oprogramowania pośredniego jest zawsze wywoływany w dokładnie takiej kolejności, w jakiej został zdefiniowany, dlatego bardzo ważne jest, aby dokładnie wiedzieć, co robi konkretny element oprogramowania pośredniego.
Po zakończeniu funkcji oprogramowania pośredniego wywołuje następną funkcję w łańcuchu, wywołując jej następny argument jako funkcję.
Po wykonaniu całego łańcucha wywoływana jest procedura obsługi żądań użytkownika.

rishabh dev
źródło
1

Uprość to, stary!

Uwaga: odpowiedź dotyczy przypadków wbudowanego oprogramowania pośredniego ExpressJS, jednak istnieją różne definicje i przypadki użycia oprogramowania pośredniego.

Z mojego punktu widzenia, middleware działa jako funkcji użytkowych lub pomocnika, ale jego uruchomienie i stosowanie jest całkowicie opcjonalne za pomocą przycisków app.use('path', /* define or use builtin middleware */), które nie chce od nas napisać trochę kodu do wykonywania bardzo typowych zadań, które są potrzebne dla każdego żądania HTTP naszego klienta takie jak przetwarzanie plików cookie, tokenów CSRF i ..., które są bardzo powszechne w większości aplikacji, więc oprogramowanie pośrednie może pomóc nam to zrobić dla każdego żądania HTTP naszego klienta w stosie, sekwencji lub kolejności operacji, a następnie dostarczyć wynik procesu jako pojedyncza jednostka żądania klienta .

Przykład:

Przyjmowanie żądań klientów i udzielanie odpowiedzi zwrotnych zgodnie z ich żądaniami jest naturą technologii serwerów sieciowych.

Wyobraź sobie, że odpowiadamy tylko „Witaj, świecie!” tekst żądania GET HTTP do głównego identyfikatora URI naszego serwera WWW jest bardzo prostym scenariuszem i nie wymaga niczego innego, ale zamiast tego sprawdzamy aktualnie zalogowanego użytkownika, a następnie odpowiadamy „Witaj, nazwa użytkownika!” potrzebuje czegoś więcej niż zwykle w tym przypadku potrzebujemy oprogramowania pośredniego do przetworzenia wszystkich metadanych żądania klienta i dostarczenia nam informacji identyfikacyjnych pobranych z żądania klienta, a następnie zgodnie z tymi informacjami możemy jednoznacznie zidentyfikować naszego bieżącego użytkownika i można na nie odpowiedzieć z jej powiązanymi danymi.

Mam nadzieję, że komuś pomoże!

MNR
źródło
-1

Mówiąc bardzo prosto, jeśli chcę to wyjaśnić w ten sposób, uczę się tego z traversymedia youtube channel express express crash crash.
ok, więc middleware to funkcja, która jest wykonywana po wykonaniu połączenia w taki sposób.

var logger = function(req, res, next){
   console.log('logging...');
   next();
}

app.use(logger);

Ta funkcja rejestratora jest wykonywana za każdym razem, gdy odświeżasz stronę, co oznacza, że ​​możesz napisać w niej wszystko, co trzeba zrobić po wyrenderowaniu strony przez dowolne wywołanie interfejsu API, zresetować wszystko w zasadzie wszystko. i umieść to oprogramowanie pośrednie, zanim kolejność oprogramowania pośredniego funkcji trasy jest naprawdę ważna lub nie działa

Akshay Vinchurkar
źródło