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;本阶段没有实现新的网络内核。