Dragonfly2
128 строк · 3.0 Кб
1/*
2* Copyright 2020 The Dragonfly Authors
3*
4* Licensed under the Apache License, Version 2.0 (the "License");
5* you may not use this file except in compliance with the License.
6* You may obtain a copy of the License at
7*
8* http://www.apache.org/licenses/LICENSE-2.0
9*
10* Unless required by applicable law or agreed to in writing, software
11* distributed under the License is distributed on an "AS IS" BASIS,
12* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13* See the License for the specific language governing permissions and
14* limitations under the License.
15*/
16
17package middlewares
18
19import (
20"errors"
21"net/http"
22
23"github.com/VividCortex/mysqlerr"
24"github.com/gin-gonic/gin"
25"github.com/go-redis/redis/v8"
26"github.com/go-sql-driver/mysql"
27redigo "github.com/gomodule/redigo/redis"
28"golang.org/x/crypto/bcrypt"
29"gorm.io/gorm"
30
31commonv1 "d7y.io/api/v2/pkg/apis/common/v1"
32
33"d7y.io/dragonfly/v2/internal/dferrors"
34)
35
36type ErrorResponse struct {
37Message string `json:"message,omitempty"`
38Error string `json:"errors,omitempty"`
39DocumentURL string `json:"documentation_url,omitempty"`
40}
41
42func Error() gin.HandlerFunc {
43return func(c *gin.Context) {
44c.Next()
45err := c.Errors.Last()
46if err == nil {
47return
48}
49
50// Redigo error handler
51if errors.Is(err, redigo.ErrNil) {
52c.JSON(http.StatusNotFound, ErrorResponse{
53Message: http.StatusText(http.StatusNotFound),
54})
55c.Abort()
56return
57}
58
59// RPC error handler
60var dferr *dferrors.DfError
61if errors.As(err.Err, &dferr) {
62switch dferr.Code {
63case commonv1.Code_InvalidResourceType:
64c.JSON(http.StatusBadRequest, ErrorResponse{
65Message: http.StatusText(http.StatusBadRequest),
66})
67c.Abort()
68return
69default:
70c.JSON(http.StatusInternalServerError, ErrorResponse{
71Message: http.StatusText(http.StatusInternalServerError),
72})
73c.Abort()
74return
75}
76}
77
78// Bcrypt error handler
79if errors.Is(err, bcrypt.ErrMismatchedHashAndPassword) {
80c.JSON(http.StatusUnauthorized, ErrorResponse{
81Message: http.StatusText(http.StatusUnauthorized),
82})
83c.Abort()
84return
85}
86
87// GORM error handler
88if errors.Is(err.Err, gorm.ErrRecordNotFound) {
89c.JSON(http.StatusNotFound, ErrorResponse{
90Message: http.StatusText(http.StatusNotFound),
91})
92c.Abort()
93return
94}
95
96// Mysql error handler
97var merr *mysql.MySQLError
98if errors.As(err.Err, &merr) {
99switch merr.Number {
100case mysqlerr.ER_DUP_ENTRY:
101c.JSON(http.StatusConflict, ErrorResponse{
102Message: http.StatusText(http.StatusConflict),
103})
104c.Abort()
105return
106default:
107c.JSON(http.StatusInternalServerError, ErrorResponse{
108Message: http.StatusText(http.StatusInternalServerError),
109})
110c.Abort()
111return
112}
113}
114
115if errors.Is(err.Err, redis.Nil) {
116c.JSON(http.StatusNotFound, ErrorResponse{
117Message: http.StatusText(http.StatusNotFound),
118})
119c.Abort()
120return
121}
122
123// Unknown error
124c.JSON(http.StatusInternalServerError, ErrorResponse{
125Message: err.Err.Error(),
126})
127}
128}
129