2016-01-18 3 views
1

J'ai écrit un middleware dans express.js/node.js qui vérifie la session et s'il trouve un ID utilisateur, affiche le menu de l'utilisateur, ou bien, le menu par défaut.Pourquoi mon middleware est-il exécuté deux fois?

Chaque page demande les chèques d'un identifiant et récupère les données utilisateur de la base de données (id, nom, catégorie, etc.)

Voici le middleware:

module.exports = function(req,res,next){ 
    console.log("INSIDE SESSION HANDLER"); 

    if(!req.session.uid) return next(); 
    else{ 
     User.get(uid, function(user){ 
      if (!user) {return next(err);} 
      else{ 
       req.user = res.locals.user = user; 
       next(); 
      } 
     }) 
    } 
} 

Ensuite, vérifie EJS habitants et si il y a un ID, montre le menu de l'utilisateur.

Je chargais une page de test que je n'ai pas utilisé la bibliothèque socket.io, mais j'ai oublié de supprimer la ligne <script src="/socket.io/socket.io.js"></script>.

<!DOCTYPE html> 
<html> 
    <head> 
    <title><%= title %> , <%= settings.title %></title> 
    <link rel='stylesheet' href='/stylesheets/style.css' /> 
    <script src="/socket.io/socket.io.js"></script>//<== SHOULD DELETE THIS 
    <h1>Login</h1> 
     <%include menu%> //<== USES EJS TO CHECK LOCALS AND SHOW DEFAULT OR USER MENU 
    </head> 
    <body> 

Lorsque la ligne script src n'a pas été là, le middleware exécutait une fois (vu console.log("INSIDE SESSION HANDLER"); une seule fois).

Lorsque la ligne script src était là, donnait apparemment une erreur 404, mais le middleware était en cours d'exécution deux fois (vu le console.log("INSIDE SESSION HANDLER"); deux fois).

est ici la sortie de console.log:

INSIDE SESSION HANDLER 
GET/304 66ms //page 
GET /stylesheets/style.css 304 11ms 
INSIDE SESSION HANDLER //again 
GET /socket.io/socket.io.js 404 28ms - 1.04kb 
GET /multimedia/01.jpg 304 4ms //images... 
GET /multimedia/02.jpg 304 5ms 

Je veux vraiment comprendre les demandes/réponses et middleware. Alors pourquoi cela se passe-t-il? Pourquoi ce middleware est-il exécuté deux fois à cause de l'erreur 404? Est-ce que la réponse à l'erreur 404 provoque l'exécution du middleware deux fois?

Merci

EDIT

J'utilise le middleware app.js comme ceci:

app.use(favicon(__dirname + '/node_modules/static-favicon/favicon.ico')); 
app.use(logger('dev')); 
app.use(bodyParser.json()); 
app.use(bodyParser.urlencoded({ extended: false })); 
app.use(cookieParser()); 
app.use(session({resave:'false', saveUninitialized:'false', secret:'secret'})); 

app.use(express.static(path.join(__dirname, 'public'))); 
app.set('multimedia', __dirname + '/public/multimedia'); 

app.use(handler); //<= THE MIDDLEWARE IN QUESTION 


app.use(messages); 
app.get('/', routes.list); 
app.get('/register', register.form); 
app.post('/register', register.submitit); 
+0

Il se peut que 'express.static' ne puisse pas servir le fichier qui a été demandé, donc il a continué la chaîne de requête (aka '' next() ''), auquel cas il exécutera le' app.use (gestionnaire) 'middleware et tenter de faire correspondre d'autres routes plus bas, aucun-qui s'applique donc il montre un 404. En d'autres termes, Il se connecte une fois pour le chargement de la page, et une fois pour le 404. –

+0

J'ai écrit le ci-dessus comment dans une réponse ci-dessous après avoir testé que c'est le cas. –

Répondre

2

La raison pour laquelle votre middleware s'exécute deux fois est qu'il s'exécute une fois pour la requête initiale et une fois pour le 404 (le script statique qui n'existe pas). Si express.static peut trouver un fichier, il envoie la réponse avec le fichier approprié, s'il ne peut pas trouver le bon fichier (comme c'est le cas avec vous), il appelle next() qui tente de faire correspondre la demande à d'autres routes, l'exécution de tout autre logiciel intermédiaire défini ci-dessous express.static. En d'autres termes, si express.static trouve le fichier à servir, le middleware situé en dessous ne fonctionnera pas. Dans votre cas, le middleware s'exécute une fois pour la demande réelle et une fois en essayant de trouver le fichier ou un itinéraire correct pour servir de réponse.

Ceci peut être observé en vous connectant la req.path pour un fichier statique normal et qui n'existe pas:

app.js -

app.use(express.static(path.join(__dirname, 'public'))); 

app.use(function(req, res, next){ 
    console.log('Requested path: %s', req.path); 
    next(); 
}) 

layout.hbs (Renders '/') -

<!DOCTYPE html> 
<html> 
    <head> 
    <title>{{title}}</title> 
    <link rel='stylesheet' href='/stylesheets/style.css' /> <!-- exists --> 
    <link rel='stylesheet' href='/stylesheets/foo.css' /> <!-- doesn't exist --> 
    </head> 
    <body> 
    {{{body}}} 
    </body> 
</html> 

Nous verrons que le middleware enregistrera uniquement le chemin de demande de la demande initiale et pour la 404, mais pas le fichier statique. par exemple:

Requested path:/
Requested path: /stylesheets/foo.css 

Espérons que cela aide.

+0

Merci beaucoup pour la réponse. Je suppose que dans le troisième paragraphe, première ligne, par «amende le fichier», vous voulez dire «trouve le fichier»? – slevin

+0

Oui, j'ai modifié ma réponse. –

-1

Où êtes-vous postulez ce middleware?

Si par exemple, vous avez

app.use(handler) 

handler est de la forme function (req, res, next), il sera appliqué à chaque demande (avec un verbe HTTP). Sinon,

app.get('/some/route', handler) 

où le handler appliquera partout ci-dessous /some/route (par exemple /some/route/any/deepness).

Donc, je suppose que vous êtes sur l'application de votre fonction middleware (j'interchanger gestionnaire et middleware, ils ont la même signature de la fonction - peut-être gestionnaire est plus adapté à des fonctions qui envoient une réponse et middleware à ceux qui appellent next()). Mais il est difficile de dire sans le contexte de la façon dont ce middleware est appliqué.

Voir Writing Middleware et les autres guides fournis par Express.

PS. Vous n'avez pas besoin de return next() dans le middleware. Juste next().

+0

J'ai mis à jour ma question, en montrant comment le middleware est défini dans 'app.js'. Bonne réponse, je comprends ce que vous dites, mais je ne pense pas que je l'applique trop parce que je le définis et ensuite toutes les autres définitions qui le suivent, l'utilisent. Comment est-ce lié à l'erreur 404 et au fait que le middleware s'exécute deux fois? Merci – slevin

+0

@slevin lorsque vous demandez quelque chose qui n'existe pas, le middleware s'exécute (puisqu'il s'exécute sur tout ce qui n'est pas statique), suivi par le gestionnaire 404 qui imprime la page 404. –