Base Project

This commit is contained in:
Tran Anh Tuan
2026-05-08 14:32:24 +07:00
parent 5a9249c9ea
commit 6a4a96e0ca
74 changed files with 6749 additions and 0 deletions

175
response/error_response.go Normal file
View File

@@ -0,0 +1,175 @@
package response
import (
"net/http"
"time"
"github.com/gin-gonic/gin"
)
// ErrorResponse represents a structured error response
type ErrorResponse struct {
Code int `json:"code"`
Message string `json:"message"`
Status int `json:"status"`
Now int64 `json:"now"`
}
// NewErrorResponse creates a new ErrorResponse
func NewErrorResponse(message string, status int, code int) *ErrorResponse {
return &ErrorResponse{
Code: code,
Message: message,
Status: status,
Now: time.Now().Unix(),
}
}
// Send sends the error response to the client.
// It aborts the request and responds with the error response as JSON.
func (sr *ErrorResponse) Send(c *gin.Context) {
c.AbortWithStatusJSON(sr.Status, sr)
}
// BadRequestError represents a 400 Bad Request error
func BadRequestError(c *gin.Context, code int, messages ...string) {
message := ""
if len(messages) > 0 {
message = messages[0]
}
if message == "" {
message = GetReasonPhrase(http.StatusBadRequest)
}
response := NewErrorResponse(message, http.StatusBadRequest, code)
response.Send(c)
}
// NotFoundError represents a 404 Not Found error
func NotFoundError(c *gin.Context, code int, messages ...string) {
message := ""
if len(messages) > 0 {
message = messages[0]
}
if message == "" {
message = GetReasonPhrase(http.StatusNotFound)
}
response := NewErrorResponse(message, http.StatusNotFound, code)
response.Send(c)
}
// TooManyRequestsError represents a 429 Too Many Requests error
func TooManyRequestsError(c *gin.Context, code int, messages ...string) {
message := ""
if len(messages) > 0 {
message = messages[0]
}
if message == "" {
message = GetReasonPhrase(http.StatusTooManyRequests)
}
response := NewErrorResponse(message, http.StatusTooManyRequests, code)
response.Send(c)
}
// UnauthorizedError represents a 401 Unauthorized error
func UnauthorizedError(c *gin.Context, code int, messages ...string) {
message := ""
if len(messages) > 0 {
message = messages[0]
}
if message == "" {
message = GetReasonPhrase(http.StatusUnauthorized)
}
response := NewErrorResponse(message, http.StatusUnauthorized, code)
response.Send(c)
}
// ForbiddenError handles the generation and sending of a Forbidden error response.
func ForbiddenError(c *gin.Context, code int, messages ...string) {
message := ""
if len(messages) > 0 {
message = messages[0]
}
if message == "" {
message = GetReasonPhrase(http.StatusForbidden)
}
response := NewErrorResponse(message, http.StatusForbidden, code)
response.Send(c)
}
// ConflictError represents a 409 Conflict error
func ConflictError(c *gin.Context, code int, messages ...string) {
message := ""
if len(messages) > 0 {
message = messages[0]
}
if message == "" {
message = GetReasonPhrase(http.StatusConflict)
}
response := NewErrorResponse(message, http.StatusConflict, code)
response.Send(c)
}
// EntityTooLargeError handles the HTTP 413 Request Entity Too Large error.
func EntityTooLargeError(c *gin.Context, code int, messages ...string) {
message := ""
if len(messages) > 0 {
message = messages[0]
}
if message == "" {
message = GetReasonPhrase(http.StatusRequestEntityTooLarge)
}
response := NewErrorResponse(message, http.StatusRequestEntityTooLarge, code)
response.Send(c)
}
// UnSupportMediaTypeError handles the unsupported media type error by sending an error response to the client.
func UnSupportMediaTypeError(c *gin.Context, code int, messages ...string) {
message := ""
if len(messages) > 0 {
message = messages[0]
}
if message == "" {
message = GetReasonPhrase(http.StatusUnsupportedMediaType)
}
response := NewErrorResponse(message, http.StatusUnsupportedMediaType, code)
response.Send(c)
}
// InternalServerError represents a 500 Internal Server Error
func InternalServerError(c *gin.Context, code int, messages ...string) {
message := ""
if len(messages) > 0 {
message = messages[0]
}
if message == "" {
message = GetReasonPhrase(http.StatusInternalServerError)
}
response := NewErrorResponse(message, http.StatusInternalServerError, code)
response.Send(c)
}
// ServiceUnavailable represents a 503 Service Unavailable
func ServiceUnavailable(c *gin.Context, code int, messages ...string) {
message := ""
if len(messages) > 0 {
message = messages[0]
}
if message == "" {
message = GetReasonPhrase(http.StatusServiceUnavailable)
}
response := NewErrorResponse(message, http.StatusServiceUnavailable, code)
response.Send(c)
}

