Cosa significano middleware e app.use in Expressjs?


228

Quasi tutte le app Express che vedo hanno una app.usedichiarazione per il middleware ma non ho trovato una spiegazione chiara e concisa di cosa sia realmente il middleware e di cosa app.usestia facendo la dichiarazione. Anche gli stessi documenti espressi sono un po 'vaghi su questo. Puoi spiegarmi questi concetti per favore?


3
domanda simile per riferimento (tho questo è stato creato in precedenza): stackoverflow.com/questions/11321635/...
ericsoco

43
^ Ah! Queste due domande si riferiscono reciprocamente nei commenti.
Julian H. Lam,

17
Quindi è un riferimento circolare.
Steve K,

6
Express.js Middleware Demysified Un ottimo post sul blog sull'argomento. Questo è stato incollato qui prima, il che è ovviamente plagio, ma il post originale è ancora molto utile, quindi lascio un link qui.
totymedli,

1
Ho scritto un articolo sul middleware express.js. Ecco il link: nodexplained.com/blog-detail/2017/12/31/…
shrawan_lakhe

Risposte:


111

middleware

Sono a metà strada nel separare il concetto di middleware in un nuovo progetto.

Il middleware consente di definire una serie di azioni da attraversare. I server Express stessi sono una pila di software.

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

Quindi è possibile aggiungere layer allo stack del middleware chiamando .use

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

Un livello nello stack del middleware è una funzione, che accetta n parametri (2 per express, req& res) e una nextfunzione.

Il middleware prevede che il layer esegua alcuni calcoli, aumenti i parametri e quindi chiami next.

Uno stack non fa nulla a meno che tu non lo gestisca. Express gestirà lo stack ogni volta che una richiesta HTTP in arrivo viene catturata sul server. Con il middleware gestisci lo stack manualmente.

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

Un esempio più completo:

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
})

In termini espressivi è sufficiente definire una serie di operazioni che si desidera che express gestisca per ogni richiesta HTTP in arrivo.

In termini di express (piuttosto che di connessione) hai un middleware globale e instrada middleware specifico. Ciò significa che è possibile collegare uno stack di middleware a tutte le richieste HTTP in entrata o collegarlo solo a richieste HTTP che interagiscono con una determinata route.

Esempi avanzati di express e middleware:

// 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); 
});

4
Hmm ... il middleware in questo caso è la tua libreria o parte di express?
iZ.

5
Freddo. Sono ancora un po 'confuso dalla app.use()sintassi. Qual è il valore di ritorno effettivo del middleware e cosa ne fa use?
iZ.

9
@iZ use lo aggiunge a uno stack. Quindi ogni singola richiesta passa attraverso lo stack.
Raynos,

7
@Raynos, il link al tuo progetto, "middleware", è interrotto.
Lee,

1
@Raynos ma vedo che il middleware è ancora utilizzato in Express? cosa vuoi dire che è nuked?
Timo Huovinen,

60

Dopo aver semplificato le cose, un web server può essere visto come una funzione che accetta una richiesta e genera una risposta. Quindi se visualizzi un web server come una funzione, potresti organizzarlo in più pezzi e separarli in funzioni più piccole in modo che la loro composizione sia la funzione originale.

I middleware sono le funzioni più piccole che puoi comporre con gli altri e l'ovvio vantaggio è che puoi riutilizzarle.


33

Aggiungo una risposta in ritardo per aggiungere qualcosa non menzionato nelle risposte precedenti.

Ormai dovrebbe essere chiaro che il middleware è / sono funzioni eseguite tra la richiesta client e la risposta del server . Le funzionalità middleware più comuni necessarie sono la gestione degli errori, l'interazione del database, l'ottenimento di informazioni da file statici o altre risorse. Per passare allo stack del middleware è necessario chiamare il callback successivo, è possibile vederlo alla fine della funzione middleware per passare al passaggio successivo nel flusso.

Puoi usare l' app.useapproccio e avere un flusso come questo :

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');

ma puoi anche usare un altro approccio e passare ciascun middleware come argomenti di funzione. Ecco un esempio dal sito Web MooTools Nodejs in cui il midleware ottiene il flusso di Twitter, Github e Blog prima che responsevenga inviato al client. Nota come le funzioni vengono passate come argomenti in app.get('/', githubEvents, twitter, getLatestBlog, function(req, res){. L'utilizzo app.getverrà chiamato solo per le richieste GET, app.useverrà chiamato per tutte le richieste.

// 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
    });
});

2
Stavo cercando una risposta per sapere se Express.js supporta il montaggio del middleware basato sul percorso (NON basato sul router)? Sembra che tu l'abbia mostrato nella tua risposta.
Selçuk,

Puoi spiegare il tuo esempio sopra? Come puoi passare così tante funzioni in app.get (...) e quale ordine vengono chiamati?
Tanner Summers,

