Que signifient réellement middleware et app.use dans Expressjs?

228

Presque toutes les applications Express que je vois ont une app.usedéclaration pour le middleware, mais je n'ai pas trouvé d'explication claire et concise de ce qu'est réellement le middleware et de ce que fait la app.usedéclaration. Même les documents express eux-mêmes sont un peu vagues à ce sujet. Pouvez-vous m'expliquer ces concepts s'il vous plaît?

iZ.
la source
3
question similaire pour référence (tho celui-ci a été créé plus tôt): stackoverflow.com/questions/11321635/…
ericsoco
43
^ Ha! Ces deux questions se réfèrent l'une à l'autre dans les commentaires.
Julian H. Lam
17
C'est donc une référence circulaire.
Steve K
6
Express.js Middleware Demystified Un excellent article de blog sur le sujet. Cela a été copié-collé ici avant, ce qui est du plagiat bien sûr, mais le message d'origine est toujours très utile, donc je laisse un lien ici.
totymedli
1
J'ai écrit un article sur le middleware express.js. Voici le lien: nodexplained.com/blog-detail/2017/12/31/…
shrawan_lakhe

Réponses:

111

middleware

Je suis à mi-chemin de la séparation du concept de middleware dans un nouveau projet.

Le middleware vous permet de définir une pile d'actions que vous devez parcourir. Les serveurs express eux-mêmes sont une pile de middlewares.

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

Ensuite, vous pouvez ajouter des couches à la pile du middleware en appelant .use

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

Une couche dans la pile du middleware est une fonction, qui prend n paramètres (2 pour express, req& res) et une nextfonction.

Le middleware attend de la couche qu'elle effectue des calculs, augmente les paramètres puis appelle next.

Une pile ne fait rien sauf si vous la manipulez. Express gérera la pile chaque fois qu'une requête HTTP entrante est interceptée sur le serveur. Avec le middleware, vous gérez la pile manuellement.

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

Un exemple plus complet:

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

En termes express, vous définissez simplement une pile d'opérations que vous souhaitez que express gère pour chaque requête HTTP entrante.

En termes d'express (plutôt que de connexion), vous avez un middleware global et un middleware spécifique à l'itinéraire. Cela signifie que vous pouvez attacher une pile de middleware à toutes les demandes HTTP entrantes ou la joindre uniquement aux demandes HTTP qui interagissent avec une certaine route.

Exemples avancés d'express et 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); 
});
Raynos
la source
4
Hmm ... le middleware dans ce cas est-il votre propre bibliothèque ou une partie d'express?
iZ.
5
Cool. Je suis toujours un peu confus par la app.use()syntaxe. Quelle est la valeur de retour réelle du middleware et qu'en fait use-il?
iZ.
9
@iZ use l'ajoute à une pile. Ensuite, chaque demande passe par la pile.
Raynos
7
@Raynos, le lien vers votre projet, "middleware", est rompu.
Lee
1
@Raynos mais je vois un middleware toujours utilisé dans Express? qu'est-ce que tu veux dire, c'est nucléaire?
Timo Huovinen
60

Après avoir simplifié les choses, un serveur Web peut être considéré comme une fonction qui accepte une demande et génère une réponse. Donc, si vous affichez un serveur Web en tant que fonction, vous pouvez l'organiser en plusieurs parties et les séparer en fonctions plus petites afin que leur composition soit la fonction d'origine.

Les middlewares sont les petites fonctions que vous pouvez composer avec d'autres et l'avantage évident est que vous pouvez les réutiliser.

Barum Rho
la source
33

J'ajoute une réponse tardive pour ajouter quelque chose qui n'est pas mentionné dans les réponses précédentes.

À présent, il devrait être clair que les fonctions intermédiaires sont exécutées entre la demande du client et la réponse du serveur . Les fonctionnalités middleware les plus courantes nécessaires sont la gestion des erreurs, l'interaction de la base de données, l'obtention d'informations à partir de fichiers statiques ou d'autres ressources. Pour se déplacer sur la pile du middleware, le prochain rappel doit être appelé, vous pouvez le voir dans la fonction de fin de middleware pour passer à l'étape suivante du flux.

Vous pouvez utiliser l' app.useapproche et avoir un flux comme celui-ci :

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

mais vous pouvez également utiliser une autre approche et passer chaque middleware comme arguments de fonction. Voici un exemple tiré du site Web MooTools Nodejs où les logiciels intermédiaires reçoivent les flux Twitter, Github et Blog avant d' responseêtre renvoyés au client. Notez comment les fonctions sont passées comme arguments dans app.get('/', githubEvents, twitter, getLatestBlog, function(req, res){. L'utilisation app.getne sera appelée que pour les requêtes GET, app.usesera appelée pour toutes les requêtes.

