Files
go-omni/transport/README.md

4.7 KiB
Raw Permalink Blame History

Transport adapters

业务 Handler 依赖 GoOmni 的 httpx.Context,Service 接收标准 context.Context。适配器只在启动入口组装:

import (
    omni "git.yuntuo.hk/k2safe/go-omni"
    netrouter "git.yuntuo.hk/k2safe/go-omni/transport/nethttp"
)

application := omni.NewWithRouter(netrouter.New())
registerRoutes(application) // 与 omni.New() 复用同一份业务注册代码

transport/nethttp 是当前内置的标准库路由实现。它提供一套可移植的路径、方法和错误回退规则;自研网络层可以直接实现同一个 httpx.Router 契约。

可移植路由规则(v0.3.0)

项目 约定
路径 顶层路由必须以 / 开头;区分大小写。禁止重复斜杠、. / .. 段、查询串和片段标识。
参数 /users/:id 匹配一个非空路径段;参数必须占据整个段,同一路由内名称唯一。
通配 /files/*path 仅允许出现在末尾,值包含开头的 /;/files/ 对应 /,/files 不匹配。
路由优先级 相同方法内,从左向右比较,静态段优先于参数段;更具体的分支匹配失败后允许回退。
注册冲突 同方法重复注册、相同前缀处参数名冲突、catch-all 与同级分支冲突,均在注册时 panic。不同方法可用同一路径。
分组 支持嵌套与相对路径。Group("/api").Handle("GET", "", h) 注册 /api,传 "/" 则注册 /api/。
尾部斜杠 /users 与 /users/ 是不同路由;不自动重定向、补斜杠或清理请求路径。
URL 编码 使用已解码的 URL.Path;例如 %2F 作为路径分隔符,+ 保留为加号。
方法 Handle 接受大写字母组成的方法名;HEAD 不自动复用 GET,OPTIONS 不自动成功。
Any 注册 GET、POST、PUT、PATCH、HEAD、OPTIONS、DELETE、CONNECT、TRACE 九种方法;其他方法需显式注册。
404 / 405 未找到路径返回纯文本 404;路径存在但方法不支持时返回纯文本 405,Allow 去重并按字母排序。
并发 启动前完成路由注册;允许并发处理请求,各请求参数、业务值、requestId 必须隔离。

HTTP 回退响应属于路由层,不进入应用路由中间件,不携带统一 JSON 封装或 requestId。业务 Handler 返回的错误则经过统一 JSON 错误处理。

业务层通过 application.Handle("HEAD", path, handler) 或 group.Handle("OPTIONS", path, handler) 显式注册其他方法,同样经过框架中间件和错误处理。

业务行为

  • 同一套 Handler、Service、中间件用于两种适配器;应用、分组、嵌套分组、路由中间件依次进入、反序退出。
  • Use 只影响后续注册的路由。鉴权失败短路处理链,panic 转为统一 500。
  • URI / Query / JSON 绑定、业务错误、requestId 与业务日志关联一致。
  • JSON / OK 等方法先编码再发送;编码失败返回统一 500。已通过 Context 提交响应后,后续错误、panic 或重复响应不会追加 JSON。
  • 客户端断开会取消传入 Service 的 context;适配时保留原有 context 的值、截止时间和取消信号。
  • Raw() 是高级逃生口;直接写入、流式响应、Hijack 等行为不属于上述 Context 响应追踪契约,勿与自动响应方法混用。

自研适配器验收

实现 httpx.Router / httpx.RouterGroup,在调用 Handler 前通过 httpx.WithRouteParams 和 httpx.WithRoutePattern 注入请求元数据。使用外部测试包接入公共验收套件:

package myrouter_test

import (
    "testing"
    "git.yuntuo.hk/k2safe/go-omni/httpx"
    "git.yuntuo.hk/k2safe/go-omni/transport/transporttest"
    "example.com/project/myrouter"
)

func TestContract(t *testing.T) {
    transporttest.Run(t, func() httpx.Router { return myrouter.New() })
}

工厂需每次返回新的空路由器。套件依次创建路由器,内部会发送并发请求、打开本地 HTTP 测试服务,运行时应启用 race 检查:

go test -race ./transport/... ./examples/reference
python3 scripts/verifyTransports.py --version v0.4.0

第一条验证标准库适配器复用完整 Handler / Service / Repository。第二条在源码目录外创建无 replace 的消费模块,从远程版本导入同一套验收包;自研适配器也应使用同一个公共测试包。

当前替换边界是路由与 HTTP 适配层,App.Run 仍使用标准库 net/http.Server。未来自研监听、连接管理或协议解析时,可让自研服务调用 App.ServeHTTP(提供标准 HTTP 请求/响应桥接),由自研启动层管理监听与关闭,并在退出时调用 App.Close;本阶段没有实现新的网络内核。