149 lines
3.7 KiB
Go
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())
|
|
}
|