请求处理 #

一、请求参数 #

1.1 路径参数 #

go
// 必需参数
app.Get("/users/:id", func(c *fiber.Ctx) error {
    id := c.Params("id")
    return c.SendString("User ID: " + id)
})

// 多个参数
app.Get("/users/:userId/posts/:postId", func(c *fiber.Ctx) error {
    userId := c.Params("userId")
    postId := c.Params("postId")
    return c.JSON(fiber.Map{
        "user_id": userId,
        "post_id": postId,
    })
})

// 可选参数
app.Get("/search/:keyword?", func(c *fiber.Ctx) error {
    keyword := c.Params("keyword", "default")
    return c.SendString("Keyword: " + keyword)
})

// 整数参数
app.Get("/page/:num", func(c *fiber.Ctx) error {
    num := c.ParamsInt("num", 1)
    return c.SendString("Page: " + strconv.Itoa(num))
})

// 通配符
app.Get("/files/*", func(c *fiber.Ctx) error {
    path := c.Params("*")
    return c.SendString("Path: " + path)
})

1.2 查询参数 #

go
app.Get("/search", func(c *fiber.Ctx) error {
    // 字符串参数
    q := c.Query("q")
    page := c.Query("page", "1")
    
    // 整数参数
    limit := c.QueryInt("limit", 10)
    offset := c.QueryInt("offset", 0)
    
    // 布尔参数
    active := c.QueryBool("active", false)
    
    // 浮点参数
    price := c.QueryFloat("price", 0.0)
    
    // 所有参数
    all := c.Queries()
    
    return c.JSON(fiber.Map{
        "q":      q,
        "page":   page,
        "limit":  limit,
        "active": active,
        "price":  price,
        "all":    all,
    })
})

1.3 解析查询到结构体 #

go
type SearchQuery struct {
    Q      string `query:"q"`
    Page   int    `query:"page"`
    Limit  int    `query:"limit"`
    Sort   string `query:"sort"`
    Order  string `query:"order"`
}

app.Get("/users", func(c *fiber.Ctx) error {
    var query SearchQuery
    query.Page = 1
    query.Limit = 10
    query.Sort = "id"
    query.Order = "asc"
    
    if err := c.QueryParser(&query); err != nil {
        return c.Status(400).JSON(fiber.Map{
            "error": "Invalid query parameters",
        })
    }
    
    return c.JSON(query)
})

二、请求体解析 #

2.1 JSON解析 #

go
type User struct {
    Name  string `json:"name"`
    Email string `json:"email"`
    Age   int    `json:"age"`
}

app.Post("/users", func(c *fiber.Ctx) error {
    var user User
    if err := c.BodyParser(&user); err != nil {
        return c.Status(400).JSON(fiber.Map{
            "error": "Invalid JSON",
        })
    }
    return c.JSON(user)
})

2.2 表单解析 #

go
type LoginForm struct {
    Username string `form:"username"`
    Password string `form:"password"`
    Remember bool   `form:"remember"`
}

app.Post("/login", func(c *fiber.Ctx) error {
    var form LoginForm
    if err := c.BodyParser(&form); err != nil {
        return c.Status(400).JSON(fiber.Map{
            "error": "Invalid form data",
        })
    }
    return c.JSON(form)
})

2.3 多部分表单 #

go
app.Post("/upload", func(c *fiber.Ctx) error {
    // 获取表单字段
    name := c.FormValue("name")
    description := c.FormValue("description")
    
    // 获取文件
    file, err := c.FormFile("file")
    if err != nil {
        return c.Status(400).JSON(fiber.Map{
            "error": "File is required",
        })
    }
    
    // 保存文件
    if err := c.SaveFile(file, "./uploads/"+file.Filename); err != nil {
        return c.Status(500).JSON(fiber.Map{
            "error": "Failed to save file",
        })
    }
    
    return c.JSON(fiber.Map{
        "name":        name,
        "description": description,
        "filename":    file.Filename,
        "size":        file.Size,
    })
})

2.4 原始Body #

go
app.Post("/raw", func(c *fiber.Ctx) error {
    // 字节切片
    body := c.Body()
    
    // 字符串
    bodyStr := c.BodyString()
    
    return c.Send(body)
})

