diff --git a/gin/internal/middleware/cors.go b/gin/internal/middleware/cors.go new file mode 100644 index 0000000..59b5f95 --- /dev/null +++ b/gin/internal/middleware/cors.go @@ -0,0 +1,12 @@ +package middleware + +import "github.com/gin-gonic/gin" + +func CorsMiddleWare() gin.HandlerFunc { + return func(ctx *gin.Context) { + ctx.Header("Access-Control-Allow-Origin", "*") + ctx.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE") + ctx.Header("Access-Control-Allow-Headers", "Action, Module, X-PINGOTHER, Content-Type, Content-Disposition") + ctx.Next() + } +} diff --git a/gin/internal/middleware/error.go b/gin/internal/middleware/error.go new file mode 100644 index 0000000..c7feee6 --- /dev/null +++ b/gin/internal/middleware/error.go @@ -0,0 +1,38 @@ +package middleware + +import ( + "net/http" + "runtime/debug" + + "github.com/gin-gonic/gin" + + "gin-study/pkg/errorx" +) + +// gin 全局异常处理 +func ErrorHandler() gin.HandlerFunc { + return func(c *gin.Context) { + defer func() { + if r := recover(); r != nil { + err := parseError(r) + //打印错误堆栈信息 + debug.PrintStack() + //封装通用JSON返回 + c.JSON(http.StatusOK, errorx.NewDefaultError(err)) + //终止后续接口调用,不加的话recover到异常后,还会继续执行接口里后续代码 + c.Abort() + } + }() + //加载完 defer recover,继续后续的插件及代码执行 + c.Next() + } +} + +func parseError(r interface{}) string { + switch v := r.(type) { + case error: + return v.Error() + default: + return r.(string) + } +} diff --git a/gin/main.go b/gin/main.go index 26d0385..b7fb853 100644 --- a/gin/main.go +++ b/gin/main.go @@ -3,6 +3,7 @@ package main import ( "context" "gin-study/internal/controller" + "gin-study/internal/middleware" "log" "net/http" @@ -19,6 +20,8 @@ func main() { // 注册 favicon e.Use(favicon.New("./templates/favicon.ico")) e.Use(gin.Recovery()) + e.Use(middleware.CorsMiddleWare()) + e.Use(middleware.ErrorHandler()) controller.Register(e) diff --git a/gin/pkg/errorx/errorx.go b/gin/pkg/errorx/errorx.go new file mode 100644 index 0000000..1e57cbf --- /dev/null +++ b/gin/pkg/errorx/errorx.go @@ -0,0 +1,57 @@ +package errorx + +import "gin-study/pkg/response" + +type CodeError struct { + *response.Response +} + +type CodeErrorResponse struct { + *response.Response +} + +func NewCustomError(code int, data interface{}, msg string) error { + return &CodeError{ + Response: response.NewCustomResponse(code, data, msg), + } +} + +func NewErrorWithCode(code int, msg string) error { + return &CodeError{ + Response: response.NewCustomResponse(code, nil, msg), + } +} + +func ParseError(err error) error { + if err != nil { + return NewErrorWithCode(response.ERROR, err.Error()) + } + + return nil +} + +func ParseErrorWithCode(code int, err error) error { + if err != nil { + return NewErrorWithCode(code, err.Error()) + } + + return nil +} + +func NewDefaultError(msg string) error { + return NewErrorWithCode(response.ERROR, msg) +} + +func (e *CodeError) Error() string { + return e.Msg +} + +func (e *CodeError) Resp() *CodeErrorResponse { + return &CodeErrorResponse{ + Response: &response.Response{ + Code: e.Code, + Data: e.Data, + Msg: e.Msg, + }, + } +} diff --git a/gin/pkg/response/response.go b/gin/pkg/response/response.go new file mode 100644 index 0000000..9e93abc --- /dev/null +++ b/gin/pkg/response/response.go @@ -0,0 +1,40 @@ +package response + +type Response struct { + Code Code `json:"code" example:"200"` + Data interface{} `json:"data"` + Msg string `json:"msg" example:"OK"` +} + +type Code = int + +const ( + SUCCESS = 200 + UNAUTHORIZED = 401 + FORBIDDEN = 403 + ERROR = 500 +) + +func NewCustomResponse(code int, data interface{}, msg string) *Response { + return &Response{ + Code: code, + Data: data, + Msg: msg, + } +} + +func NewResponseWithCode(code int, data interface{}) *Response { + return &Response{ + Code: SUCCESS, + Data: data, + Msg: "OK", + } +} + +func NewResponse(data interface{}) *Response { + return &Response{ + Code: SUCCESS, + Data: data, + Msg: "OK", + } +}