Kratos2.0 支持Http请求模式,但对于Http请求的常见使用场景支撑的并不多,很多时候需要编程人员通过Filter和Middleware实现,以下是一种获取http请求来源IP的方式;
1.server/http.go NewHTTPServer 方法中添加Filter和Middleware
// NewHTTPServer new a HTTP server.
func NewHTTPServer(c *conf.Server, a *conf.Auth, user *service.UserService, logger log.Logger) *http.Server {
var opts = []http.ServerOption{
http.Middleware(
recovery.Recovery(),
validate.Validator(),
LocalHttpRequestMiddleware(),
selector.Server(authMiddleware(a)).Match(witheList()).Build(),
),
http.Filter(handlers.CORS(
handlers.AllowedHeaders([]string{"X-Requested-With", "Content-Type", "Authorization"}),
handlers.AllowedMethods([]string{"GET", "POST", "PUT", "HEAD", "OPTIONS"}),
handlers.AllowedOrigins([]string{"*"}),
), LocalHttpRequestFilter()),
}
if c.Http.Network != "" {
opts = append(opts, http.Network(c.Http.Network))
}
if c.Http.Addr != "" {
opts = append(opts, http.Address(c.Http.Addr))
}
if c.Http.Timeout != nil {
opts = append(opts, http.Timeout(c.Http.Timeout.AsDuration()))
}
srv := http.NewServer(opts...)
v1.RegisterUserHTTPServer(srv, user)
return srv
}
2. Filter主要功能是获取http请求的真实IP并填充到Header中
func LocalHttpRequestFilter() http.FilterFunc {
return func(next nhttp.Handler) nhttp.Handler {
return nhttp.HandlerFunc(func(w nhttp.ResponseWriter, req *nhttp.Request) {
req.Header.Add("X-RemoteAddr", strings.Split(req.RemoteAddr, ":")[0])
next.ServeHTTP(w, req)
})}
}
Filter 先于 Middleware 被执行,Filter执行后 Request 的相关信息会被存储到 ctx 中并传递下去,具体代码可以分析 kratos/v2/transport 模块的代码,此处不展开分析;
3.此处Middleware主要是解析ctx中的Header并取出真实IP
func LocalHttpRequestMiddleware() middleware.Middleware {
return func(handler middleware.Handler) middleware.Handler {
return func(ctx context.Context, req interface{}) (reply interface{}, err error) {
if tp, ok := transport.FromServerContext(ctx); ok {
println(fmt.Sprintf("remote_addr: %v",tp.RequestHeader().Get("RemoteAddr")))
}
return handler(ctx, req)
}
}
}
此处的ctx即service实现接口中注入的ctx,也可以直接在service中处理获得真实IP(此处Middleware仅作为演示使用,具体实现时可以忽略);
备注:对于Kratos微服务架构,个人并不建议用太多http请求,如果确需大量http api请求,建议还是使用Gin或Beego框架;