2.5 XML解析 #

go
type UserXML struct {
    XMLName xml.Name `xml:"user"`
    Name    string   `xml:"name"`
    Email   string   `xml:"email"`
}

app.Post("/xml", func(c *fiber.Ctx) error {
    var user UserXML
    if err := xml.Unmarshal(c.Body(), &user); err != nil {
        return c.Status(400).JSON(fiber.Map{
            "error": "Invalid XML",
        })
    }
    return c.JSON(user)
})

三、请求头 #

3.1 获取请求头 #

go
app.Get("/headers", func(c *fiber.Ctx) error {
    // 单个请求头
    contentType := c.Get("Content-Type")
    authorization := c.Get("Authorization")
    userAgent := c.Get("User-Agent")
    
    // 快捷方法
    host := c.Hostname()
    accept := c.Get("Accept")
    
    return c.JSON(fiber.Map{
        "content-type":  contentType,
        "authorization": authorization,
        "user-agent":    userAgent,
        "host":          host,
        "accept":        accept,
    })
})

3.2 遍历所有请求头 #

go
app.Get("/all-headers", func(c *fiber.Ctx) error {
    headers := make(map[string]string)
    
    c.Request().Header.VisitAll(func(key, value []byte) {
        headers[string(key)] = string(value)
    })
    
    return c.JSON(headers)
})

四、文件上传 #

4.1 单文件上传 #

go
app.Post("/upload", func(c *fiber.Ctx) error {
    // 获取文件
    file, err := c.FormFile("file")
    if err != nil {
        return c.Status(400).JSON(fiber.Map{
            "error": "File is required",
        })
    }
    
    // 文件信息
    fmt.Println("Filename:", file.Filename)
    fmt.Println("Size:", file.Size)
    fmt.Println("Header:", file.Header)
    
    // 保存文件
    err = c.SaveFile(file, "./uploads/"+file.Filename)
    if err != nil {
        return c.Status(500).JSON(fiber.Map{
            "error": "Failed to save file",
        })
    }
    
    return c.JSON(fiber.Map{
        "message":  "File uploaded successfully",
        "filename": file.Filename,
        "size":     file.Size,
    })
})

4.2 多文件上传 #

go
app.Post("/uploads", func(c *fiber.Ctx) error {
    // 解析多部分表单
    form, err := c.MultipartForm()
    if err != nil {
        return c.Status(400).JSON(fiber.Map{
            "error": "Invalid multipart form",
        })
    }
    
    // 获取所有文件
    files := form.File["files"]
    
    var results []fiber.Map
    for _, file := range files {
        // 保存文件
        err := c.SaveFile(file, "./uploads/"+file.Filename)
        if err != nil {
            results = append(results, fiber.Map{
                "filename": file.Filename,
                "error":    err.Error(),
            })
            continue
        }
        
        results = append(results, fiber.Map{
            "filename": file.Filename,
            "size":     file.Size,
            "status":   "uploaded",
        })
    }
    
    return c.JSON(fiber.Map{
        "total":  len(files),
        "files":  results,
    })
})

4.3 文件类型验证 #

go
func validateFileType(file *multipart.FileHeader) bool {
    allowedTypes := map[string]bool{
        "image/jpeg": true,
        "image/png":  true,
        "image/gif":  true,
        "application/pdf": true,
    }
    
    // 获取文件内容类型
    f, err := file.Open()
    if err != nil {
        return false
    }
    defer f.Close()
    
    buffer := make([]byte, 512)
    _, err = f.Read(buffer)
    if err != nil {
        return false
    }
    
    contentType := http.DetectContentType(buffer)
    return allowedTypes[contentType]
}

app.Post("/upload-safe", func(c *fiber.Ctx) error {
    file, err := c.FormFile("file")
    if err != nil {
        return c.Status(400).JSON(fiber.Map{
            "error": "File is required",
        })
    }
    
    if !validateFileType(file) {
        return c.Status(400).JSON(fiber.Map{
            "error": "Invalid file type",
        })
    }
    
    // 保存文件...
    return c.JSON(fiber.Map{"message": "OK"})
})

五、Cookie处理 #

5.1 获取Cookie #

