Diferença entre app.all ('*') e app.use ('/')

121

Existe uma diferença útil entre app.all('*', ... )e app.use('/', ...)no Node.JS Express?

Ostergaard
fonte

Respostas:

119

Na maioria dos casos, eles funcionariam de forma equivalente. A maior diferença é a ordem em que o middleware seria aplicado:

  • app.all() anexa ao roteador do aplicativo, portanto, é usado sempre que o middleware app.router é alcançado (que lida com todas as rotas de método ... GET, POST, etc).

AVISO: app.router foi descontinuado no express 4.x

  • app.use()anexa à pilha principal de middleware do aplicativo, portanto, é usado na ordem especificada pelo middleware. por exemplo, se você colocá-lo primeiro, será a primeira coisa a ser executada. Se você colocá-lo por último, (após o roteador), ele geralmente não será executado.

Normalmente, se você deseja fazer algo globalmente em todas as rotas, app.use () é a melhor opção. Além disso, tem menos chance de bugs futuros, já que o express 0.4 provavelmente deixará o roteador implícito cair (ou seja, a posição do roteador no middleware será mais importante do que é agora, já que você tecnicamente nem precisa usá-lo agora mesmo).

hunterloftis
fonte
15
Isso ainda se aplica após o Express 4.x? app.router foi removido.
ruffrey de
1
Você pode usar next("route")com app.all, mas não com app.use.
Jozef Mikušinec
@JozefMikusinec A documentação parece sugerir o contrário ... expressjs.com/en/guide/writing-middleware.html
musicin3d
Seu link não menciona próximo ('rota'), mas eu olhei na API, você está certo.
Jozef Mikušinec
2
@ musicin3d Pesquisei mais e encontrei este problema do GitHub , que confirma que "next () e next ('route') não têm diferença para app.use" (citação). Eles devem mudar os documentos.
Jozef Mikušinec
87

app.use leva apenas uma função de retorno de chamada e é destinado a Middleware. O middleware geralmente não lida com solicitações e respostas (tecnicamente podem), eles apenas processam os dados de entrada e os entregam ao próximo manipulador na fila.

app.use([path], function)

app.all recebe vários retornos de chamada e se destina ao roteamento. com vários retornos de chamada, você pode filtrar solicitações e enviar respostas. É explicado em Filtros em express.js

app.all(path, [callback...], callback)

app.use vê apenas se o url começa com o caminho especificado

app.use( "/product" , mymiddleware);
// will match /product
// will match /product/cool
// will match /product/foo

app.all corresponderá ao caminho completo

app.all( "/product" , handler);
// will match /product
// won't match /product/cool   <-- important
// won't match /product/foo    <-- important

app.all( "/product/*" , handler);
// won't match /product        <-- Important
// will match /product/
// will match /product/cool
// will match /product/foo
Palani
fonte
17
Pelo menos na v4, app.use assume uma ou mais funções de middleware, não "apenas uma".
Jess Austin
2
app.use vê apenas se o url começa com o caminho especificado; app.all corresponderá ao caminho completo. esta é a principal diferença.
meizilp
@frogcjn não, não deveria, pois ignora o * e / na minha pergunta.
ostergaard
15
  • app.use:

    1. injetar middlware em sua configuração de controlador frontal, por exemplo: cabeçalho, cookies, sessões, etc.
    2. deve ser escrito antes do app [http_method], caso contrário, não será executado.
    3. várias chamadas são processadas na ordem de escrita
  • app.all:

    1. (como app [http_method]) é usado para configurar controladores de rotas
    2. "todos" significa que se aplica a todos os métodos http.
    3. várias chamadas são processadas na ordem de escrita

Veja este exemplo de código expressJs:

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

app.use(function frontControllerMiddlewareExecuted(req, res, next){
  console.log('(1) this frontControllerMiddlewareExecuted is executed');
  next();
});

app.all('*', function(req, res, next){
  console.log('(2) route middleware for all method and path pattern "*", executed first and can do stuff before going next');
  next();
});

app.all('/hello', function(req, res, next){
  console.log('(3) route middleware for all method and path pattern "/hello", executed second and can do stuff before going next');
  next();
});

app.use(function frontControllerMiddlewareNotExecuted(req, res, next){
  console.log('(4) this frontControllerMiddlewareNotExecuted is not executed');
  next();
});

