为 gin 框架做不同用途的中间件时一般都需要获取到请求体和响应体的一些数据,例如做签名插件需要获取到请求参数、请求内容和 header,做鉴权插件需要获取到 header 的某些值,做日志插件需要的数据就更多了。下面就使用代码演示各种数据的获取方法:
package middleware
import (
"bytes"
"fmt"
"github.com/gin-gonic/gin"
"io"
"time"
)
//自定义一个结构体,实现 gin.ResponseWriter interfacetype responseWriter struct {
gin.ResponseWriter
b *bytes.Buffer
}
//重写 Write([]byte) (int, error) 方法func(w responseWriter)Write(b []byte)(int, error) {
//向一个bytes.buffer中写一份数据来为获取body使用
w.b.Write(b)
//完成gin.Context.Writer.Write()原有功能
return w.ResponseWriter.Write(b)
}
funcTestMiddleware()gin.HandlerFunc {
returnfunc(c *gin.Context) {
start := time.Now()
//请求日期
requestData := start.Format(time.RFC3339)
//请求接口路由
path := c.Request.URL
//请求方式
requestMethod := c.Request.Method
//请求 header
requestHeader := c.Request.Header
//请求体 body
requestBody := ""
b, err := c.GetRawData()
if err != nil {
requestBody = "failed to get request body"
} else {
requestBody = string(b)
}
c.Request.Body = io.NopCloser(bytes.NewBuffer(b))
//请求 host
host := c.Request.Host
//协议及版本
schema := c.Request.Proto
//客户端IP
c.ClientIP()
writer := responseWriter{
c.Writer,
bytes.NewBuffer([]byte{}),
}
c.Writer = writer
c.Next()
//请求耗时
cost := time.Since(start).Milliseconds()
//响应状态码
responseStatus := c.Writer.Status()
//响应 header
responseHeader := c.Writer.Header()
//响应体大小
responseBodySize := c.Writer.Size()
//响应体 body
responseBody := writer.b.String()
}
}
获取请求体 body 和响应体 body 稍微有一点难度,获取响应体 body 的方法及原理可以参考之前的文章《获取 Gin 框架在中间件中获取 response body 的方法》,本文中获取请求体 body 还有更高性能的方式,敬请期待接下来的文章。