go
app.Get("/get-cookie", func(c *fiber.Ctx) error {
    session := c.Cookies("session")
    token := c.Cookies("token", "default")
    
    return c.JSON(fiber.Map{
        "session": session,
        "token":   token,
    })
})

5.2 获取所有Cookie #

go
app.Get("/all-cookies", func(c *fiber.Ctx) error {
    cookies := make(map[string]string)
    
    c.Request().Header.VisitAllCookie(func(key, value []byte) {
        cookies[string(key)] = string(value)
    })
    
    return c.JSON(cookies)
})

六、请求信息 #

6.1 客户端信息 #

go
app.Get("/client-info", func(c *fiber.Ctx) error {
    return c.JSON(fiber.Map{
        "ip":         c.IP(),
        "ips":        c.IPs(),
        "hostname":   c.Hostname(),
        "protocol":   c.Protocol(),
        "secure":     c.Secure(),
        "user_agent": c.Get("User-Agent"),
        "referer":    c.Get("Referer"),
    })
})

6.2 请求方法判断 #

go
app.All("/check", func(c *fiber.Ctx) error {
    method := c.Method()
    
    switch method {
    case fiber.MethodGet:
        return c.SendString("GET request")
    case fiber.MethodPost:
        return c.SendString("POST request")
    case fiber.MethodPut:
        return c.SendString("PUT request")
    case fiber.MethodDelete:
        return c.SendString("DELETE request")
    default:
        return c.Status(405).SendString("Method not allowed")
    }
})

6.3 Content-Type判断 #

go
app.Post("/content", func(c *fiber.Ctx) error {
    contentType := c.Get("Content-Type")
    
    switch {
    case strings.Contains(contentType, "application/json"):
        // 处理JSON
        var data map[string]interface{}
        c.BodyParser(&data)
        return c.JSON(data)
        
    case strings.Contains(contentType, "application/x-www-form-urlencoded"):
        // 处理表单
        name := c.FormValue("name")
        return c.SendString("Form: " + name)
        
    case strings.Contains(contentType, "multipart/form-data"):
        // 处理文件上传
        file, _ := c.FormFile("file")
        return c.SendString("File: " + file.Filename)
        
    default:
        return c.Status(400).SendString("Unsupported content type")
    }
})

七、综合示例 #

7.1 完整请求处理 #

go
package main

import (
    "github.com/gofiber/fiber/v2"
)

type CreateUserRequest struct {
    Name     string `json:"name" validate:"required"`
    Email    string `json:"email" validate:"required,email"`
    Password string `json:"password" validate:"required,min=6"`
    Age      int    `json:"age" validate:"min=0,max=150"`
}

type UserResponse struct {
    ID       string `json:"id"`
    Name     string `json:"name"`
    Email    string `json:"email"`
    Age      int    `json:"age"`
    CreateAt string `json:"created_at"`
}

func main() {
    app := fiber.New()
    
    app.Post("/users", func(c *fiber.Ctx) error {
        // 解析请求体
        var req CreateUserRequest
        if err := c.BodyParser(&req); err != nil {
            return c.Status(400).JSON(fiber.Map{
                "error": "Invalid request body",
            })
        }
        
        // 验证请求
        if req.Name == "" {
            return c.Status(400).JSON(fiber.Map{
                "error": "Name is required",
            })
        }
        
        if req.Email == "" {
            return c.Status(400).JSON(fiber.Map{
                "error": "Email is required",
            })
        }
        
        // 创建用户
        user := UserResponse{
            ID:       "1",
            Name:     req.Name,
            Email:    req.Email,
            Age:      req.Age,
            CreateAt: "2024-01-01T00:00:00Z",
        }
        
        // 返回响应
        return c.Status(201).JSON(user)
    })
    
    app.Listen(":3000")
}

八、总结 #

8.1 请求处理方法汇总 #

方法 用途
c.Params() 路径参数
c.Query() 查询参数
c.FormValue() 表单参数
c.BodyParser() 解析请求体
c.Get() 请求头
c.Cookies() Cookie
c.FormFile() 上传文件
c.IP() 客户端IP

8.2 下一步 #

现在你已经掌握了请求处理,接下来让我们学习 响应处理,了解如何返回各种类型的响应!

最后更新:2026-03-28