跨源资源共享
hertz 提供 cors 跨域中间件的实现。
Hertz中间件的种类是多种多样的,简单分为两大类:
Hertz 服务端中间件是 HTTP 请求-响应周期中的一个函数,提供了一种方便的机制来检查和过滤进入应用程序的 HTTP 请求, 例如记录每个请求或者启用CORS。
图1:中间件调用链 |
中间件可以在请求更深入地传递到业务逻辑之前或之后执行:
.Next
,如图1的中间件 B。.Next
,如图1的中间件 C。// 方式一
func MyMiddleware() app.HandlerFunc {
return func(ctx context.Context, c *app.RequestContext) {
// pre-handle
// ...
c.Next(ctx)
}
}
// 方式二
func MyMiddleware() app.HandlerFunc {
return func(ctx context.Context, c *app.RequestContext) {
c.Next(ctx) // call the next middleware(handler)
// post-handle
// ...
}
}
中间件会按定义的先后顺序依次执行,如果想快速终止中间件调用,可以使用以下方法,注意当前中间件仍将执行。
Abort()
:终止后续调用AbortWithMsg(msg string, statusCode int)
:终止后续调用,并设置 response中body,和状态码AbortWithStatus(code int)
:终止后续调用,并设置状态码Server 级别中间件会对整个server的路由生效
h := server.Default()
h.Use(GlobalMiddleware())
路由组级别中间件对当前路由组下的路径生效
h := server.Default()
group := h.Group("/group")
group.Use(GroupMiddleware())
或者
package main
import (
"context"
"fmt"
"github.com/cloudwego/hertz/pkg/app"
"github.com/cloudwego/hertz/pkg/app/server"
)
func GroupMiddleware() []app.HandlerFunc {
return []app.HandlerFunc{func(ctx context.Context, c *app.RequestContext) {
fmt.Println("group middleware")
c.Next(ctx)
}}
}
func main() {
h := server.Default(server.WithHostPorts("127.0.0.1:8888"))
group := h.Group("/group", append(GroupMiddleware(),
func(ctx context.Context, c *app.RequestContext) {
fmt.Println("group middleware 2")
c.Next(ctx)
})...)
// ...
h.Spin()
}
单一路由级别中间件只对当前路径生效
package main
import (
"context"
"fmt"
"net/http"
"github.com/cloudwego/hertz/pkg/app"
"github.com/cloudwego/hertz/pkg/app/server"
)
func PathMiddleware() []app.HandlerFunc {
return []app.HandlerFunc{func(ctx context.Context, c *app.RequestContext) {
fmt.Println("path middleware")
c.Next(ctx)
}}
}
func main() {
h := server.Default(server.WithHostPorts("127.0.0.1:8888"))
h.GET("/path", append(PathMiddleware(),
func(ctx context.Context, c *app.RequestContext) {
c.String(http.StatusOK, "path")
})...)
h.Spin()
}
如果你使用hz工具和IDL开发项目、router文件夹下会自动根据服务和方法生成路由组中间件和单一方法中间件模板,你可以在其中添加相应的逻辑,定制自己的个性化中间件。
Hertz 框架已经预置了常用的 recover 中间件,使用 server.Default()
默认可以注册该中间件。
Hertz 提供了常用的 BasicAuth、CORS、JWT等中间件,更多实现可以在 hertz-contrib 查找,其他中间件如有需求,可提 issue 告诉我们。
客户端中间件可以在请求发出之前或获取响应之后执行:
客户端中间件实现和服务端中间件不同。Client 侧无法拿到中间件 index 实现递增,因此 Client 中间件采用提前构建嵌套函数的形式实现,在实现一个中间件时,可以参考下面的代码。
func MyMiddleware(next client.Endpoint) client.Endpoint {
return func(ctx context.Context, req *protocol.Request, resp *protocol.Response) (err error) {
// pre-handle
// ...
err = next(ctx, req, resp)
if err != nil {
return
}
// post-handle
// ...
}
}
注意:必须执行
next
方法才能继续调用后续中间件。如果想停止中间件调用,在next
之前返回就可以了。
注册中间件的方式和 Server 相同
c, err := client.NewClient()
c.Use(MyMiddleware)
package main
import (
"context"
"fmt"
"github.com/cloudwego/hertz/pkg/app/client"
"github.com/cloudwego/hertz/pkg/protocol"
)
func MyMiddleware(next client.Endpoint) client.Endpoint {
return func(ctx context.Context, req *protocol.Request, resp *protocol.Response) (err error) {
// pre-handle
// ...
fmt.Println("before request")
req.AppendBodyString("k1=v1&")
err = next(ctx, req, resp)
if err != nil {
return
}
// post-handle
// ...
fmt.Println("after request")
return nil
}
}
func main() {
client, _ := client.NewClient()
client.Use(MyMiddleware)
statusCode, body, err := client.Post(context.Background(),
[]byte{},
"http://httpbin.org/redirect-to?url=http%3A%2F%2Fhttpbin.org%2Fpost&status_code=302",
&protocol.Args{})
fmt.Printf("%d, %s, %s", statusCode, body, err)
}
中间件可能执行不止一次,比如发生跳转等,需要考虑幂等性
hertz 提供 cors 跨域中间件的实现。
Recovery 中间件是 Hertz 框架预置的中间件,为 Hertz 框架提供 panic 恢复的功能。
Hertz 提供了 basic auth 的实现。
Hertz 提供了 jwt 的实现。
Hertz 提供了 Gzip 的实现。
Hertz 提供了国际化 (i18n) 的中间件扩展 。
Hertz 提供了 Session 的实现。
Hertz 提供了 pprof 扩展,帮助用户对 Hertz 项目进行性能分析。
Hertz 提供了 keyauth 扩展用于帮助用户实现 token
鉴权。
用 Swagger 2.0 来自动生成 RESTful API 文档的 Hertz 中间件。
Hertz 提供了可以对 X-Request-ID
进行操作的 Request ID 中间件。
访问日志可以收集所有 HTTP 请求的详细信息,包括时间、端口、请求方法等。Hertz 也提供了 access log 的实现。
Secure 是 Hertz 的一个 HTTP 中间件 , 它可以通过检查 HTTP 请求以达到快速的保证访问请求安全。
Hertz 通过使用中间件 hertzsentry,整合了 Sentry-Go 的 SDK。
Hertz 提供了 CSRF 中间件,可帮助您防止跨站点请求伪造攻击。
针对用户的使用场景,提供 Casbin 中间件,对 Hertz 进行了适配。
Hertz 提供了可以对 ETag
进行操作的 ETag 中间件。
Hertz 提供了对 cache 的适配,支持 multi-backend。
这是为 Hertz 实现的 PASETO 中间件。