跳到主要内容
版本:0.4.x(Latest)

基本介绍

路由声明覆盖插件HTTP路由的注册和绑定。源码插件通过pluginhost.Declarations.HTTP()注册路由贡献回调,由主框架启动时统一触发;动态插件通过pluginbridge.Declarations.Routes()声明路由组绑定。

能力阶段:声明期

类型支持:源码插件、动态插件

能力设计

路由注册模型

API命名空间

所有插件路由挂载在/x/{plugin-id}/命名空间下:

常量说明
PluginAPINamespaceSegmentxAPI路径段
PluginAPINamespacePrefix/xAPI路径前缀

源码插件的RouteRegistrar.APIPrefix()返回/x/{plugin-id},动态插件的路由前缀同样遵循此规则。

中间件体系

源码插件通过RouteMiddlewares访问宿主提供的八个标准中间件:

中间件说明
NeverDoneCtx防止请求上下文超时的中间件
HandlerResponse统一响应格式中间件
CORS跨域资源共享中间件
RequestBodyLimit请求体大小限制中间件
Ctx请求上下文注入中间件
Auth认证中间件
Tenancy租户隔离中间件
Permission权限校验中间件

全局中间件

源码插件可以通过GlobalMiddlewareRegistrar注册全局中间件,作用于所有请求:

字段说明
scope中间件作用域
handler中间件处理函数

路由绑定

路由绑定定义HTTP方法、路径和处理器的映射关系。每个绑定包含以下元数据:

字段说明
MethodHTTP方法(GETPOSTPUTDELETE等)
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定义:

字段类型说明
pathstring路由路径,必须以/开头
methodstringHTTP方法,自动转为大写
accessstring访问模式:publiclogin
permissionstring权限标识
summarystring接口摘要
descriptionstring接口描述
requestTypestring请求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声明,不支持运行时动态注册。
  • 路由路径必须以/开头。 宿主校验路由路径格式,拒绝不合法的路径。

相关文档