请求信息获取

处理请求时,经常需要获取各种请求信息。Gin 的 Context 提供了丰富的方法来获取这些信息。

获取请求方法

r.Any("/method", func(c *gin.Context) {
    method := c.Request.Method
    
    if c.Request.Method == "GET" {
    }
    
    if c.Request.Method == "POST" {
    }
    
    c.String(200, "Method: %s", method)
})

获取请求路径

r.GET("/path/*action", func(c *gin.Context) {
    path := c.Request.URL.Path
    fullPath := c.FullPath()
    action := c.Param("action")
    
    c.JSON(200, gin.H{
        "path":     path,
        "fullPath": fullPath,
        "action":   action,
    })
})

获取客户端 IP

r.GET("/ip", func(c *gin.Context) {
    ip := c.ClientIP()
    
    c.String(200, "Your IP: %s", ip)
})

ClientIP() 会依次检查:

  1. X-Forwarded-For 头
  2. X-Real-IP 头
  3. RemoteAddr

获取请求头

r.GET("/headers", func(c *gin.Context) {
    auth := c.GetHeader("Authorization")
    contentType := c.ContentType()
    userAgent := c.UserAgent()
    referer := c.GetHeader("Referer")
    
    allHeaders := c.Request.Header
    
    c.JSON(200, gin.H{
        "authorization": auth,
        "contentType":   contentType,
        "userAgent":     userAgent,
        "referer":       referer,
        "all":           allHeaders,
    })
})

获取查询参数

r.GET("/search", func(c *gin.Context) {
    q := c.Query("q")
    page := c.DefaultQuery("page", "1")
    size := c.DefaultQuery("size", "10")
    
    allQuery := c.Request.URL.Query()
    
    c.JSON(200, gin.H{
        "q":    q,
        "page": page,
        "size": size,
        "all":  allQuery,
    })
})

获取表单参数

r.POST("/form", func(c *gin.Context) {
    username := c.PostForm("username")
    password := c.PostForm("password")
    remember := c.DefaultPostForm("remember", "false")
    
    c.JSON(200, gin.H{
        "username": username,
        "password": password,
        "remember": remember,
    })
})

获取路由参数

r.GET("/users/:id", func(c *gin.Context) {
    id := c.Param("id")
    c.String(200, "User ID: %s", id)
})

r.GET("/files/*filepath", func(c *gin.Context) {
    filepath := c.Param("filepath")
    c.String(200, "File: %s", filepath)
})

获取请求体

r.POST("/body", func(c *gin.Context) {
    body, err := c.GetRawData()
    if err != nil {
        c.String(400, "Error reading body")
        return
    }
    
    c.String(200, "Body: %s", string(body))
})

获取文件上传信息

r.POST("/upload", func(c *gin.Context) {
    file, err := c.FormFile("file")
    if err != nil {
        c.String(400, "No file")
        return
    }
    
    c.JSON(200, gin.H{
        "filename": file.Filename,
        "size":     file.Size,
        "header":   file.Header,
    })
})

判断请求类型

r.POST("/check", func(c *gin.Context) {
    contentType := c.ContentType()
    
    var result string
    switch {
    case strings.Contains(contentType, "application/json"):
        result = "JSON 请求"
    case strings.Contains(contentType, "application/x-www-form-urlencoded"):
        result = "表单请求"
    case strings.Contains(contentType, "multipart/form-data"):
        result = "文件上传请求"
    default:
        result = "其他类型请求"
    }
    
    c.String(200, result)
})

获取完整请求信息

r.GET("/request-info", func(c *gin.Context) {
    info := gin.H{
        "method":        c.Request.Method,
        "url":           c.Request.URL.String(),
        "path":          c.Request.URL.Path,
        "fullPath":      c.FullPath(),
        "host":          c.Request.Host,
        "clientIP":      c.ClientIP(),
        "contentType":   c.ContentType(),
        "userAgent":     c.UserAgent(),
        "referer":       c.GetHeader("Referer"),
        "contentLength": c.Request.ContentLength,
        "headers":       c.Request.Header,
        "query":         c.Request.URL.Query(),
        "cookies":       c.Request.Cookies(),
        "isWebSocket":   c.IsWebsocket(),
        "scheme":        c.Request.URL.Scheme,
    }
    
    c.JSON(200, info)
})

解析 JSON 请求体

type LoginRequest struct {
    Username string `json:"username" binding:"required"`
    Password string `json:"password" binding:"required"`
}

r.POST("/login", func(c *gin.Context) {
    var req LoginRequest
    if err := c.ShouldBindJSON(&req); err != nil {
        c.JSON(400, gin.H{"error": err.Error()})
        return
    }
    
    c.JSON(200, gin.H{
        "username": req.Username,
    })
})

获取原始请求对象

如果需要访问原始的 http.Request

r.GET("/raw", func(c *gin.Context) {
    req := c.Request
    
    req.Method
    req.URL
    req.Header
    req.Body
    req.Cookies()
    req.Context()
    
    c.String(200, "OK")
})

小结

Gin 提供了丰富的请求信息获取方法,大部分场景下不需要直接访问 c.Request。记住 Query 用于 URL 参数,PostForm 用于表单参数,Param 用于路由参数,GetHeader 用于请求头。