Files
kevin 2858d3c0f7 接口响应与文档文案全部改为英文
- 错误响应、健康检查等运行时文案改为英文
- 种子数据英文化,新增迁移 v5 更新存量内置数据(不覆盖手工修改)
- Swagger 注释与 docs/ 文档全英文化
- 补充英文文案断言与 v5 迁移测试
2026-09-20 02:13:17 +08:00

81 lines
2.5 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Package httpx 提供 HTTP 接口的公共辅助:统一错误响应、分页参数与路径参数解析。
package httpx
import (
"errors"
"log/slog"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
const (
defaultPageSize = 20
maxPageSize = 100
)
// ErrorResponse 统一错误响应。
type ErrorResponse struct {
Error string `json:"error" example:"record not found"`
}
// ParsePagination 解析 page/page_size,非法值回落默认。
func ParsePagination(c *gin.Context) (int, int) {
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", strconv.Itoa(defaultPageSize)))
if page < 1 {
page = 1
}
if pageSize < 1 || pageSize > maxPageSize {
pageSize = defaultPageSize
}
return page, pageSize
}
// ParseID 解析路径参数 id0 或非法值返回 false 并写入 400。
func ParseID(c *gin.Context) (uint, bool) {
id, err := strconv.ParseUint(c.Param("id"), 10, 64)
if err != nil || id == 0 {
c.JSON(http.StatusBadRequest, ErrorResponse{Error: "invalid id"})
return 0, false
}
return uint(id), true
}
// RespondDBError 记录数据库错误并返回 500。
func RespondDBError(c *gin.Context, err error) {
slog.ErrorContext(c.Request.Context(), "数据库操作失败", "err", err, "path", c.Request.URL.Path)
c.JSON(http.StatusInternalServerError, ErrorResponse{Error: "internal server error"})
}
// RespondServerError 记录业务错误并返回 500。
func RespondServerError(c *gin.Context, err error, msg string) {
slog.ErrorContext(c.Request.Context(), msg, "err", err, "path", c.Request.URL.Path)
c.JSON(http.StatusInternalServerError, ErrorResponse{Error: "internal server error"})
}
// RespondGetError 查询类错误:记录不存在返回 404,其余按数据库错误处理。
func RespondGetError(c *gin.Context, err error) {
if errors.Is(err, gorm.ErrRecordNotFound) {
c.JSON(http.StatusNotFound, ErrorResponse{Error: "record not found"})
return
}
RespondDBError(c, err)
}
// RespondDuplicateOrDBError 写入类错误:唯一约束冲突返回 409,其余按数据库错误处理。
func RespondDuplicateOrDBError(c *gin.Context, err error, duplicateMsg string) {
if errors.Is(err, gorm.ErrDuplicatedKey) {
c.JSON(http.StatusConflict, ErrorResponse{Error: duplicateMsg})
return
}
RespondDBError(c, err)
}
// RespondUnauthorized 中止请求并返回 401。
func RespondUnauthorized(c *gin.Context) {
c.AbortWithStatusJSON(http.StatusUnauthorized, ErrorResponse{Error: "unauthorized or session expired"})
}