如何在 Express 中获取所有已注册的路线?
Posted
技术标签:
【中文标题】如何在 Express 中获取所有已注册的路线?【英文标题】:How to get all registered routes in Express? 【发布时间】:2013-02-02 18:35:13 【问题描述】:我有一个使用 Node.js 和 Express 构建的 Web 应用程序。现在我想列出所有已注册的路线及其适当的方法。
例如,如果我执行了
app.get('/', function (...) ... );
app.get('/foo/:id', function (...) ... );
app.post('/foo/:id', function (...) ... );
我想检索一个对象(或与之等效的对象),例如:
get: [ '/', '/foo/:id' ],
post: [ '/foo/:id' ]
这可能吗?如果可以,怎么做?
【问题讨论】:
我试过的所有解决方案,当你定义了路由器时都不起作用。它仅适用于每条路线 - 它不会在我的应用程序中为我提供该路线的整个 url... @guymograbi 你可能想看看***.com/a/55589657/6693775 我创建了collect-express-routes,它适用于 express 应用程序和 express.Router 【参考方案1】:表达 3.x
好的,我自己找到的...只是app.routes
:-)
表达 4.x
Applications - 使用 express()
构建
app._router.stack
Routers - 使用 express.Router()
构建
router.stack
注意:堆栈也包含中间件功能,应过滤以仅获取“路由”。
【讨论】:
我正在使用节点 0.10,它是app.routes.routes
- 这意味着我可以执行 JSON.stringify(app.routes.routes)
仅适用于 Express 3.x,不适用于 4.x。在 4.x 中,您应该检查 app._router.stack
这对我来说没有按预期工作。 app._router 似乎不包括来自 app.use('/path', otherRouter); 的路由
是否有某种方式可以将其与命令行脚本集成,该脚本会在无需实际启动 Web 应用的情况下提取与实时应用完全相同的路由文件?
至少在 express 4.13.1 app._router.stack
中是未定义的。【参考方案2】:
在 Express 3.5.x 上,我在启动应用程序之前添加它以在我的终端上打印路线:
var routes = app.routes;
for (var verb in routes)
if (routes.hasOwnProperty(verb))
routes[verb].forEach(function(route)
console.log(verb + " : "+route['path']);
);
也许能帮上忙……
【讨论】:
【参考方案3】:在 express 4 中记录所有路线的功能(可以轻松调整到 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);
日志输出:
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
把它变成一个 NPM https://www.npmjs.com/package/express-list-routes
【讨论】:
这对我来说没有按预期工作。 app._router 似乎不包括来自 app.use('/path', otherRouter); 的路由 @MichaelCole 您是否看过以下来自 Golo Roden 的答案? @Dazzler13 我玩了一个小时,但无法让它工作。快递 4.0。 Made app,made router,app.use(path,router),路由器路由没有出现在app._router中。例子? 下面来自@Caleb 的示例适用于使用 express.Router 等处理的路由,如果这是您的问题。请注意,使用中间件(包括 express.Router)设置的路由可能不会立即显示,您可能需要在 app._router 中检查它们之前添加一小段延迟(即使使用来自@Caleb 的方法)。【参考方案4】:app._router.stack.forEach(function(r)
if (r.route && r.route.path)
console.log(r.route.path)
)
【讨论】:
请注意,如果您使用的是 Express Router(或其他中间件)之类的东西,您应该会看到 @Caleb 稍长的答案,它扩展了这种方法。【参考方案5】:这会获取直接在应用上注册的路由(通过 app.VERB)和注册为路由器中间件的路由(通过 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
【讨论】:
太好了,感谢您提供了一个示例,该示例展示了如何通过 Express 路由器等中间件设置显示路由。 在我的情况下,这不适用于 esbuild minified build added fix ` const endpoints: any[] = []; this.app._router.stack.forEach(function (middleware: any) if (middleware.route) // 直接注册在应用程序上的路由 endpoints.push(middleware.route); else if (middleware.handle && middleware .handle.stack) // 路由器中间件 middleware.handle.stack.forEach(function (handler: any) const route = handler.route; route && endpoints.push(route); ); );` 【参考方案6】:我已根据我的需要改编了一篇不再在线的旧帖子。 我使用了 express.Router() 并像这样注册了我的路线:
var questionsRoute = require('./BE/routes/questions');
app.use('/api/questions', questionsRoute);
我将 apiTable.js 中的 document.js 文件重命名并修改如下:
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;
;
然后我在 server.js 中这样称呼它:
var server = app.listen(process.env.PORT || 5000, function ()
require('./BE/utils/apiTable')('/api/questions', questionsRoute.stack);
);
结果如下:
这只是一个例子,但可能有用..我希望..
【讨论】:
这不适用于此处确定的嵌套路由:***.com/questions/25260818/… 当心这个答案中的链接!它把我重定向到一个随机网站并强制下载到我的电脑。【参考方案7】:我受到 Labithiotis 的 express-list-routes 的启发,但我想一次性了解我所有的路由和粗略的 url,而不是指定路由器,并且每次都找出前缀。我想出的办法是简单地将 app.use 函数替换为我自己的函数,该函数存储 baseUrl 和给定的路由器。从那里我可以打印我所有路线的任何表格。
注意这对我有用,因为我在一个特定的路由文件(函数)中声明了我的路由,该路由文件(函数)被传递到 app 对象中,如下所示:
// 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);
这允许我传入另一个带有假使用功能的“app”对象,我可以获得所有路由。这对我有用(为清楚起见删除了一些错误检查,但仍然适用于示例):
// 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);
);
);
这个完整的例子(带有一些基本的 CRUD 路由器)刚刚经过测试并打印出来:
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
使用cli-table 我得到了这样的结果:
┌────────┬───────────────────────┐
│ │ => 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 │
└────────┴───────────────────────────────────┘
这真是太棒了。
【讨论】:
【参考方案8】:这是我用来获取 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
【讨论】:
console.log(server._router.stack.map(r=>r.route).filter(r=>r).map(r=>$Object.keys(r.methods).join(', ') $r.path
))
你把这个放在哪里,在 app.js 中??
@Juan 在app.listen
回调中
我只能得到一个无用的结果:[ '*' ]
【参考方案9】:
https://www.npmjs.com/package/express-list-endpoints 效果很好。
示例
用法:
const all_routes = require('express-list-endpoints');
console.log(all_routes(app));
输出:
[ path: '*', methods: [ 'OPTIONS' ] ,
path: '/', methods: [ 'GET' ] ,
path: '/sessions', methods: [ 'POST' ] ,
path: '/sessions', methods: [ 'DELETE' ] ,
path: '/users', methods: [ 'GET' ] ,
path: '/users', methods: [ 'POST' ] ]
【讨论】:
这不适用于:server = express(); app1 = express(); server.use('/app1', app1); ...
【参考方案10】:
在express github issues 上由Doug Wilson 提供的hacky 复制/粘贴答案。肮脏但像魅力一样工作。
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, []))
生产
【讨论】:
为什么路线不明显? 这是唯一适用于我的 Express 4.15。其他人都没有给出完整的路径。唯一需要注意的是,它不会返回默认的根路径 / - 它们都不会。 我不明白你为什么要将参数绑定到print
?
@ZzZombo 问道格·威尔逊,是他写的。如果你愿意,你可能可以清理所有这些。
太棒了.. 谢谢【参考方案11】:
这对我有用
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"
]
【讨论】:
【参考方案12】:对@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));
【讨论】:
【参考方案13】:快递4
给定一个带有端点和嵌套路由器的 Express 4 配置
const express = require('express')
const app = express()
const router = express.Router()
app.get(...)
app.post(...)
router.use(...)
router.get(...)
router.post(...)
app.use(router)
扩展@caleb的答案可以递归和排序获取所有路由。
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
用于基本字符串输出。
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
更新 1:
由于 Express 4 的内部限制,无法检索已安装的应用程序和已安装的路由器。例如,无法从此配置中获取路由。
const subApp = express()
app.use('/sub/app', subApp)
const subRouter = express.Router()
app.use('/sub/route', subRouter)
【讨论】:
列出挂载的路由适用于这个包:github.com/AlbertoFdzM/express-list-endpoints【参考方案14】:需要一些调整,但应该适用于 Express v4。包括那些用.use()
添加的路由。
function listRoutes(routes, stack, parent)
parent = parent || '';
if(stack)
stack.forEach(function(r)
if (r.route && r.route.path)
var method = '';
for(method in r.route.methods)
if(r.route.methods[method])
routes.push(method: method.toUpperCase(), path: parent + r.route.path);
else if (r.handle && r.handle.name == 'router')
const routerName = r.regexp.source.replace("^\\","").replace("\\/?(?=\\/|$)","");
return listRoutes(routes, r.handle.stack, parent + routerName);
);
return routes;
else
return listRoutes([], app._router.stack);
//Usage on app.js
const routes = listRoutes(); //array: ["method: path", "..."]
编辑:代码改进
【讨论】:
【参考方案15】:所以我正在查看所有答案.. 最不喜欢.. 从少数人中提取一些.. 做了这个:
const resolveRoutes = (stack) =>
return stack.map(function (layer)
if (layer.route && layer.route.path.isString())
let methods = Object.keys(layer.route.methods);
if (methods.length > 20)
methods = ["ALL"];
return methods: methods, path: layer.route.path;
if (layer.name === 'router') // router middleware
return resolveRoutes(layer.handle.stack);
).filter(route => route);
;
const routes = resolveRoutes(express._router.stack);
const printRoute = (route) =>
if (Array.isArray(route))
return route.forEach(route => printRoute(route));
console.log(JSON.stringify(route.methods) + " " + route.path);
;
printRoute(routes);
不是最漂亮的......但是嵌套,并且可以解决问题
还要注意那里的 20 个...我只是假设不会有 20 个方法的正常路线..所以我推断这就是全部..
【讨论】:
【参考方案16】:路线详情为 "express": "4.x.x",
import
Router
from 'express';
var router = Router();
router.get("/routes", (req, res, next) =>
var routes = [];
var i = 0;
router.stack.forEach(function (r)
if (r.route && r.route.path)
r.route.stack.forEach(function (type)
var method = type.method.toUpperCase();
routes[i++] =
no:i,
method: method.toUpperCase(),
path: r.route.path
;
)
)
res.send('<h1>List of routes.</h1>' + JSON.stringify(routes));
);
简单的代码输出
List of routes.
[
"no":1,"method":"POST","path":"/admin",
"no":2,"method":"GET","path":"/",
"no":3,"method":"GET","path":"/routes",
"no":4,"method":"POST","path":"/student/:studentId/course/:courseId/topic/:topicId/task/:taskId/item",
"no":5,"method":"GET","path":"/student/:studentId/course/:courseId/topic/:topicId/task/:taskId/item",
"no":6,"method":"PUT","path":"/student/:studentId/course/:courseId/topic/:topicId/task/:taskId/item/:itemId",
"no":7,"method":"DELETE","path":"/student/:studentId/course/:courseId/topic/:topicId/task/:taskId/item/:itemId"
]
【讨论】:
【参考方案17】:我发布了一个包,它打印所有中间件和路由,在尝试审核 express 应用程序时非常有用。您将包安装为中间件,因此它甚至会自行打印出来:
https://github.com/ErisDS/middleware-stack-printer
它打印出一种树,例如:
- middleware 1
- middleware 2
- Route /thing/
- - middleware 3
- - controller (HTTP VERB)
【讨论】:
【参考方案18】:json 输出
function availableRoutes()
return app._router.stack
.filter(r => r.route)
.map(r =>
return
method: Object.keys(r.route.methods)[0].toUpperCase(),
path: r.route.path
;
);
console.log(JSON.stringify(availableRoutes(), null, 2));
看起来像这样:
[
"method": "GET",
"path": "/api/todos"
,
"method": "POST",
"path": "/api/todos"
,
"method": "PUT",
"path": "/api/todos/:id"
,
"method": "DELETE",
"path": "/api/todos/:id"
]
字符串输出
function availableRoutesString()
return app._router.stack
.filter(r => r.route)
.map(r => Object.keys(r.route.methods)[0].toUpperCase().padEnd(7) + r.route.path)
.join("\n")
console.log(availableRoutesString());
看起来像这样:
GET /api/todos
POST /api/todos
PUT /api/todos/:id
DELETE /api/todos/:id
这些都是基于@corvid's的回答
希望对你有帮助
【讨论】:
这不显示嵌套路由 - 仅显示***路由【参考方案19】:DEBUG=express:* node index.js
如果您使用上述命令运行您的应用,它将使用DEBUG
模块启动您的应用并提供路由,以及所有正在使用的中间件功能。
您可以参考:ExpressJS - Debugging和debug。
【讨论】:
迄今为止最好的答案...一个环境变量! 确实,最有用的答案。 @nbsamar 您甚至可以将其扩展为使用DEBUG=express:paths
仅查看路径输出而不查看所有其他调试消息。谢谢!【参考方案20】:
只需使用这个 npm 包,它就会以漂亮的表格视图提供 web 输出和终端输出。
https://www.npmjs.com/package/express-routes-catalogue
【讨论】:
这个其他包有更多的接受度。 npmjs.com/package/express-list-endpoints 。我是 21.111,每周下载 34 次。但是,express-routes-catalogue
也将路线显示为 HTML,而另一个则没有。
不错,包的文档在需要时与实际的包名称不同,并且这个包像所有其他提到的一样只显示包含它的单层路由
@hamzakhan p.s 感谢更新。我是作者,很快将在文档中更新。【参考方案21】:
初始化快速路由器
let router = require('express').Router();
router.get('/', function (req, res)
res.json(
status: `API Its Working`,
route: router.stack.filter(r => r.route)
.map(r=> return "path":r.route.path,
"methods":r.route.methods),
message: 'Welcome to my crafted with love!',
);
);
导入用户控制器
var userController = require('./controller/userController');
用户路线
router.route('/users')
.get(userController.index)
.post(userController.new);
router.route('/users/:user_id')
.get(userController.view)
.patch(userController.update)
.put(userController.update)
.delete(userController.delete);
导出 API 路由
module.exports = router;
输出
"status":"API Its Working, APP Route","route":
["path":"/","methods":"get":true,
"path":"/users","methods":"get":true,"post":true,
"path":"/users/:user_id","methods": ....
【讨论】:
【参考方案22】:这是一个在 Express app
中漂亮地打印路线的单行函数:
const getAppRoutes = (app) => app._router.stack.reduce(
(acc, val) => acc.concat(
val.route ? [val.route.path] :
val.name === "router" ? val.handle.stack.filter(
x => x.route).map(
x => val.regexp.toString().match(/\/[a-z]+/)[0] + (
x.route.path === '/' ? '' : x.route.path)) : []) , []).sort();
【讨论】:
【参考方案23】:您可以实现/get-all-routes
API:
const express = require("express");
const app = express();
app.get("/get-all-routes", (req, res) =>
let get = app._router.stack.filter(r => r.route && r.route.methods.get).map(r => r.route.path);
let post = app._router.stack.filter(r => r.route && r.route.methods.post).map(r => r.route.path);
res.send( get: get, post: post );
);
const listener = app.listen(process.env.PORT, () =>
console.log("Your app is listening on port " + listener.address().port);
);
这是一个演示:https://glitch.com/edit/#!/get-all-routes-in-nodejs
【讨论】:
不适用于子路由,例如app.use('/module', anotherRouters)
【参考方案24】:
在快递 4.*
//Obtiene las rutas declaradas de la API
let listPathRoutes: any[] = [];
let rutasRouter = _.filter(application._router.stack, rutaTmp => rutaTmp.name === 'router');
rutasRouter.forEach((pathRoute: any) =>
let pathPrincipal = pathRoute.regexp.toString();
pathPrincipal = pathPrincipal.replace('/^\\','');
pathPrincipal = pathPrincipal.replace('?(?=\\/|$)/i','');
pathPrincipal = pathPrincipal.replace(/\\\//g,'/');
let routesTemp = _.filter(pathRoute.handle.stack, rutasTmp => rutasTmp.route !== undefined);
routesTemp.forEach((route: any) =>
let pathRuta = `$pathPrincipal.replace(/\/\//g,'')$route.route.path`;
let ruta =
path: pathRuta.replace('//','/'),
methods: route.route.methods
listPathRoutes.push(ruta);
);
);console.log(listPathRoutes)
【讨论】:
【参考方案25】:在您的应用中/routes
显示您的快速路线名称
app.get('/routes', (req, res) =>
res.send(app._router.stack
.filter(r => r.route)
.map(r => r.route.path))
)
http://localhost:3000/routes
【讨论】:
【参考方案26】:这个对我有用
// Express 4.x
function getRoutes(stacks: any, routes: path: string; method: string [] = [], prefix: string = ''): path: string; method: string []
for (const stack of stacks)
if (stack.route)
routes.push( path: `$prefix$stack.route.path`, method: stack.route.stack[0].method );
if (stack && stack.handle && stack.handle.stack)
let stackPrefix = stack.regexp.source.match(/\/[A-Za-z0-9_-]+/g);
if (stackPrefix)
stackPrefix = prefix + stackPrefix.join('');
routes.concat(getRoutes(stack.handle.stack, routes, stackPrefix));
return routes;
【讨论】:
【参考方案27】:const routes =
function routerRecursion(middleware, pointer, currentName)
if (middleware.route) // routes registered directly on the app
if (!Array.isArray(pointer['routes']))
pointer['routes'] = []
const routeObj =
path: middleware.route.path,
method: middleware.route.stack[0].method
pointer['routes'].push(routeObj)
else if (middleware.name === 'router') // inside router
const current = middleware.regexp.toString().replace(/\/\^\\\//, '').replace(/\\\/\?\(\?\=\\\/\|\$\)\/\i/, '')
pointer[current] =
middleware.handle.stack.forEach(function (handler)
routerRecursion(handler, pointer[current], current)
);
app._router.stack.forEach(function (middleware)
routerRecursion(middleware, routes, 'main')
);
console.log(routes);
app._router.stack.forEach(函数(中间件) routerRecursion(中间件,路由,'main') ); console.log(路由);
【讨论】:
【参考方案28】:静态代码分析方法。
此工具无需启动服务器即可分析源代码并显示路由信息。
npx express-router-dependency-graph --rootDir=path/to/project
# json or markdown output
https://github.com/azu/express-router-dependency-graph
示例输出:
File | Method | Routing | Middlewares | FilePath |
---|---|---|---|---|
user/index.ts | ||||
get | /getUserById | requireView | user/index.ts#L1-3 | |
get | /getUserList | requireView | user/index.ts#L4-6 | |
post | /updateUserById | requireEdit | user/index.ts#L8-10 | |
post | /deleteUserById | requireEdit | user/index.ts#L12-20 | |
game/index.ts | ||||
get | /getGameList | requireView | game/index.ts#L1-3 | |
get | /getGameById | requireView | game/index.ts#L4-6 | |
post | /updateGameById | requireEdit | game/index.ts#L8-10 | |
post | /deleteGameById | requireEdit | game/index.ts#L12-20 |
【讨论】:
很好的解决方案!唉,没有为github.com/TryGhost/Ghost 产生任何有用的结果,但它确实在node_modules
中找到了一些路线!【参考方案29】:
在所有服务器中我都是这样做的
app.get('/', (req, res) =>
console.log('home')
)
app.get('/home', (req, res) =>
console.log('/home')
)
function list(id)
const path = require('path');
const defaultOptions =
prefix: '',
spacer: 7,
;
const COLORS =
yellow: 33,
green: 32,
blue: 34,
red: 31,
grey: 90,
magenta: 35,
clear: 39,
;
const spacer = (x) => (x > 0 ? [...new Array(x)].map(() => ' ').join('') : '');
const colorText = (color, string) => `\u001b[$colorm$string\u001b[$COLORS.clearm`;
function colorMethod(method)
switch (method)
case 'POST':
return colorText(COLORS.yellow, method);
case 'GET':
return colorText(COLORS.green, method);
case 'PUT':
return colorText(COLORS.blue, method);
case 'DELETE':
return colorText(COLORS.red, method);
case 'PATCH':
return colorText(COLORS.grey, method);
default:
return method;
function getPathFromRegex(regexp)
return regexp.toString().replace('/^', '').replace('?(?=\\/|$)/i', '').replace(/\\\//g, '/');
function combineStacks(acc, stack)
if (stack.handle.stack)
const routerPath = getPathFromRegex(stack.regexp);
return [...acc, ...stack.handle.stack.map((stack) => ( routerPath, ...stack ))];
return [...acc, stack];
function getStacks(app)
// Express 3
if (app.routes)
// convert to express 4
return Object.keys(app.routes)
.reduce((acc, method) => [...acc, ...app.routes[method]], [])
.map((route) => ( route: stack: [route] ));
// Express 4
if (app._router && app._router.stack)
return app._router.stack.reduce(combineStacks, []);
// Express 4 Router
if (app.stack)
return app.stack.reduce(combineStacks, []);
// Express 5
if (app.router && app.router.stack)
return app.router.stack.reduce(combineStacks, []);
return [];
function expressListRoutes(app, opts)
const stacks = getStacks(app);
const options = ...defaultOptions, ...opts ;
if (stacks)
for (const stack of stacks)
if (stack.route)
const routeLogged = ;
for (const route of stack.route.stack)
const method = route.method ? route.method.toUpperCase() : null;
if (!routeLogged[method] && method)
const stackMethod = colorMethod(method);
const stackSpace = spacer(options.spacer - method.length);
const stackPath = path.resolve(
[options.prefix, stack.routerPath, stack.route.path, route.path].filter((s) => !!s).join(''),
);
console.info(stackMethod, stackSpace, stackPath);
routeLogged[method] = true;
;
expressListRoutes(app)
list(1);
如果你运行它,就会发生这种情况
获取 C: 获取 C:\home
【讨论】:
【参考方案30】:对于 express 4.x
这是一个总 1 班轮,适用于添加到 app
的路线和添加到 express.Router()
的路线。
它返回这个结构。
[
"path": "/api",
"methods":
"get": true
,
"path": "/api/servermembers/",
"methods":
"get": true
,
"path": "/api/servermembers/find/:query",
"methods":
"get": true
]
使用express.Router()
的模块需要像这样导出:
module.exports =
router,
path: "/servermembers",
;
并像这样添加:
app.use(`/api$ServerMemberRoutes.path`, ServerMemberRoutes.router);
app.get(
"/api",
/**
* Gets the API's available routes.
* @param request _req
* @param response res
*/
(_req, res) =>
res.json(
[app._router, ServerMemberRoutes]
.map((routeInfo) => (
entityPath: routeInfo.path || "",
stack: (routeInfo?.router?.stack || routeInfo.stack).filter(
(stack) => stack.route
),
))
.map(( entityPath, stack ) =>
stack.map(( route: path, methods ) => (
path: entityPath ? `/api$entityPath$path` : path,
methods,
))
).flat()
);
);
当然,如果需要,/api
基本 url 前缀也可以存储在变量中。
【讨论】:
以上是关于如何在 Express 中获取所有已注册的路线?的主要内容,如果未能解决你的问题,请参考以下文章
如何仅在丢失的路线上将 Express.js 设置为 404?
Node.js_express_中间件 middleware_登录/注册实例