golang,go,博客,开源,编程

gin中间件打印请求、响应报文补充打印header

Published on with 0 views and 0 comments

Gin 中,你可以通过自定义中间件来打印请求和响应的头部信息(Headers)。通过这种方式,你可以捕获和记录每个 HTTP 请求和响应的详细信息。下面是一个示例,展示如何创建中间件来打印请求的头部信息、响应的头部信息,并记录相关的日志。

1. 打印请求和响应头的中间件

以下是一个简单的 Gin 中间件示例,它将打印 HTTP 请求的头部信息以及响应的头部信息:

package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"log"
	"time"

	"github.com/gin-gonic/gin"
)

// 自定义Writer以捕获响应头部信息
type ResponseWriterWrapper struct {
	gin.ResponseWriter
	body *bytes.Buffer
}

func (rw *ResponseWriterWrapper) Write(b []byte) (int, error) {
	rw.body.Write(b)
	return rw.ResponseWriter.Write(b)
}

// 请求和响应头部信息日志中间件
func RequestLogger() gin.HandlerFunc {
	return func(c *gin.Context) {
		// 获取请求的开始时间
		start := time.Now()

		// 读取请求体(如果有)
		body, _ := ioutil.ReadAll(c.Request.Body)
		// 恢复请求体,以便后续处理
		c.Request.Body = ioutil.NopCloser(bytes.NewReader(body))

		// 打印请求信息
		log.Printf("Request Method: %s", c.Request.Method)
		log.Printf("Request URL: %s", c.Request.URL)
		log.Printf("Request Headers: %+v", c.Request.Header)
		log.Printf("Request Body: %s", string(body))

		// 创建ResponseWriterWrapper来捕获响应头和响应体
		rw := &ResponseWriterWrapper{ResponseWriter: c.Writer, body: bytes.NewBufferString("")}
		c.Writer = rw

		// 继续处理请求
		c.Next()

		// 打印响应信息
		duration := time.Since(start)
		log.Printf("Response Status: %d", c.Writer.Status())
		log.Printf("Response Headers: %+v", c.Writer.Header())
		log.Printf("Response Body: %s", rw.body.String())
		log.Printf("Duration: %v", duration)
	}
}

func main() {
	// 初始化Gin
	r := gin.Default()

	// 使用自定义的请求日志中间件
	r.Use(RequestLogger())

	// 示例路由
	r.POST("/example", func(c *gin.Context) {
		// 设置响应头部
		c.Header("X-Custom-Header", "CustomHeaderValue")
		// 返回响应
		c.JSON(200, gin.H{
			"message": "Request received",
		})
	})

	// 启动服务器
	r.Run(":8080")
}

2. 代码解析

  • ResponseWriterWrapper
    • 我们通过一个自定义的 ResponseWriterWrapper 来捕获响应体和响应头。该结构体包装了 Gin 的默认 ResponseWriter,并通过 Write 方法记录响应内容。
  • RequestLogger 中间件
    • 该中间件会打印 请求头c.Request.Header)、请求体请求方法请求 URL
    • 接着,它会创建一个 ResponseWriterWrapper 来捕获响应头和响应体,并打印 响应头c.Writer.Header())和 响应体
  • 请求和响应头部的输出
    • 请求头:通过 c.Request.Header 访问。
    • 响应头:通过 c.Writer.Header() 访问。
    • 还可以记录请求体(如果有的话)和响应体。

3. 启动应用

启动程序后,访问 http://localhost:8080/example 并发送一个 POST 请求。日志将会打印出类似如下的请求和响应头部信息:

Request Method: POST
Request URL: /example
Request Headers: map[Content-Type:[application/json] User-Agent:[Go-http-client/1.1]]
Request Body: {"name": "John"}
Response Status: 200
Response Headers: map[X-Custom-Header:[CustomHeaderValue] Content-Type:[application/json]; charset=utf-8]]
Response Body: {"message":"Request received"}
Duration: 12.34ms

4. 日志说明

  • Request Headers:显示请求的所有头部信息,例如 Content-TypeUser-Agent
  • Response Headers:显示响应的所有头部信息,在这个例子中,我们设置了一个自定义响应头 X-Custom-Header
  • Request Body:如果请求包含 body(例如 POST 请求),会显示请求体的内容。
  • Response Body:显示返回给客户端的响应体内容(例如返回的 JSON 数据)。
  • Duration:处理请求的时间,帮助你分析请求的性能。

5. 进一步优化

  • 如果你不想每次都打印日志,可以考虑根据环境(开发、生产)来决定是否启用该中间件。
  • 你可以将日志写入文件或使用更强大的日志框架(如 zaplogrus)来替换标准日志。
import "github.com/gin-gonic/gin"

// 使用 zap 或 logrus 等高级日志库
import "go.uber.org/zap"

var logger, _ = zap.NewProduction()

func RequestLogger() gin.HandlerFunc {
    return func(c *gin.Context) {
        start := time.Now()
        body, _ := ioutil.ReadAll(c.Request.Body)
        c.Request.Body = ioutil.NopCloser(bytes.NewReader(body))

        // 使用 zap 记录日志
        logger.Info("Request Received",
            zap.String("method", c.Request.Method),
            zap.String("url", c.Request.URL.String()),
            zap.Any("headers", c.Request.Header),
            zap.String("body", string(body)),
        )

        rw := &ResponseWriterWrapper{ResponseWriter: c.Writer, body: bytes.NewBufferString("")}
        c.Writer = rw
        c.Next()

        logger.Info("Response Sent",
            zap.Int("status", c.Writer.Status()),
            zap.Any("response_headers", c.Writer.Header()),
            zap.String("response_body", rw.body.String()),
            zap.Duration("duration", time.Since(start)),
        )
    }
}

总结

通过 Gin 中间件,你可以方便地打印 HTTP 请求和响应的头部信息。这对于调试、性能监控和日志记录非常有用,可以帮助开发者实时了解请求和响应的内容和性能表现。


标题:gin中间件打印请求、响应报文补充打印header
作者:mooncakeee
地址:http://blog.dd95828.com/articles/2025/01/07/1736218153594.html
联系:scotttu@163.com