app.get('/hello', function(req, res){
  console.log('(5) route middleware for method GET and path patter "/hello", executed last and I do my stuff sending response');
  res.send('Hello World');
});

app.listen(80);

Aqui está o registro ao acessar a rota '/ hello':

(1) this frontControllerMiddlewareExecuted is executed
(2) route middleware for all method and path pattern "*", executed first and can do stuff before going next
(3) route middleware for all method and path pattern "/hello", executed second and can do stuff before going next
(5) route middleware for method GET and path patter "/hello", executed last and I do my stuff sending response
daemon1981
fonte
6
Depois de executar este exemplo literalmente no express 4.x, ele realmente executa todos os 5 em ordem. Isso provavelmente se deve a mudanças no expresso nos quase 3 anos desde que este foi escrito, mas pensei em acrescentar isso para maior clareza.
Nathan Wiebe
11

Com app.use(), o caminho de "montagem" é removido e não é visível para a função de middleware:

app.use('/static', express.static(__dirname + '/public'));

As funções de middleware montadas ( express.static) não são chamadas a menos que req.urlcontenha esse prefixo ( /static), ponto no qual ele é removido quando a função é chamada.

Com app.all() , não existe esse comportamento.

melhor9
fonte
A pergunta pergunta explicitamente apenas sobre app.use ('/', ...).
ostergaard
Esta é a resposta correta para a pergunta que ainda é verdadeira em 2018! Um middleware pode ser montado com all () também ... a única diferença é que o caminho de montagem é removido ao executar o middleware.
Xatian
4

Sim, app.all()é chamado quando um determinado URI é solicitado com qualquer tipo de método de solicitação (POST, GET, PUT ou DELETE)

Por outro lado app.use() é usado para qualquer middleware que você possa ter e é montado em um prefixo de caminho e será chamado sempre que um URI nessa rota for solicitado.

Aqui está a documentação para app.all e app.use .

Gurpreet Singh
fonte
obrigado, mas acho que você perdeu o curinga app.all e o caminho de raiz app.use, que os tornam exatamente a mesma coisa, não é? Exceto que app.all pode receber uma série de retornos de chamada e app.use pode ter apenas um - certo?
ostergaard
1

Duas diferenças todas as respostas acima não se aplicam.

O primeiro: app.allaceita um regex como seu parâmetro de caminho. app.useNÃO aceita um regex.

O segundo: app.all(path,handler)ou app[method](path,handler), o manipulador pathdeve ser o mesmo para todos path . Isto é, o caminho do aplicativo [método] está completo.

app.use(path,hanlder), se o caminho do uso estiver completo, o caminho do hanlder deve ser '/'. se o caminho do uso for o início do caminho completo, o caminho do manipulador deve ser o resto do caminho completo.

 app.use('/users', users);

  //users.js:  the handler will be called when matchs `/user/` path
      router.get('/', function(req, res, next) {
      res.send('respond with a resource');
    });
  // others.js: the handler will be called when matchs `/users/users` path
      router.get('/users', function(req, res, next) {
      res.send('respond with a resource');
    });

app.all('/users', users);

//others.js: the handler wil be called when matchs `/`path
router.get('/', function(req, res, next) {
     res.send('respond with a resource');
});
//users.js: the handler will be called when matchs `/users` path
router.get('/users', function(req, res, next) {
    res.send('respond with a resource');
 });
JackChouMine
fonte
0

Existem duas diferenças principais:

1. correspondência de padrões (resposta dada por Palani)
2. next(route)não funcionará dentro do corpo da função do middleware carregado usando app.use. Isso é afirmado no link dos documentos:

NOTE: next('route') will work only in middleware functions that were loaded by using the app.METHOD() or router.METHOD() functions.

Link: http://expressjs.com/en/guide/using-middleware.html

O efeito de funcionamento de next('route')pode ser visto no seguinte exemplo:

app.get('/',
(req,res,next)=>{console.log("1");
next(route); //The code here skips ALL the following middlewares
}
(req,res,next)=>{next();}, //skipped
(req,res,next)=>{next();}  //skipped
);

//Not skipped
app.get('/',function(req,res,next){console.log("2");next();});
Ng Ju Ping
fonte