// 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
la source
2
Je cherchais une réponse pour savoir si Express.js prend en charge le montage de middleware basé sur l'itinéraire (PAS sur le routeur)? Il semble que vous l'ayez montré dans votre réponse.
Selçuk
Pouvez-vous expliquer votre exemple ci-dessus?, Comment pouvez-vous passer autant de fonctions dans app.get (...) et dans quel ordre sont-elles appelées?
Tanner Summers
2
Salut @TannerSummers, la .get()méthode prend 3 types d'arguments: le premier, le dernier et le milieu. En interne, il détecte s'il y a plus d'arguments que 2 et utilise ceux (ceux du milieu) comme fonctions middleware, en les appelant de gauche à droite.
Sergio
22

Le guide expressjs a une réponse assez soignée à votre question, je vous recommande fortement de lire cela, je poste un court extrait du guide, le guide est assez bon.

Écriture de middleware à utiliser dans les applications Express

Aperçu

Middleware fonctions sont des fonctions qui ont accès à l' objet de demande ( req ), à l' objet de réponse ( res ) et à la fonction suivante du cycle demande-réponse de l'application. La fonction suivante est une fonction du routeur Express qui, lorsqu'elle est invoquée, exécute le middleware succédant au middleware actuel.

Les fonctions middleware peuvent effectuer les tâches suivantes:

  • Exécutez n'importe quel code.
  • Apportez des modifications à la demande et aux objets de réponse.
  • Mettez fin au cycle demande-réponse.
  • Appelez le prochain middleware de la pile.

Si la fonction middleware actuelle ne met pas fin au cycle demande-réponse, elle doit appeler next () pour passer le contrôle à la fonction middleware suivante. Sinon, la demande sera laissée en suspens.

entrez la description de l'image ici

Exemple

Voici un exemple d'une application Express «Hello World» simple. Le reste de cet article va définir et ajouter deux fonctions middleware à l'application: une appelée myLogger qui imprime un simple message de log et une autre appelée requestTime 1 qui affiche l'horodatage de la demande HTTP.

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

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

app.listen(3000)   

Fonction middleware myLogger

Voici un exemple simple d'une fonction middleware appelée «myLogger». Cette fonction imprime simplement «LOGGED» lorsqu'une demande à l'application la traverse. La fonction middleware est affectée à une variable nommée myLogger.

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

Notez l'appel ci-dessus à next () . L'appel de cette fonction appelle la prochaine fonction middleware de l'application. La fonction next () ne fait pas partie de Node.js ou de l'API Express, mais est le troisième argument transmis à la fonction middleware. La fonction next () peut être nommée n'importe quoi, mais par convention, elle est toujours nommée «next». Pour éviter toute confusion, utilisez toujours cette convention.

Pour charger la fonction middleware, appelez app.use () , en spécifiant la fonction middleware. Par exemple, le code suivant charge la fonction middleware myLogger avant la route vers le chemin racine (/).

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)

Chaque fois que l'application reçoit une demande, elle imprime le message «LOGGED» sur le terminal.

L'ordre de chargement du middleware est important: les fonctions middleware qui sont chargées en premier sont également exécutées en premier.

Si myLogger est chargé après la route vers le chemin racine, la demande ne l'atteint jamais et l'application n'imprime pas «LOGGED», car le gestionnaire de route du chemin racine termine le cycle demande-réponse.

La fonction middleware myLogger imprime simplement un message, puis transmet la requête à la fonction middleware suivante de la pile en appelant la fonction next () .


  1. Ce message ne contiendra que le middleware myLogger, pour plus d'informations, vous pouvez consulter le guide expressjs original ici .

Suraj Jain
la source
1
Très belle explication.
Drumbeg
Il est disponible sur le site express ici expressjs.com/en/guide/writing-middleware.html , c'est vraiment bien. Je me demande pourquoi personne ne l'a mentionné jusqu'à présent.
Suraj Jain
2
Joli. C'est l'explication la plus claire que j'ai vue ici et oui, étrange que personne ne l'ait référencée!
Drumbeg
1
Bien expliqué
Rehan Shikkalgar
L'ordre de chargement du middleware est important: les fonctions middleware qui sont chargées en premier sont également exécutées en premier. : Ceci est une note si importante. Aucune autre réponse ne le mentionne. Pour un débutant qui n'a travaillé que sur python, cela est extrêmement important car ces choses n'ont peut-être jamais été rencontrées.
Tessaracter
11

===== Explication très très simple =====

Les middlewares sont souvent utilisés dans le contexte du framework Express.js et sont un concept fondamental pour node.js. En bref, c'est essentiellement une fonction qui a accès aux objets de demande et de réponse de votre application. La façon dont j'aimerais y penser, est une série de «vérifications / pré-écrans» que la demande passe avant d'être traitée par l'application. Par exemple, Middlewares serait un bon moyen de déterminer si la demande est authentifiée avant de passer à l'application et de renvoyer la page de connexion si la demande n'est pas authentifiée ou pour enregistrer chaque demande. De nombreux middlewares tiers sont disponibles qui permettent une variété de fonctionnalités.

Exemple simple de middleware:

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