View File

@@ -0,0 +1,51 @@
package response
// ReasonPhrases is a map of HTTP status codes to their reason phrases
var ReasonPhrases = map[int]string{
100: "Continue",
101: "Switching Protocols",
200: "OK",
201: "Created",
202: "Accepted",
203: "Non-Authoritative Information",
204: "No Content",
205: "Reset Content",
206: "Partial Content",
300: "Multiple Choices",
301: "Moved Permanently",
302: "Found",
303: "See Other",
304: "Not Modified",
305: "Use Proxy",
307: "Temporary Redirect",
400: "Bad Request",
401: "Unauthorized",
402: "Payment Required",
403: "Forbidden",
404: "Not Found",
405: "Method Not Allowed",
406: "Not Acceptable",
407: "Proxy Authentication Required",
408: "Request Timeout",
409: "Conflict",
410: "Gone",
411: "Length Required",
412: "Precondition Failed",
413: "Payload Too Large",
414: "URI Too Long",
415: "Unsupported Media Type",
416: "Range Not Satisfiable",
417: "Expectation Failed",
429: "Too Many Requests",
500: "Internal Server Error",
501: "Not Implemented",
502: "Bad Gateway",
503: "Service Unavailable",
504: "Gateway Timeout",
505: "HTTP Version Not Supported",
}
// GetReasonPhrase returns the reason phrase for a given status code
func GetReasonPhrase(statusCode int) string {
return ReasonPhrases[statusCode]
}

View File

@@ -0,0 +1,50 @@
package response
import (
"net/http"
"github.com/gin-gonic/gin"
)
// SuccessResponse represents a structured success response
type SuccessResponse struct {
Message string `json:"message"`
Status int `json:"status"`
ReasonStatusCode string `json:"reason_status_code"`
Option any `json:"option,omitempty"`
Data any `json:"data,omitempty"`
}
// NewSuccessResponse creates a new SuccessResponse
func NewSuccessResponse(message string, statusCode int, reasonStatusCode string, option any, data any) *SuccessResponse {
return &SuccessResponse{
Message: message,
Status: statusCode,
ReasonStatusCode: reasonStatusCode,
Option: option,
Data: data,
}
}
// Send sends the success response to the client
func (sr *SuccessResponse) Send(c *gin.Context) {
c.JSON(sr.Status, sr)
}
// Ok represents a 200 OK success response
func Ok(c *gin.Context, message string, metadata any) {
if message == "" {
message = GetReasonPhrase(http.StatusOK)
}
response := NewSuccessResponse(message, http.StatusOK, GetReasonPhrase(http.StatusOK), nil, metadata)
response.Send(c)
}
// Created represents a 201 Created success response
func Created(c *gin.Context, message string, metadata any) {
if message == "" {
message = GetReasonPhrase(http.StatusCreated)
}
response := NewSuccessResponse(message, http.StatusCreated, GetReasonPhrase(http.StatusCreated), nil, metadata)
response.Send(c)
}