Kratos HTTP接口通过http.Server实例注册transport.HTTPServer类型handler实现,需用func(ctx context.Context, w http.ResponseWriter, r *http.Request)签名并配合RequestContext提取traceID等信息。

Kratos 的 HTTP 接口不是靠“配置”出来的,而是靠 http.Server 实例 + http.Register 注册路由 + transport.HTTPServer 封装 handler 实现的;直接写 net/http 风格 handler 也能跑,但会丢失 Kratos 的中间件、日志、指标等能力。
如何注册一个标准的 HTTP handler(带 Kratos 上下文)
Kratos 要求 handler 必须是 transport.HTTPServer 类型,不能直接传 http.HandlerFunc。它内部会把原始 *http.Request 和 http.ResponseWriter 包装成 transport.Context,供中间件和业务逻辑使用。
常见错误:把 func(http.ResponseWriter, *http.Request) 直接塞进 http.Register —— 编译会报类型不匹配。
- 用
http.NewServer创建服务实例,再调用.Handle注册路径和 handler - handler 函数签名必须是
func(ctx context.Context, w http.ResponseWriter, r *http.Request) - 推荐用
transport/http提供的RequestContext提取 Kratos 的 traceID、logger 等信息
srv := http.NewServer(
http.Address(":8000"),
http.Middleware(
recovery.Recovery(),
logging.Server(logger),
),
)
srv.Handle("/ping", func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
l := log.FromContext(ctx)
l.Info("ping received")
w.WriteHeader(200)
w.Write([]byte("pong"))
})
如何把 Protobuf 定义的 API 自动生成 HTTP 路由
Kratos 支持通过 protoc 插件从 .proto 文件生成 Go handler 接口和默认路由注册代码,前提是 proto 中加了 google.api.http 扩展。
容易踩的坑:没启用 grpc-gateway 插件,或 proto 里漏写了 option (google.api.http) = { get: "/v1/ping" };,会导致生成器跳过 HTTP 路由部分。
- 确保
buf.gen.yaml或protoc命令中包含plugin: protoc-gen-go-http - 生成后会在
api/xxx/v1/xxx_http.pb.go里看到RegisterXXXHTTPServer函数 - 在
cmd/xxx/main.go中调用该函数注册到http.Server实例上 - 注意:生成的 handler 默认只做参数绑定和响应包装,业务逻辑仍需手动实现对应 method
为什么 /debug/pprof 不工作?
Kratos 默认不会自动挂载 /debug/pprof,它和主 HTTP server 是分离的——除非你显式把 http.DefaultServeMux 或自定义 mux 传进去,否则 pprof 服务根本没启动。
典型现象:访问 localhost:8000/debug/pprof 返回 404,但 net/http/pprof 包已导入。
- 正确做法是新建一个独立的
http.Server专跑 pprof,比如监听:6060 - 或者在主 server 的 mux 中手动注册:
mux := http.NewServeMux(); mux.Handle("/debug/pprof/", http.StripPrefix("/debug/pprof/", http.HandlerFunc(pprof.Index))) - 别依赖 “只要 import _ 'net/http/pprof' 就自动生效” —— Kratos 的
http.Server不复用http.DefaultServeMux
真正难的不是写 handler,而是理解 Kratos 的 transport 层怎么把原始 HTTP 请求转化成可被中间件链消费的上下文;一旦 route 绑定错、context 传丢了,日志打不出 traceID、metric 标签为空、recover 中间件捕不到 panic,问题就变得隐蔽。