Le code ci-dessus serait exécuté pour chaque requête qui arriverait et enregistrerait l'url de la requête, la méthode next () permet essentiellement au programme de continuer. Si la fonction next () n'est pas invoquée, le programme n'irait pas plus loin et s'arrêterait lors de l'exécution du middleware.

Un couple de Gotchas Middleware:

  1. L'ordre des middlewares dans votre application est important, car la demande passerait par chacun dans un ordre séquentiel.
  2. Oublier d'appeler la méthode next () dans votre fonction middleware peut interrompre le traitement de votre demande.
  3. Toute modification des objets req et res dans la fonction middleware rendrait la modification disponible pour d'autres parties de l'application qui utilise req et res
Vaibhav Bacchav
la source
1
Merci beaucoup! c'est la meilleure explication à ce jour pour comprendre cela. Une question, je lis du code avec un middleware et il n'appelle pas next()mais return next(). Quelle est la différence?
KansaiRobot
Merci beaucoup pour vos aimables paroles ... nous le faisons next()parce que nous voulons que le prochain middleware soit appelé, je ne pense pas next()ou return next(), devrait faire la différence! Cela dépend quand même du code ...
Vaibhav Bacchav
7

Les middlewares sont des fonctions exécutées au milieu après que l'entrée / la source produit ensuite une sortie qui pourrait être la sortie finale ou pourrait être utilisée par le middleware suivant jusqu'à la fin du cycle.

C'est comme un produit qui passe par une chaîne de montage où il est modifié au fur et à mesure de son achèvement, de son évaluation ou de son rejet.

Un middleware attend une valeur sur laquelle travailler (c'est-à-dire des valeurs de paramètres) et, sur la base d'une logique, le middleware appellera ou non le middleware suivant ou enverra une réponse au client.

Si vous ne pouvez toujours pas saisir le concept de middleware, il est d'une manière similaire aux modèles de décorateur ou de chaîne de commandes.

naz
la source
5

L'intergiciel est un sous-ensemble de fonctions chaînées appelées par la couche de routage Express js avant que le gestionnaire défini par l'utilisateur soit appelé. Les fonctions middleware ont un accès complet aux objets de demande et de réponse et peuvent modifier l'un ou l'autre.

La chaîne du middleware est toujours appelée dans l'ordre exact dans lequel elle a été définie, il est donc essentiel que vous sachiez exactement ce que fait un middleware spécifique.
Une fois la fonction middleware terminée, elle appelle la fonction suivante de la chaîne en invoquant son prochain argument en tant que fonction.
Une fois la chaîne complète exécutée, le gestionnaire de requêtes utilisateur est appelé.

rishabh dev
la source
1

Gardez les choses simples, mec!

Remarque: la réponse est liée aux cas de middlware intégrés ExpressJS, mais il existe différentes définitions et cas d'utilisation des middlewares.

De mon point de vue, le middleware agit comme une fonction utilitaire ou auxiliaire mais son activation et son utilisation sont entièrement facultatives en utilisant le app.use('path', /* define or use builtin middleware */)qui ne veut pas de nous écrire du code pour effectuer des tâches très courantes qui sont nécessaires pour chaque requête HTTP de notre client comme le traitement des cookies, des jetons CSRF et ..., qui sont très communs dans la plupart des applications , le middleware peut donc nous aider à tout faire pour chaque requête HTTP de notre client dans une pile, une séquence ou un ordre d'opérations, puis fournir le résultat du processus comme une seule unité de demande client .

Exemple:

Accepter les demandes des clients et leur répondre en fonction de leurs demandes est la nature de la technologie des serveurs Web.

Imaginez si nous fournissons une réponse avec simplement "Bonjour, monde!" le texte d'une demande GET HTTP vers l'URI racine de notre serveur Web est un scénario très simple et n'a besoin de rien d'autre, mais à la place si nous vérifions l'utilisateur actuellement connecté et répondons ensuite par "Bonjour, Nom d'utilisateur!" a besoin de quelque chose de plus que d'habitude dans ce cas, nous avons besoin d'un middleware pour traiter toutes les métadonnées de la demande du client et nous fournir les informations d'identification extraites de la demande du client, puis en fonction de ces informations, nous pouvons identifier de manière unique notre utilisateur actuel et il est possible de lui répondre / elle avec quelques données connexes.

J'espère que cela aidera quelqu'un!

MRN
la source
-1

En termes très basiques, si je veux l'expliquer comme ça, j'apprends cela du cours express de traversymedia youtube channel express.
ok donc le middleware est une fonction qui s'exécute après avoir appelé votre itinéraire comme ceci.

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

app.use(logger);

Cette fonction de journalisation s'exécute à chaque fois que vous actualisez votre page, ce qui signifie que vous pouvez y écrire tout ce que vous deviez faire après que votre page a été rendue tout appel api d'opération, réinitialiser les choses essentiellement n'importe quoi. et mettez ce middleware avant votre ordre de fonction de routage de middleware est vraiment important ou il ne fonctionne pas

Akshay Vinchurkar
la source