2
Ciao @TannerSummers, il .get()metodo accetta 3 tipi di argomenti: il primo, l'ultimo e il medio. Internamente rileva se ci sono più argomenti di 2 e li usa (quelli di mezzo) come funzioni di middleware, chiamandoli da sinistra a destra.
Sergio,

22

La guida di expressjs ha una risposta abbastanza chiara alla tua domanda, ti consiglio vivamente di leggerlo, sto pubblicando un breve frammento della guida, la guida è abbastanza buona.

Scrittura di middleware da utilizzare nelle app Express

Panoramica

Le funzioni del middleware sono funzioni che hanno accesso all'oggetto richiesta ( req ), all'oggetto risposta ( res ) e alla funzione successiva nel ciclo richiesta-risposta dell'applicazione. La funzione successiva è una funzione nel router Express che, se richiamata, esegue il middleware succedendo al middleware corrente.

Le funzioni del middleware possono eseguire le seguenti attività:

  • Esegui qualsiasi codice.
  • Apporta modifiche alla richiesta e agli oggetti risposta.
  • Termina il ciclo richiesta-risposta.
  • Chiama il middleware successivo nello stack.

Se la funzione middleware corrente non termina il ciclo richiesta-risposta, deve chiamare next () per passare il controllo alla funzione middleware successiva. In caso contrario, la richiesta verrà lasciata in sospeso.

inserisci qui la descrizione dell'immagine

Esempio

Ecco un esempio di una semplice applicazione Express "Hello World". Il resto di questo articolo definirà e aggiungerà due funzioni middleware all'applicazione: una chiamata myLogger che stampa un semplice messaggio di registro e un'altra chiamata requestTime 1 che mostra il timestamp della richiesta HTTP.

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

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

app.listen(3000)   

Funzione middleware myLogger

Ecco un semplice esempio di una funzione middleware chiamata "myLogger". Questa funzione stampa semplicemente "LOGGED" quando passa una richiesta all'app. La funzione middleware è assegnata a una variabile denominata myLogger.

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

Notare la chiamata sopra a next () . La chiamata a questa funzione richiama la funzione middleware successiva nell'app. La funzione next () non fa parte di Node.js o Express API, ma è il terzo argomento che viene passato alla funzione middleware. La funzione next () può essere nominata in qualsiasi modo, ma per convenzione viene sempre chiamata "next". Per evitare confusione, utilizzare sempre questa convenzione.

Per caricare la funzione middleware, chiamare app.use () , specificando la funzione middleware. Ad esempio, il codice seguente carica la funzione middleware myLogger prima del percorso sul percorso principale (/).

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)

Ogni volta che l'app riceve una richiesta, stampa il messaggio "LOGGED" sul terminale.

L'ordine di caricamento del middleware è importante: anche le funzioni del middleware caricate per prime vengono eseguite per prime.

Se myLogger viene caricato dopo il percorso verso il percorso principale, la richiesta non lo raggiunge mai e l'app non stampa "LOGGED", poiché il gestore del percorso del percorso principale termina il ciclo richiesta-risposta.

La funzione middleware myLogger stampa semplicemente un messaggio, quindi passa la richiesta alla funzione middleware successiva nello stack chiamando la funzione next () .


  1. Questo post conterrà solo il middleware myLogger, per ulteriori post puoi consultare la guida expressjs originale qui .


1
Spiegazione molto bella.
Drumbeg,

È disponibile sul sito express qui expressjs.com/en/guide/writing-middleware.html , è davvero buono. Mi chiedo perché nessuno lo abbia menzionato finora.
Suraj Jain,

2
Ben fatto. È la spiegazione più chiara che ho visto qui e sì, strano che nessuno l'ha fatto riferimento!
Drumbeg,

1
Ben spiegato
Rehan Shikkalgar

L'ordine di caricamento del middleware è importante: anche le funzioni del middleware caricate per prime vengono eseguite per prime. : Questa è una nota così importante. Nessun'altra risposta menziona questo. Per un principiante che ha lavorato solo su Python questo è estremamente importante in quanto queste cose potrebbero non essere mai state incontrate.
Tessaracter,

11

===== Spiegazione molto molto semplice =====

I middleware sono spesso utilizzati nel contesto del framework Express.js e sono un concetto fondamentale per node.js. In poche parole, è fondamentalmente una funzione che ha accesso agli oggetti richiesta e risposta dell'applicazione. Il modo in cui mi piacerebbe pensarci è una serie di "controlli / pre-schermate" che la richiesta passa prima che venga gestita dall'applicazione. Ad esempio, Middlewares sarebbe una buona soluzione per determinare se la richiesta è autenticata prima di procedere all'applicazione e restituire la pagina di accesso se la richiesta non è autenticata o per la registrazione di ogni richiesta. Sono disponibili molti middleware di terze parti che consentono una varietà di funzionalità.

Esempio di Middleware semplice:

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

