Files
tyapi-server/internal/shared/http/response.go

287 lines
6.7 KiB
Go
Raw 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 http
import (
"math"
"net/http"
"time"
"tyapi-server/internal/shared/interfaces"
"github.com/gin-gonic/gin"
)
// ResponseBuilder 响应构建器实现
type ResponseBuilder struct{}
// NewResponseBuilder 创建响应构建器
func NewResponseBuilder() interfaces.ResponseBuilder {
return &ResponseBuilder{}
}
// Success 成功响应
func (r *ResponseBuilder) Success(c *gin.Context, data interface{}, message ...string) {
msg := "操作成功"
if len(message) > 0 && message[0] != "" {
msg = message[0]
}
response := interfaces.APIResponse{
Success: true,
Message: msg,
Data: data,
RequestID: r.getRequestID(c),
Timestamp: time.Now().Unix(),
}
c.JSON(http.StatusOK, response)
}
// Created 创建成功响应
func (r *ResponseBuilder) Created(c *gin.Context, data interface{}, message ...string) {
msg := "创建成功"
if len(message) > 0 && message[0] != "" {
msg = message[0]
}
response := interfaces.APIResponse{
Success: true,
Message: msg,
Data: data,
RequestID: r.getRequestID(c),
Timestamp: time.Now().Unix(),
}
c.JSON(http.StatusCreated, response)
}
// Error 错误响应
func (r *ResponseBuilder) Error(c *gin.Context, err error) {
// 根据错误类型确定状态码
statusCode := http.StatusInternalServerError
message := "服务器内部错误"
errorDetail := err.Error()
// 这里可以根据不同的错误类型设置不同的状态码
// 例如ValidationError -> 400, NotFoundError -> 404, etc.
response := interfaces.APIResponse{
Success: false,
Message: message,
Errors: errorDetail,
RequestID: r.getRequestID(c),
Timestamp: time.Now().Unix(),
}
c.JSON(statusCode, response)
}
// BadRequest 400错误响应
func (r *ResponseBuilder) BadRequest(c *gin.Context, message string, errors ...interface{}) {
response := interfaces.APIResponse{
Success: false,
Message: message,
RequestID: r.getRequestID(c),
Timestamp: time.Now().Unix(),
}
if len(errors) > 0 {
response.Errors = errors[0]
}
c.JSON(http.StatusBadRequest, response)
}
// Unauthorized 401错误响应
func (r *ResponseBuilder) Unauthorized(c *gin.Context, message ...string) {
msg := "用户未登录或认证已过期"
if len(message) > 0 && message[0] != "" {
msg = message[0]
}
response := interfaces.APIResponse{
Success: false,
Message: msg,
RequestID: r.getRequestID(c),
Timestamp: time.Now().Unix(),
}
c.JSON(http.StatusUnauthorized, response)
}
// Forbidden 403错误响应
func (r *ResponseBuilder) Forbidden(c *gin.Context, message ...string) {
msg := "权限不足,无法访问此资源"
if len(message) > 0 && message[0] != "" {
msg = message[0]
}
response := interfaces.APIResponse{
Success: false,
Message: msg,
RequestID: r.getRequestID(c),
Timestamp: time.Now().Unix(),
}
c.JSON(http.StatusForbidden, response)
}
// NotFound 404错误响应
func (r *ResponseBuilder) NotFound(c *gin.Context, message ...string) {
msg := "请求的资源不存在"
if len(message) > 0 && message[0] != "" {
msg = message[0]
}
response := interfaces.APIResponse{
Success: false,
Message: msg,
RequestID: r.getRequestID(c),
Timestamp: time.Now().Unix(),
}
c.JSON(http.StatusNotFound, response)
}
// Conflict 409错误响应
func (r *ResponseBuilder) Conflict(c *gin.Context, message string) {
response := interfaces.APIResponse{
Success: false,
Message: message,
RequestID: r.getRequestID(c),
Timestamp: time.Now().Unix(),
}
c.JSON(http.StatusConflict, response)
}
// InternalError 500错误响应
func (r *ResponseBuilder) InternalError(c *gin.Context, message ...string) {
msg := "服务器内部错误"
if len(message) > 0 && message[0] != "" {
msg = message[0]
}
response := interfaces.APIResponse{
Success: false,
Message: msg,
RequestID: r.getRequestID(c),
Timestamp: time.Now().Unix(),
}
c.JSON(http.StatusInternalServerError, response)
}
// Paginated 分页响应
func (r *ResponseBuilder) Paginated(c *gin.Context, data interface{}, pagination interfaces.PaginationMeta) {
response := interfaces.APIResponse{
Success: true,
Message: "查询成功",
Data: data,
Pagination: &pagination,
RequestID: r.getRequestID(c),
Timestamp: time.Now().Unix(),
}
c.JSON(http.StatusOK, response)
}
// getRequestID 从上下文获取请求ID
func (r *ResponseBuilder) getRequestID(c *gin.Context) string {
if requestID, exists := c.Get("request_id"); exists {
if id, ok := requestID.(string); ok {
return id
}
}
return ""
}
// BuildPagination 构建分页元数据
func BuildPagination(page, pageSize int, total int64) interfaces.PaginationMeta {
totalPages := int(math.Ceil(float64(total) / float64(pageSize)))
if totalPages < 1 {
totalPages = 1
}
return interfaces.PaginationMeta{
Page: page,
PageSize: pageSize,
Total: total,
TotalPages: totalPages,
HasNext: page < totalPages,
HasPrev: page > 1,
}
}
// CustomResponse 自定义响应
func (r *ResponseBuilder) CustomResponse(c *gin.Context, statusCode int, data interface{}) {
var message string
switch statusCode {
case http.StatusOK:
message = "请求成功"
case http.StatusCreated:
message = "创建成功"
case http.StatusNoContent:
message = "无内容"
case http.StatusBadRequest:
message = "请求参数错误"
case http.StatusUnauthorized:
message = "认证失败"
case http.StatusForbidden:
message = "权限不足"
case http.StatusNotFound:
message = "资源不存在"
case http.StatusConflict:
message = "资源冲突"
case http.StatusTooManyRequests:
message = "请求过于频繁"
case http.StatusInternalServerError:
message = "服务器内部错误"
default:
message = "未知状态"
}
response := interfaces.APIResponse{
Success: statusCode >= 200 && statusCode < 300,
Message: message,
Data: data,
RequestID: r.getRequestID(c),
Timestamp: time.Now().Unix(),
}
c.JSON(statusCode, response)
}
// ValidationError 验证错误响应
func (r *ResponseBuilder) ValidationError(c *gin.Context, errors interface{}) {
response := interfaces.APIResponse{
Success: false,
Message: "请求参数验证失败",
Errors: errors,
RequestID: r.getRequestID(c),
Timestamp: time.Now().Unix(),
}
c.JSON(http.StatusUnprocessableEntity, response)
}
// TooManyRequests 限流错误响应
func (r *ResponseBuilder) TooManyRequests(c *gin.Context, message ...string) {
msg := "请求过于频繁,请稍后再试"
if len(message) > 0 && message[0] != "" {
msg = message[0]
}
response := interfaces.APIResponse{
Success: false,
Message: msg,
RequestID: r.getRequestID(c),
Timestamp: time.Now().Unix(),
Meta: map[string]interface{}{
"retry_after": "60s",
},
}
c.JSON(http.StatusTooManyRequests, response)
}