otpm/api/response.go
“xHuPo” bcd986e3f7 beta
2025-05-23 18:57:11 +08:00

149 lines
3.7 KiB
Go

package api
import (
"encoding/json"
"errors"
"fmt"
"net/http"
)
// Common error codes
const (
CodeSuccess = 0
CodeInvalidParams = 400
CodeUnauthorized = 401
CodeForbidden = 403
CodeNotFound = 404
CodeInternalError = 500
CodeServiceUnavail = 503
)
// Error represents an API error
type Error struct {
Code int `json:"code"`
Message string `json:"message"`
}
// Error implements the error interface
func (e *Error) Error() string {
return fmt.Sprintf("code: %d, message: %s", e.Code, e.Message)
}
// NewError creates a new API error
func NewError(code int, message string) *Error {
return &Error{
Code: code,
Message: message,
}
}
// Response represents a standard API response
type Response struct {
Code int `json:"code"`
Message string `json:"message"`
Data interface{} `json:"data,omitempty"`
}
// ResponseWriter wraps common response writing functions
type ResponseWriter struct {
http.ResponseWriter
}
// NewResponseWriter creates a new ResponseWriter
func NewResponseWriter(w http.ResponseWriter) *ResponseWriter {
return &ResponseWriter{w}
}
// WriteJSON writes a JSON response
func (w *ResponseWriter) WriteJSON(code int, data interface{}) error {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(code)
return json.NewEncoder(w).Encode(data)
}
// WriteSuccess writes a success response
func (w *ResponseWriter) WriteSuccess(data interface{}) error {
return w.WriteJSON(http.StatusOK, Response{
Code: CodeSuccess,
Message: "success",
Data: data,
})
}
// WriteError writes an error response
func (w *ResponseWriter) WriteError(err error) error {
var apiErr *Error
if errors.As(err, &apiErr) {
return w.WriteJSON(getHTTPStatus(apiErr.Code), Response{
Code: apiErr.Code,
Message: apiErr.Message,
})
}
// Handle unknown errors
return w.WriteJSON(http.StatusInternalServerError, Response{
Code: CodeInternalError,
Message: "Internal Server Error",
})
}
// WriteErrorWithCode writes an error response with a specific code
func (w *ResponseWriter) WriteErrorWithCode(code int, message string) error {
return w.WriteJSON(getHTTPStatus(code), Response{
Code: code,
Message: message,
})
}
// getHTTPStatus maps API error codes to HTTP status codes
func getHTTPStatus(code int) int {
switch code {
case CodeSuccess:
return http.StatusOK
case CodeInvalidParams:
return http.StatusBadRequest
case CodeUnauthorized:
return http.StatusUnauthorized
case CodeForbidden:
return http.StatusForbidden
case CodeNotFound:
return http.StatusNotFound
case CodeServiceUnavail:
return http.StatusServiceUnavailable
default:
return http.StatusInternalServerError
}
}
// Common errors
var (
ErrInvalidParams = NewError(CodeInvalidParams, "Invalid parameters")
ErrUnauthorized = NewError(CodeUnauthorized, "Unauthorized")
ErrForbidden = NewError(CodeForbidden, "Forbidden")
ErrNotFound = NewError(CodeNotFound, "Resource not found")
ErrInternalError = NewError(CodeInternalError, "Internal server error")
ErrServiceUnavail = NewError(CodeServiceUnavail, "Service unavailable")
)
// ValidationError creates an error for invalid parameters
func ValidationError(message string) *Error {
return NewError(CodeInvalidParams, message)
}
// NotFoundError creates an error for not found resources
func NotFoundError(resource string) *Error {
return NewError(CodeNotFound, fmt.Sprintf("%s not found", resource))
}
// ForbiddenError creates an error for forbidden actions
func ForbiddenError(message string) *Error {
return NewError(CodeForbidden, message)
}
// InternalError creates an error for internal server errors
func InternalError(err error) *Error {
if err == nil {
return ErrInternalError
}
return NewError(CodeInternalError, err.Error())
}