基本介绍
路由声明覆盖插件HTTP路由的注册和绑定。源码插件通过pluginhost.Declarations.HTTP()注册路由贡献回调,由主框架启动时统一触发;动态插件通过pluginbridge.Declarations.Routes()声明路由组绑定。
能力阶段:声明期
类型支持:源码插件、动态插件
能力设计
路由注册模型
API命名空间
所有插件路由挂载在/x/{plugin-id}/命名空间下:
| 常量 | 值 | 说明 |
|---|---|---|
PluginAPINamespaceSegment | x | API路径段 |
PluginAPINamespacePrefix | /x | API路径前缀 |
源码插件的RouteRegistrar.APIPrefix()返回/x/{plugin-id},动态插件的路由前缀同样遵循此规则。
中间件体系
源码插件通过RouteMiddlewares访问宿主提供的八个标准中间件:
| 中间件 | 说明 |
|---|---|
NeverDoneCtx | 防止请求上下文超时的中间件 |
HandlerResponse | 统一响应格式中间件 |
CORS | 跨域资源共享中间件 |
RequestBodyLimit | 请求体大小限制中间件 |
Ctx | 请求上下文注入中间件 |
Auth | 认证中间件 |
Tenancy | 租户隔离中间件 |
Permission | 权限校验中间件 |
全局中间件
源码插件可以通过GlobalMiddlewareRegistrar注册全局中间件,作用于所有请求:
| 字段 | 说明 |
|---|---|
scope | 中间件作用域 |
handler | 中间件处理函数 |
路由绑定
路由绑定定义HTTP方法、路径和处理器的映射关系。每个绑定包含以下元数据:
| 字段 | 说明 |
|---|---|
Method | HTTP方法(GET、POST、PUT、DELETE等) |
Path | 路由路径,相对于API前缀 |
Access | 访问模式:public(公开)或login(需要登录) |
Permission | 权限标识,格式为{plugin-id}:{resource}:{action} |
Summary | 接口摘要 |
Description | 接口描述 |
接口定义
源码插件接口
源码插件通过HTTP()注册路由贡献回调:
| 方法 | 说明 |
|---|---|
RegisterRoutes | 注册路由贡献回调,由主框架启动时统一触发 |
回调处理器通过HTTPRegistrar访问路由注册能力:
| 方法 | 说明 |
|---|---|
Routes() | 返回RouteRegistrar,用于注册路由组 |
GlobalMiddlewares() | 返回GlobalMiddlewareRegistrar,用于注册全局中间件 |
Services() | 返回Services,用于访问宿主能力 |
RouteRegistrar接口:
| 方法 | 说明 |
|---|---|
APIPrefix() | 返回当前插件的API前缀 |
Group() | 注册路由组 |
Middlewares() | 返回标准中间件集合 |
RouteBindings() | 返回已注册的路由绑定列表 |
Err() | 返回注册过程中的错误 |
RouteGroup接口支持标准HTTP方法注册:
| 方法 | 说明 |
|---|---|
ALL | 注册所有方法的路由 |
GET | 注册GET路由 |
POST | 注册POST路由 |
PUT | 注册PUT路由 |
DELETE | 注册DELETE路由 |
PATCH | 注册PATCH路由 |
HEAD | 注册HEAD路由 |
CONNECT | 注册CONNECT路由 |
OPTIONS | 注册OPTIONS路由 |
TRACE | 注册TRACE路由 |
Group | 嵌套路由组 |
Middleware | 注册组级中间件 |
Bind | 绑定路由处理器 |
Err() | 返回注册过程中的错误 |
动态插件接口
动态插件通过pluginbridge.Declarations.Routes()声明路由组绑定:
| 方法 | 说明 |
|---|---|
Group | 声明路由组绑定,指定API前缀和路由包 |
动态插件的路由通过RouteContract定义:
| 字段 | 类型 | 说明 |
|---|---|---|
path | string | 路由路径,必须以/开头 |
method | string | HTTP方法,自动转为大写 |
access | string | 访问模式:public或login |
permission | string | 权限标识 |
summary | string | 接口摘要 |
description | string | 接口描述 |
requestType | string | 请求DTO名称 |
能力使用
源码插件使用
源码插件在init()中注册路由贡献回调,再在回调中使用HTTPRegistrar注册路由:
func init() {
plugin := pluginhost.NewDeclarations("my-author-my-domain-my-cap")
if err := plugin.HTTP().RegisterRoutes(
pluginhost.ExtensionPointHTTPRouteRegister,
pluginhost.CallbackExecutionModeBlocking,
registerRoutes,
); err != nil {
panic(err)
}
if err := pluginhost.RegisterSourcePlugin(plugin); err != nil {
panic(err)
}
}
// 在注册回调中
func registerRoutes(ctx context.Context, registrar pluginhost.HTTPRegistrar) error {
routes := registrar.Routes()
middlewares := routes.Middlewares()
routes.Group("/reports", func(group pluginhost.RouteGroup) {
group.Middleware(middlewares.Auth())
group.Middleware(middlewares.Tenancy())
group.Middleware(middlewares.Permission())
group.GET("/", listReports)
group.GET("/:id", getReport)
group.POST("/", createReport)
group.PUT("/:id", updateReport)
group.DELETE("/:id", deleteReport)
})
return routes.Err()
}
注册全局中间件:
func registerGlobalMiddleware(ctx context.Context, registrar pluginhost.HTTPRegistrar) error {
return registrar.GlobalMiddlewares().Bind(
"", // 空字符串默认匹配所有路径 "/*"
func(r *ghttp.Request) {
// 全局中间件逻辑
r.Middleware.Next()
},
)
}
动态插件使用
动态插件通过Routes()声明路由组绑定:
func RegisterPlugin(ctx context.Context) error {
decl := pluginbridge.NewDeclarations()
// 声明路由组绑定
err := decl.Routes().Group("/reports", "controllers")
if err != nil {
return err
}
return nil
}
动态插件的路由控制器使用标准HTTP方法签名:
//go:build wasm
package controllers
type ReportController struct{}
func (c *ReportController) Get(ctx context.Context, req *GetReportReq) (*ReportResp, error) {
// 处理GET请求
}
func (c *ReportController) Post(ctx context.Context, req *CreateReportReq) (*ReportResp, error) {
// 处理POST请求
}
构建工具会自动生成RouteContract并嵌入.wasm产物的lina.plugin.backend.routes自定义段。
设计约束
- 路由挂载在插件命名空间下。 所有插件路由必须在
/x/{plugin-id}/前缀下。 - 注册回调在启动时触发。 源码插件的路由注册回调在宿主启动时统一触发,不是运行时动态注册。
- 中间件链由插件组装。 插件根据业务需要选择和组合中间件,宿主不强制中间件顺序。
- 权限标识格式必须规范。 权限标识必须符合
{plugin-id}:{resource}:{action}格式。 - 动态插件路由通过契约声明。 动态插件的路由在构建期通过
RouteContract声明,不支持运行时动态注册。 - 路由路径必须以
/开头。 宿主校验路由路径格式,拒绝不合法的路径。