| |
| package response |
|
|
| import ( |
| "log" |
| "math" |
| "net/http" |
|
|
| infraerrors "github.com/Wei-Shaw/sub2api/internal/pkg/errors" |
| "github.com/Wei-Shaw/sub2api/internal/util/logredact" |
| "github.com/gin-gonic/gin" |
| ) |
|
|
| |
| type Response struct { |
| Code int `json:"code"` |
| Message string `json:"message"` |
| Reason string `json:"reason,omitempty"` |
| Metadata map[string]string `json:"metadata,omitempty"` |
| Data any `json:"data,omitempty"` |
| } |
|
|
| |
| type PaginatedData struct { |
| Items any `json:"items"` |
| Total int64 `json:"total"` |
| Page int `json:"page"` |
| PageSize int `json:"page_size"` |
| Pages int `json:"pages"` |
| } |
|
|
| |
| func Success(c *gin.Context, data any) { |
| c.JSON(http.StatusOK, Response{ |
| Code: 0, |
| Message: "success", |
| Data: data, |
| }) |
| } |
|
|
| |
| func Created(c *gin.Context, data any) { |
| c.JSON(http.StatusCreated, Response{ |
| Code: 0, |
| Message: "success", |
| Data: data, |
| }) |
| } |
|
|
| |
| func Accepted(c *gin.Context, data any) { |
| c.JSON(http.StatusAccepted, Response{ |
| Code: 0, |
| Message: "accepted", |
| Data: data, |
| }) |
| } |
|
|
| |
| func Error(c *gin.Context, statusCode int, message string) { |
| c.JSON(statusCode, Response{ |
| Code: statusCode, |
| Message: message, |
| Reason: "", |
| Metadata: nil, |
| }) |
| } |
|
|
| |
| |
| func ErrorWithDetails(c *gin.Context, statusCode int, message, reason string, metadata map[string]string) { |
| c.JSON(statusCode, Response{ |
| Code: statusCode, |
| Message: message, |
| Reason: reason, |
| Metadata: metadata, |
| }) |
| } |
|
|
| |
| |
| func ErrorFrom(c *gin.Context, err error) bool { |
| if err == nil { |
| return false |
| } |
|
|
| statusCode, status := infraerrors.ToHTTP(err) |
|
|
| |
| if statusCode >= 500 && c.Request != nil { |
| log.Printf("[ERROR] %s %s\n Error: %s", c.Request.Method, c.Request.URL.Path, logredact.RedactText(err.Error())) |
| } |
|
|
| ErrorWithDetails(c, statusCode, status.Message, status.Reason, status.Metadata) |
| return true |
| } |
|
|
| |
| func BadRequest(c *gin.Context, message string) { |
| Error(c, http.StatusBadRequest, message) |
| } |
|
|
| |
| func Unauthorized(c *gin.Context, message string) { |
| Error(c, http.StatusUnauthorized, message) |
| } |
|
|
| |
| func Forbidden(c *gin.Context, message string) { |
| Error(c, http.StatusForbidden, message) |
| } |
|
|
| |
| func NotFound(c *gin.Context, message string) { |
| Error(c, http.StatusNotFound, message) |
| } |
|
|
| |
| func InternalError(c *gin.Context, message string) { |
| Error(c, http.StatusInternalServerError, message) |
| } |
|
|
| |
| func Paginated(c *gin.Context, items any, total int64, page, pageSize int) { |
| pages := int(math.Ceil(float64(total) / float64(pageSize))) |
| if pages < 1 { |
| pages = 1 |
| } |
|
|
| Success(c, PaginatedData{ |
| Items: items, |
| Total: total, |
| Page: page, |
| PageSize: pageSize, |
| Pages: pages, |
| }) |
| } |
|
|
| |
| type PaginationResult struct { |
| Total int64 |
| Page int |
| PageSize int |
| Pages int |
| } |
|
|
| |
| func PaginatedWithResult(c *gin.Context, items any, pagination *PaginationResult) { |
| if pagination == nil { |
| Success(c, PaginatedData{ |
| Items: items, |
| Total: 0, |
| Page: 1, |
| PageSize: 20, |
| Pages: 1, |
| }) |
| return |
| } |
|
|
| Success(c, PaginatedData{ |
| Items: items, |
| Total: pagination.Total, |
| Page: pagination.Page, |
| PageSize: pagination.PageSize, |
| Pages: pagination.Pages, |
| }) |
| } |
|
|
| |
| func ParsePagination(c *gin.Context) (page, pageSize int) { |
| page = 1 |
| pageSize = 20 |
|
|
| if p := c.Query("page"); p != "" { |
| if val, err := parseInt(p); err == nil && val > 0 { |
| page = val |
| } |
| } |
|
|
| |
| if ps := c.Query("page_size"); ps != "" { |
| if val, err := parseInt(ps); err == nil && val > 0 && val <= 1000 { |
| pageSize = val |
| } |
| } else if l := c.Query("limit"); l != "" { |
| if val, err := parseInt(l); err == nil && val > 0 && val <= 1000 { |
| pageSize = val |
| } |
| } |
|
|
| return page, pageSize |
| } |
|
|
| func parseInt(s string) (int, error) { |
| var result int |
| for _, c := range s { |
| if c < '0' || c > '9' { |
| return 0, nil |
| } |
| result = result*10 + int(c-'0') |
| } |
| return result, nil |
| } |
|
|