node.js - proyecto - node js express
¿Cómo obtener todas las rutas registradas en Express? (13)
Tengo una aplicación web creada usando Node.js y Express. Ahora me gustaría enumerar todas las rutas registradas con sus métodos apropiados.
Por ejemplo, si he ejecutado
app.get(''/'', function (...) { ... });
app.get(''/foo/:id'', function (...) { ... });
app.post(''/foo/:id'', function (...) { ... });
Me gustaría recuperar un objeto (o algo equivalente a eso) como:
{
get: [ ''/'', ''/foo/:id'' ],
post: [ ''/foo/:id'' ]
}
¿Es posible? y si lo es, cómo?
ACTUALIZACIÓN: Mientras tanto, he creado un paquete npm llamado get-routes que extrae las rutas de una aplicación determinada, lo que resuelve este problema. Actualmente, solo se admite Express 4.x, pero supongo que por ahora esto está bien. Solo para tu información.
expreso 3.x
De acuerdo, lo encontré yo mismo ... es solo una aplicación. app.routes
:-)
expreso 4.x
Applications - construidas con express()
app._router.stack
Routers - construidos con express.Router()
router.stack
Nota : La pila también incluye las funciones de middleware, debe filtrarse para obtener solo las "rutas" .
Express 4
Dada una configuración de Express 4 con puntos finales y enrutadores anidados
const express = require(''express'')
const app = express()
const router = express.Router()
app.get(...)
app.post(...)
router.use(...)
router.get(...)
router.post(...)
app.use(router)
Ampliando la respuesta de @caleb es posible obtener todas las rutas recursivamente y ordenadas.
getRoutes(app._router && app._router.stack)
// =>
// [
// [ ''GET'', ''/''],
// [ ''POST'', ''/auth''],
// ...
// ]
/**
* Converts Express 4 app routes to an array representation suitable for easy parsing.
* @arg {Array} stack An Express 4 application middleware list.
* @returns {Array} An array representation of the routes in the form [ [ ''GET'', ''/path'' ], ... ].
*/
function getRoutes(stack) {
const routes = (stack || [])
// We are interested only in endpoints and router middleware.
.filter(it => it.route || it.name === ''router'')
// The magic recursive conversion.
.reduce((result, it) => {
if (! it.route) {
// We are handling a router middleware.
const stack = it.handle.stack
const routes = getRoutes(stack)
return result.concat(routes)
}
// We are handling an endpoint.
const methods = it.route.methods
const path = it.route.path
const routes = Object
.keys(methods)
.map(m => [ m.toUpperCase(), path ])
return result.concat(routes)
}, [])
// We sort the data structure by route path.
.sort((prev, next) => {
const [ prevMethod, prevPath ] = prev
const [ nextMethod, nextPath ] = next
if (prevPath < nextPath) {
return -1
}
if (prevPath > nextPath) {
return 1
}
return 0
})
return routes
}
Para salida de cadena básica.
infoAboutRoutes(app)
/**
* Converts Express 4 app routes to a string representation suitable for console output.
* @arg {Object} app An Express 4 application
* @returns {string} A string representation of the routes.
*/
function infoAboutRoutes(app) {
const entryPoint = app._router && app._router.stack
const routes = getRoutes(entryPoint)
const info = routes
.reduce((result, it) => {
const [ method, path ] = it
return result + `${method.padEnd(6)} ${path}/n`
}, '''')
return info
}
Actualización 1:
Debido a las limitaciones internas de Express 4, no es posible recuperar la aplicación montada y los enrutadores montados. Por ejemplo, no es posible obtener rutas desde esta configuración.
const subApp = express()
app.use(''/sub/app'', subApp)
const subRouter = express.Router()
app.use(''/sub/route'', subRouter)
Aquí hay una pequeña cosa que uso solo para obtener las rutas registradas en Express 4.x
app._router.stack // registered routes
.filter(r => r.route) // take out all the middleware
.map(r => r.route.path) // get all the paths
Copia / pega la respuesta de Hacky cortesía de Doug Wilson sobre los problemas expresos de github . Sucio, pero funciona como un encanto.
function print (path, layer) {
if (layer.route) {
layer.route.stack.forEach(print.bind(null, path.concat(split(layer.route.path))))
} else if (layer.name === ''router'' && layer.handle.stack) {
layer.handle.stack.forEach(print.bind(null, path.concat(split(layer.regexp))))
} else if (layer.method) {
console.log(''%s /%s'',
layer.method.toUpperCase(),
path.concat(split(layer.regexp)).filter(Boolean).join(''/''))
}
}
function split (thing) {
if (typeof thing === ''string'') {
return thing.split(''/'')
} else if (thing.fast_slash) {
return ''''
} else {
var match = thing.toString()
.replace(''///?'', '''')
.replace(''(?=///|$)'', ''$'')
.match(/^///^((?://[.*+?^${}()|[/]////]|[^.*+?^${}()|[/]////])*)/$///)
return match
? match[1].replace(///(.)/g, ''$1'').split(''/'')
: ''<complex:'' + thing.toString() + ''>''
}
}
app._router.stack.forEach(print.bind(null, []))
Produce
En Express 3.5.x, agrego esto antes de iniciar la aplicación para imprimir las rutas en mi terminal:
var routes = app.routes;
for (var verb in routes){
if (routes.hasOwnProperty(verb)) {
routes[verb].forEach(function(route){
console.log(verb + " : "+route[''path'']);
});
}
}
Quizás pueda ayudar ...
En Express 4 puede seguir esta útil guía: list-all-rest-endpoints
Lo he adaptado para mis necesidades. He usado express.Router () y registré mis rutas de esta manera:
var questionsRoute = require(''./BE/routes/questions'');
app.use(''/api/questions'', questionsRoute);
Cambié el nombre del archivo document.js en apiTable.js y lo adapté así:
module.exports = function (baseUrl, routes) {
var Table = require(''cli-table'');
var table = new Table({ head: ["", "Path"] });
console.log(''/nAPI for '' + baseUrl);
console.log(''/n********************************************'');
for (var key in routes) {
if (routes.hasOwnProperty(key)) {
var val = routes[key];
if(val.route) {
val = val.route;
var _o = {};
_o[val.stack[0].method] = [baseUrl + val.path];
table.push(_o);
}
}
}
console.log(table.toString());
return table;
};
entonces lo llamo en mi server.js de esta manera:
var server = app.listen(process.env.PORT || 5000, function () {
require(''./BE/utils/apiTable'')(''/api/questions'', questionsRoute.stack);
});
El resultado es así:
Es solo un ejemplo, pero podría ser útil ... espero ...
Esto funcionó para mí
let routes = []
app._router.stack.forEach(function (middleware) {
if(middleware.route) {
routes.push(Object.keys(middleware.route.methods) + " -> " + middleware.route.path);
}
});
console.log(JSON.stringify(routes, null, 4));
O / P:
[
"get -> /posts/:id",
"post -> /posts",
"patch -> /posts"
]
Esto obtiene las rutas registradas directamente en la aplicación (a través de la aplicación.VERB) y las rutas que están registradas como middleware del enrutador (a través de app.use). Express 4.11.0
//////////////
app.get("/foo", function(req,res){
res.send(''foo'');
});
//////////////
var router = express.Router();
router.get("/bar", function(req,res,next){
res.send(''bar'');
});
app.use("/",router);
//////////////
var route, routes = [];
app._router.stack.forEach(function(middleware){
if(middleware.route){ // routes registered directly on the app
routes.push(middleware.route);
} else if(middleware.name === ''router''){ // router middleware
middleware.handle.stack.forEach(function(handler){
route = handler.route;
route && routes.push(route);
});
}
});
// routes:
// {path: "/foo", methods: {get: true}}
// {path: "/bar", methods: {get: true}}
Me inspiré en las rutas de listas expresas de Labithiotis, pero quería una visión general de todas mis rutas y urls brutas de una vez, y no especificar un enrutador, y averiguar el prefijo cada vez. Algo que se me ocurrió fue simplemente reemplazar la función app.use con mi propia función que almacena la baseUrl y el enrutador dado. Desde allí puedo imprimir cualquier tabla de todas mis rutas.
NOTA, esto funciona para mí porque declaro mis rutas en un archivo de rutas específico (función) que se pasa en el objeto de la aplicación, como este:
// index.js
[...]
var app = Express();
require(./config/routes)(app);
// ./config/routes.js
module.exports = function(app) {
// Some static routes
app.use(''/users'', [middleware], UsersRouter);
app.use(''/users/:user_id/items'', [middleware], ItemsRouter);
app.use(''/otherResource'', [middleware], OtherResourceRouter);
}
Esto me permite pasar otro objeto ''aplicación'' con una función de uso falso, y puedo obtener TODAS las rutas. Esto funciona para mí (eliminé la comprobación de errores para mayor claridad, pero aún funciona para el ejemplo):
// In printRoutes.js (or a gulp task, or whatever)
var Express = require(''express'')
, app = Express()
, _ = require(''lodash'')
// Global array to store all relevant args of calls to app.use
var APP_USED = []
// Replace the `use` function to store the routers and the urls they operate on
app.use = function() {
var urlBase = arguments[0];
// Find the router in the args list
_.forEach(arguments, function(arg) {
if (arg.name == ''router'') {
APP_USED.push({
urlBase: urlBase,
router: arg
});
}
});
};
// Let the routes function run with the stubbed app object.
require(''./config/routes'')(app);
// GRAB all the routes from our saved routers:
_.each(APP_USED, function(used) {
// On each route of the router
_.each(used.router.stack, function(stackElement) {
if (stackElement.route) {
var path = stackElement.route.path;
var method = stackElement.route.stack[0].method.toUpperCase();
// Do whatever you want with the data. I like to make a nice table :)
console.log(method + " -> " + used.urlBase + path);
}
});
});
Este ejemplo completo (con algunos enrutadores CRUD básicos) acaba de probarse e imprimirse:
GET -> /users/users
GET -> /users/users/:user_id
POST -> /users/users
DELETE -> /users/users/:user_id
GET -> /users/:user_id/items/
GET -> /users/:user_id/items/:item_id
PUT -> /users/:user_id/items/:item_id
POST -> /users/:user_id/items/
DELETE -> /users/:user_id/items/:item_id
GET -> /otherResource/
GET -> /otherResource/:other_resource_id
POST -> /otherResource/
DELETE -> /otherResource/:other_resource_id
Usando cli-table obtuve algo como esto:
┌────────┬───────────────────────┐
│ │ => Users │
├────────┼───────────────────────┤
│ GET │ /users/users │
├────────┼───────────────────────┤
│ GET │ /users/users/:user_id │
├────────┼───────────────────────┤
│ POST │ /users/users │
├────────┼───────────────────────┤
│ DELETE │ /users/users/:user_id │
└────────┴───────────────────────┘
┌────────┬────────────────────────────────┐
│ │ => Items │
├────────┼────────────────────────────────┤
│ GET │ /users/:user_id/items/ │
├────────┼────────────────────────────────┤
│ GET │ /users/:user_id/items/:item_id │
├────────┼────────────────────────────────┤
│ PUT │ /users/:user_id/items/:item_id │
├────────┼────────────────────────────────┤
│ POST │ /users/:user_id/items/ │
├────────┼────────────────────────────────┤
│ DELETE │ /users/:user_id/items/:item_id │
└────────┴────────────────────────────────┘
┌────────┬───────────────────────────────────┐
│ │ => OtherResources │
├────────┼───────────────────────────────────┤
│ GET │ /otherResource/ │
├────────┼───────────────────────────────────┤
│ GET │ /otherResource/:other_resource_id │
├────────┼───────────────────────────────────┤
│ POST │ /otherResource/ │
├────────┼───────────────────────────────────┤
│ DELETE │ /otherResource/:other_resource_id │
└────────┴───────────────────────────────────┘
Que patea el culo.
Un enfoque ligeramente actualizado y más funcional para la respuesta de @prranay:
const routes = app._router.stack
.filter((middleware) => middleware.route)
.map((middleware) => `${Object.keys(middleware.route.methods).join('', '')} -> ${middleware.route.path}`)
console.log(JSON.stringify(routes, null, 4));
Una función para registrar todas las rutas en Express 4 (se puede ajustar fácilmente para v3 ~)
function space(x) {
var res = '''';
while(x--) res += '' '';
return res;
}
function listRoutes(){
for (var i = 0; i < arguments.length; i++) {
if(arguments[i].stack instanceof Array){
console.log('''');
arguments[i].stack.forEach(function(a){
var route = a.route;
if(route){
route.stack.forEach(function(r){
var method = r.method.toUpperCase();
console.log(method,space(8 - method.length),route.path);
})
}
});
}
}
}
listRoutes(router, routerAuth, routerHTML);
Logs de salida:
GET /isAlive
POST /test/email
POST /user/verify
PUT /login
POST /login
GET /player
PUT /player
GET /player/:id
GET /players
GET /system
POST /user
GET /user
PUT /user
DELETE /user
GET /
GET /login
Hecho esto en un NPM https://www.npmjs.com/package/express-list-routes
https://www.npmjs.com/package/express-list-endpoints funciona bastante bien.
Ejemplo
Uso:
const all_routes = require(''express-list-endpoints'');
console.log(all_routes(app));
Salida:
[ { path: ''*'', methods: [ ''OPTIONS'' ] },
{ path: ''/'', methods: [ ''GET'' ] },
{ path: ''/sessions'', methods: [ ''POST'' ] },
{ path: ''/sessions'', methods: [ ''DELETE'' ] },
{ path: ''/users'', methods: [ ''GET'' ] },
{ path: ''/users'', methods: [ ''POST'' ] } ]
app._router.stack.forEach(function(r){
if (r.route && r.route.path){
console.log(r.route.path)
}
})