Il codice sopra sarebbe eseguito per ogni richiesta che arriva e registrerebbe l'URL della richiesta, il metodo next () essenzialmente consente al programma di continuare. Se la funzione next () non viene invocata, il programma non procederà oltre e si fermerebbe all'esecuzione del middleware.

Un paio di Gotcha di middleware:

  1. L'ordine dei middleware nella tua applicazione è importante, poiché la richiesta passerebbe attraverso ognuno in un ordine sequenziale.
  2. Dimenticare di chiamare il metodo next () nella funzione middleware può interrompere l'elaborazione della richiesta.
  3. Qualsiasi modifica agli oggetti req e res nella funzione middleware, renderebbe la modifica disponibile ad altre parti dell'applicazione che utilizza req e res

1
Grazie mille! questa è la migliore spiegazione finora per capirlo. Una domanda, sto leggendo del codice con middleware e non chiama next()ma return next(). Qual è la differenza?
KansaiRobot,

Grazie mille amico per le belle parole ... lo facciamo next()perché vogliamo che il prossimo middleware venga chiamato, non credo next()o return next(), dovremmo fare la differenza! Tuttavia dipende da quale sia il codice ...
Vaibhav Bacchav,

7

I middleware sono funzioni eseguite nel mezzo dopo che input / source produce quindi un output che potrebbe essere l'output finale o potrebbe essere utilizzato dal middleware successivo fino al completamento del ciclo.

È come un prodotto che attraversa una catena di montaggio in cui viene modificato man mano che si muove fino a quando non viene completato, valutato o rifiutato.

Un middleware si aspetta che funzioni un po 'di valore (ovvero i valori dei parametri) e basato su una logica che il middleware chiamerà o non chiamerà il middleware successivo o invierà una risposta al client.

Se non riesci ancora a cogliere il concetto di middleware, è in un modo simile ai modelli di comando Decoratore o Catena di comandi.


5

Il middleware è un sottoinsieme di funzioni concatenate chiamate dal layer di routing Express js prima che venga richiamato il gestore definito dall'utente. Le funzioni del middleware hanno pieno accesso agli oggetti richiesta e risposta e possono modificarli.

La catena del middleware viene sempre chiamata nell'ordine esatto in cui è stata definita, quindi è essenziale che tu sappia esattamente cosa sta facendo un determinato middleware.
Una volta terminata una funzione middleware, chiama la funzione successiva nella catena invocando il suo argomento successivo come funzione.
Dopo l'esecuzione della catena completa, viene chiamato il gestore richieste utente.


1

Mantieni le cose semplici, amico!

Nota: la risposta è correlata ai casi di middlware incorporati in ExpressJS, tuttavia esistono definizioni e casi d'uso diversi dei middleware.

Dal mio punto di vista, il middleware agisce come funzioni di utilità o di supporto, ma la sua attivazione e utilizzo è completamente facoltativo utilizzando app.use('path', /* define or use builtin middleware */)ciò che non vuole da noi scrivere un codice per svolgere attività molto comuni che sono necessarie per ogni richiesta HTTP del nostro client come l'elaborazione di cookie, token CSRF e ..., che sono molto comuni nella maggior parte delle applicazioni, quindi il middleware può aiutarci a fare tutto ciò per ogni richiesta HTTP del nostro cliente in alcuni stack, sequenze o ordini di operazioni, quindi fornire il risultato del processo come una singola unità di richiesta del cliente .

Esempio:

Accettare le richieste dei clienti e fornire loro risposte in base alle loro richieste è la natura della tecnologia del web server.

Immagina se stiamo fornendo una risposta solo con "Ciao, mondo!" il testo per ottenere una richiesta HTTP all'URI principale del nostro server web è uno scenario molto semplice e non ha bisogno di nient'altro, ma invece se stiamo controllando l'utente attualmente connesso e quindi rispondendo con "Ciao, nome utente!" ha bisogno di qualcosa di più del solito in questo caso abbiamo bisogno di un middleware per elaborare tutti i metadati di richiesta del client e fornirci le informazioni di identificazione acquisite dalla richiesta del client, quindi in base a tali informazioni possiamo identificare in modo univoco il nostro utente corrente ed è possibile rispondere a lui con alcuni dati correlati.

Spero che possa aiutare qualcuno!


-1

In parole povere, se voglio spiegarlo in questo modo, imparo questo dal corso di crash express di traversymedia youtube channel.
ok quindi middleware è una funzione che viene eseguita dopo aver effettuato una chiamata al percorso in questo modo.

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

app.use(logger);

Questa funzione di logger viene eseguita ogni volta che aggiorni la tua pagina, il che significa che puoi scrivere qualsiasi cosa in essa che hai richiesto di fare dopo che la tua pagina ha eseguito il rendering di qualsiasi operazione api call, resetta praticamente praticamente qualsiasi cosa. e metti questo middleware prima che l'ordine delle funzioni di route del middleware sia davvero importante o non funzioni

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.