Skip to main content
Version: 2.0.0

Web 路由表

从 v2.8.0 开始,Midway 提供了内置的路由表能力,所有的 Web 框架都将使用这份路由表注册路由。

在应用启动,onReady 生命周期以及之后可用。

创建路由表收集器

import { WebRouterCollector } from '@midwayjs/core';
const collector = new WebRouterCollector();

路由信息定义

每个路由信息由一个 RouterInfo  定义表示,包含一些属性。

定义如下:

export interface RouterInfo {
/**
* router prefix
*/
prefix: string;
/**
* router alias name
*/
routerName: string;
/**
* router path, without prefix
*/
url: string | RegExp;
/**
* request method for http, like get/post/delete
*/
requestMethod: string;
/**
* invoke function method
*/
method: string;
description: string;
summary: string;
/**
* router handler function key,for IoC container load
*/
handlerName: string;
/**
* serverless func load key
*/
funcHandlerName: string;
/**
* controller provideId
*/
controllerId: string;
/**
* router middleware
*/
middleware: any[];
/**
* controller middleware in this router
*/
controllerMiddleware: any[];
/**
* request args metadata
*/
requestMetadata: any[];
/**
* response data metadata
*/
responseMetadata: any[];
}
属性类型描述
prefixstring路由前缀,比如 / 或者 /api,用户写在 @Controller 装饰器上的部分
routerNamestring路由名
urlstring路由的去除路由前缀的部分,也是用户写在 @Get 等装饰器上的部分
requestMethodstringget/post/delete/put/all 等
methodstring实际调用的类上的方法名
descriptionstring描述,路由装饰器上的参数
summarystring摘要,路由装饰器上的参数
handlerNamestring等价于 controllerId.method
funcHandlerNamestring使用 @Func 写的 handler 名字
controllerIdstringcontroller 的依赖注入容器的 key(providerId)
middlewarestring[]路由中间件字符串数组
controllerMiddlewarestring[]控制器中间件字符串数组
requestMetadataany[]请求参数的元数据,@Query/@Body 等元数据
responseMetadataany[]响应参数的元数据,@SetHeader/@ContentType 等元数据

路由优先级

以往我们需要关心路由的加载顺序,比如通配的 /* 比如在实际的 /abc 之后,否则会加载到错误的路由。在新版本中,我们对此种情况做了自动排序。

规则如下:

    1. 绝对路径规则优先级最高如 /ab/cb/e
    1. 星号只能出现最后且必须在/后面,如 /ab/cb/**
    1. 如果绝对路径和通配都能匹配一个路径时,绝对规则优先级高
    1. 有多个通配能匹配一个路径时,最长的规则匹配,如 /ab/ 和 /ab/cd/ 在匹配 /ab/cd/f 时命中 /ab/cd/**
    1. 如果 / 与 / 都能匹配 / ,但 / 的优先级高于 /

此规则也与 Serverless 下函数的路由规则保持一致。

简单理解为,“明确的路由优先级最高,长的路由优先级高,通配的优先级最低”。

比如,排序完的优先级如下(高到低):

/api/invoke/abc
/api/invoke/*
/api/abc
/api/*
/abc
/*

获取扁平化路由列表

获取当前所有可注册到 HTTP 服务的路由列表(包括 @Func/@Controller,以及一切按照标准信息注册的自定义装饰器)。

会按照优先级从高到低自动排序。

定义:

async getFlattenRouterTable(): Promise<RouterInfo[]>

获取路由表 API。

const result = await collector.getFlattenRouterTable();

输出示例:

[
{
prefix: '/',
routerName: '',
url: '/set_header',
requestMethod: 'get',
method: 'homeSet',
description: '',
summary: '',
handlerName: 'apiController.homeSet',
funcHandlerName: 'apiController.homeSet',
controllerId: 'apiController',
middleware: [],
controllerMiddleware: [],
requestMetadata: [],
responseMetadata: [
{
type: 'web:response_header',
setHeaders: {
ccc: 'ddd',
},
},
{
type: 'web:response_header',
setHeaders: {
bbb: 'aaa',
},
},
],
},
{
prefix: '/',
routerName: '',
url: '/ctx-body',
requestMethod: 'get',
method: 'getCtxBody',
description: '',
summary: '',
handlerName: 'apiController.getCtxBody',
funcHandlerName: 'apiController.getCtxBody',
controllerId: 'apiController',
middleware: [],
controllerMiddleware: [],
requestMetadata: [],
responseMetadata: [],
},
// ...
];

获取 Router 信息列表

在 Midway 中,每个 Controller 对应一个 Router 对象,每个 Router 都会有一个路由前缀(prefix),在此之中的所有路由都会按照上面的规则进行排序。

Router 本身也会按照 prefix 进行排序。

定义:

export interface RouterPriority {
prefix: string;
priority: number;
middleware: any[];
routerOptions: any;
controllerId: string;
}

async getRoutePriorityList(): Promise<RouterPriority[]>

Router 的数据相对简单。

属性类型描述
prefixstring路由前缀,比如 / 或者 /api,用户写在 @Controller 装饰器上的部分
prioritynumberRouter 的优先级,@Priority 装饰器填写的值,/ 根 Router 默认优先级最低,为 -999
middlewarestring[]控制器中间件字符串数组
controllerIdstringcontroller 的依赖注入容器的 key(providerId)
routerOptionsany@Controller 装饰器的 options

获取路由表 API。

const list = await collector.getRoutePriorityList();

输出示例:

[
{
prefix: '/case',
priority: 0,
middleware: [],
routerOptions: {
middleware: [],
sensitive: true,
},
controllerId: 'caseController',
},
{
prefix: '/user',
priority: 0,
middleware: [],
routerOptions: {
middleware: [],
sensitive: true,
},
controllerId: 'userController',
},
{
prefix: '/',
priority: -999,
middleware: [],
routerOptions: {
middleware: [],
sensitive: true,
},
controllerId: 'apiController',
},
];

获取带层级的路由

某些情况下,我们需要拿到带层级的路由,包括哪些路由在哪个控制器(Controller)下,这样能更好的创建路由。

Midway 也提供了获取带层级的路由表方法。层级内会按照优先级从高到低自动排序。

定义:

async getRouterTable(): Promise<Map<string, RouterInfo[]>>

获取层级路由表 API,返回的是个 Map,key 为控制器的路由前缀 prefix 字符串。未明确写明路由前缀的(比如函数或者其他场景),都将归为 / 路由前缀下。

const result = await collector.getRouterTable();

输出示例:

Map(3) {
'/' => [
{
prefix: '/',
routerName: '',
url: '/set_header',
requestMethod: 'get',
method: 'homeSet',
description: '',
summary: '',
handlerName: 'apiController.homeSet',
funcHandlerName: 'apiController.homeSet',
controllerId: 'apiController',
middleware: [],
controllerMiddleware: [],
requestMetadata: [],
responseMetadata: [Array],
},
{
prefix: '/',
routerName: '',
url: '/ctx-body',
requestMethod: 'get',
method: 'getCtxBody',
description: '',
summary: '',
handlerName: 'apiController.getCtxBody',
funcHandlerName: 'apiController.getCtxBody',
controllerId: 'apiController',
middleware: [],
controllerMiddleware: [],
requestMetadata: [],
responseMetadata: [],
},
// ...
]
}