Просмотр исходного кода

feat: ali error handler timeout (#301)

zijiren 6 месяцев назад
Родитель
Сommit
37c666c572

+ 1 - 1
core/controller/relay-controller.go

@@ -217,7 +217,7 @@ func relay(c *gin.Context, mode mode.Mode, relayController RelayController) {
 			middleware.AbortLogWithMessageWithMode(mode, c,
 				http.StatusForbidden,
 				fmt.Sprintf("group (%s) balance not enough", gbc.Group),
-				middleware.GroupBalanceNotEnough,
+				relaymodel.WithType(middleware.GroupBalanceNotEnough),
 			)
 			return
 		}

+ 1 - 1
core/middleware/auth.go

@@ -92,7 +92,7 @@ func TokenAuth(c *gin.Context) {
 	} else {
 		tokenCache, err := model.ValidateAndGetToken(key)
 		if err != nil {
-			AbortLogWithMessage(c, http.StatusUnauthorized, err.Error(), "invalid_token")
+			AbortLogWithMessage(c, http.StatusUnauthorized, err.Error())
 			return
 		}
 		token = *tokenCache

+ 4 - 10
core/middleware/distributor.go

@@ -20,6 +20,7 @@ import (
 	"github.com/labring/aiproxy/core/model"
 	"github.com/labring/aiproxy/core/relay/meta"
 	"github.com/labring/aiproxy/core/relay/mode"
+	relaymodel "github.com/labring/aiproxy/core/relay/model"
 	monitorplugin "github.com/labring/aiproxy/core/relay/plugin/monitor"
 )
 
@@ -244,7 +245,6 @@ func checkGroupBalance(c *gin.Context, group model.GroupCache) bool {
 				c,
 				http.StatusForbidden,
 				err.Error(),
-				"no_real_name_used_amount_limit",
 			)
 			return false
 		}
@@ -258,7 +258,6 @@ func checkGroupBalance(c *gin.Context, group model.GroupCache) bool {
 			c,
 			http.StatusInternalServerError,
 			fmt.Sprintf("get group `%s` balance error", group.ID),
-			"get_group_balance_error",
 		)
 		return false
 	}
@@ -283,7 +282,7 @@ func checkGroupBalance(c *gin.Context, group model.GroupCache) bool {
 			c,
 			http.StatusForbidden,
 			fmt.Sprintf("group `%s` balance not enough", group.ID),
-			GroupBalanceNotEnough,
+			relaymodel.WithType(GroupBalanceNotEnough),
 		)
 		return false
 	}
@@ -340,12 +339,11 @@ func distribute(c *gin.Context, mode mode.Mode) {
 			c,
 			http.StatusInternalServerError,
 			err.Error(),
-			"get_request_model_error",
 		)
 		return
 	}
 	if requestModel == "" {
-		AbortLogWithMessage(c, http.StatusBadRequest, "no model provided", "no_model_provided")
+		AbortLogWithMessage(c, http.StatusBadRequest, "no model provided")
 		return
 	}
 
@@ -362,7 +360,6 @@ func distribute(c *gin.Context, mode mode.Mode) {
 				"The model `%s` does not exist or you do not have access to it.",
 				requestModel,
 			),
-			"model_not_found",
 		)
 		return
 	}
@@ -376,7 +373,6 @@ func distribute(c *gin.Context, mode mode.Mode) {
 				"The model `%s` does not exist or you do not have access to it.",
 				requestModel,
 			),
-			"model_not_found",
 		)
 		return
 	}
@@ -387,7 +383,6 @@ func distribute(c *gin.Context, mode mode.Mode) {
 			c,
 			http.StatusInternalServerError,
 			err.Error(),
-			"get_request_user_error",
 		)
 		return
 	}
@@ -399,7 +394,6 @@ func distribute(c *gin.Context, mode mode.Mode) {
 			c,
 			http.StatusInternalServerError,
 			err.Error(),
-			"get_request_metadata_error",
 		)
 		return
 	}
@@ -422,7 +416,7 @@ func distribute(c *gin.Context, mode mode.Mode) {
 			user,
 			metadata,
 		)
-		AbortLogWithMessage(c, http.StatusTooManyRequests, errMsg, "request_rate_limit_exceeded")
+		AbortLogWithMessage(c, http.StatusTooManyRequests, errMsg)
 		return
 	}
 

+ 1 - 1
core/middleware/mcp.go

@@ -34,7 +34,7 @@ func MCPAuth(c *gin.Context) {
 	} else {
 		tokenCache, err := model.ValidateAndGetToken(key)
 		if err != nil {
-			AbortLogWithMessage(c, http.StatusUnauthorized, err.Error(), "invalid_token")
+			AbortLogWithMessage(c, http.StatusUnauthorized, err.Error())
 			return
 		}
 		token = *tokenCache

+ 18 - 8
core/middleware/utils.go

@@ -14,10 +14,10 @@ func AbortLogWithMessageWithMode(
 	c *gin.Context,
 	statusCode int,
 	message string,
-	typ ...string,
+	opts ...relaymodel.WrapperErrorOptionFunc,
 ) {
 	common.GetLogger(c).Error(message)
-	AbortWithMessageWithMode(m, c, statusCode, message, typ...)
+	AbortWithMessageWithMode(m, c, statusCode, message, opts...)
 }
 
 func AbortWithMessageWithMode(
@@ -25,22 +25,32 @@ func AbortWithMessageWithMode(
 	c *gin.Context,
 	statusCode int,
 	message string,
-	typ ...string,
+	opts ...relaymodel.WrapperErrorOptionFunc,
 ) {
 	c.JSON(statusCode,
-		relaymodel.WrapperErrorWithMessage(m, statusCode, message, typ...),
+		relaymodel.WrapperErrorWithMessage(m, statusCode, message, opts...),
 	)
 	c.Abort()
 }
 
-func AbortLogWithMessage(c *gin.Context, statusCode int, message string, typ ...string) {
+func AbortLogWithMessage(
+	c *gin.Context,
+	statusCode int,
+	message string,
+	opts ...relaymodel.WrapperErrorOptionFunc,
+) {
 	common.GetLogger(c).Error(message)
-	AbortWithMessage(c, statusCode, message, typ...)
+	AbortWithMessage(c, statusCode, message, opts...)
 }
 
-func AbortWithMessage(c *gin.Context, statusCode int, message string, typ ...string) {
+func AbortWithMessage(
+	c *gin.Context,
+	statusCode int,
+	message string,
+	opts ...relaymodel.WrapperErrorOptionFunc,
+) {
 	c.JSON(statusCode,
-		relaymodel.WrapperErrorWithMessage(GetMode(c), statusCode, message, typ...),
+		relaymodel.WrapperErrorWithMessage(GetMode(c), statusCode, message, opts...),
 	)
 	c.Abort()
 }

+ 7 - 1
core/relay/adaptor/ali/error.go

@@ -8,13 +8,19 @@ import (
 	relaymodel "github.com/labring/aiproxy/core/relay/model"
 )
 
+// https://help.aliyun.com/zh/model-studio/error-code?userCode=okjhlpr5
+
 func ErrorHanlder(resp *http.Response) adaptor.Error {
 	statusCode, openAIError := openai.GetError(resp)
 
 	// {"error":{"code":"ServiceUnavailable","message":"<503> InternalError.Algo: An error occurred in model serving, error message is: [Too many requests. Your requests are being throttled due to system capacity limits. Please try again later.]","type":"ServiceUnavailable"}}
-	if openAIError.Type == "ServiceUnavailable" {
+	switch openAIError.Type {
+	case "ServiceUnavailable":
 		statusCode = http.StatusServiceUnavailable
 		openAIError.Type = relaymodel.ErrorTypeUpstream
+	case "RequestTimeOut":
+		statusCode = http.StatusGatewayTimeout
+		openAIError.Type = relaymodel.ErrorTypeUpstream
 	}
 	return relaymodel.NewOpenAIError(statusCode, openAIError)
 }

+ 5 - 16
core/relay/controller/dohelper.go

@@ -118,7 +118,6 @@ func DoHelper(
 			meta.Mode,
 			http.StatusInternalServerError,
 			"response is nil",
-			relaymodel.ErrorCodeBadResponse,
 		)
 		respBody, _ := relayErr.MarshalJSON()
 		detail.ResponseBody = conv.BytesToString(respBody)
@@ -156,7 +155,6 @@ func getRequestBody(meta *meta.Meta, c *gin.Context, detail *RequestDetail) adap
 				meta.Mode,
 				http.StatusBadRequest,
 				"get request body failed: "+err.Error(),
-				"get_request_body_failed",
 			)
 		}
 		detail.RequestBody = conv.BytesToString(reqBody)
@@ -181,7 +179,6 @@ func prepareAndDoRequest(
 			meta.Mode,
 			http.StatusBadRequest,
 			"convert request failed: "+err.Error(),
-			"convert_request_failed",
 		)
 	}
 	if closer, ok := convertResult.Body.(io.Closer); ok {
@@ -198,7 +195,6 @@ func prepareAndDoRequest(
 			meta.Mode,
 			http.StatusBadRequest,
 			"get request url failed: "+err.Error(),
-			"get_request_url_failed",
 		)
 	}
 
@@ -215,7 +211,6 @@ func prepareAndDoRequest(
 			meta.Mode,
 			http.StatusBadRequest,
 			"new request failed: "+err.Error(),
-			"new_request_failed",
 		)
 	}
 
@@ -242,7 +237,6 @@ func setupRequestHeader(
 			meta.Mode,
 			http.StatusInternalServerError,
 			"setup request header failed: "+err.Error(),
-			"setup_request_header_failed",
 		)
 	}
 	return nil
@@ -261,39 +255,34 @@ func doRequest(
 			return nil, relaymodel.WrapperErrorWithMessage(
 				meta.Mode,
 				http.StatusBadRequest,
-				"do request failed: request canceled by client",
-				"request_canceled",
+				"request canceled by client: "+err.Error(),
 			)
 		}
 		if errors.Is(err, context.DeadlineExceeded) {
 			return nil, relaymodel.WrapperErrorWithMessage(
 				meta.Mode,
 				http.StatusGatewayTimeout,
-				"do request failed: request timeout",
-				"request_timeout",
+				"request timeout: "+err.Error(),
 			)
 		}
 		if errors.Is(err, io.EOF) {
 			return nil, relaymodel.WrapperErrorWithMessage(
 				meta.Mode,
 				http.StatusServiceUnavailable,
-				"do request failed: "+err.Error(),
-				"request_failed",
+				"request eof: "+err.Error(),
 			)
 		}
 		if errors.Is(err, io.ErrUnexpectedEOF) {
 			return nil, relaymodel.WrapperErrorWithMessage(
 				meta.Mode,
 				http.StatusInternalServerError,
-				"do request failed: "+err.Error(),
-				"request_failed",
+				"request unexpected eof: "+err.Error(),
 			)
 		}
 		return nil, relaymodel.WrapperErrorWithMessage(
 			meta.Mode,
 			http.StatusBadRequest,
-			"do request failed: "+err.Error(),
-			"request_failed",
+			"request error: "+err.Error(),
 		)
 	}
 	return resp, nil

+ 40 - 8
core/relay/model/errors.go

@@ -11,25 +11,56 @@ const (
 	ErrorCodeBadResponse = "bad_response"
 )
 
-func WrapperError(m mode.Mode, statusCode int, err error, typ ...string) adaptor.Error {
-	return WrapperErrorWithMessage(m, statusCode, err.Error(), typ...)
+func WrapperError(
+	m mode.Mode,
+	statusCode int,
+	err error,
+	opts ...WrapperErrorOptionFunc,
+) adaptor.Error {
+	return WrapperErrorWithMessage(m, statusCode, err.Error(), opts...)
+}
+
+type WrapperErrorOption struct {
+	Type string
+	Code any
+}
+
+type WrapperErrorOptionFunc func(o *WrapperErrorOption)
+
+func WithType(typ string) WrapperErrorOptionFunc {
+	return func(o *WrapperErrorOption) {
+		o.Type = typ
+	}
+}
+
+func WithCode(code any) WrapperErrorOptionFunc {
+	return func(o *WrapperErrorOption) {
+		o.Code = code
+	}
+}
+
+func DefaultWrapperErrorOption() WrapperErrorOption {
+	return WrapperErrorOption{
+		Type: ErrorTypeAIPROXY,
+	}
 }
 
 func WrapperErrorWithMessage(
 	m mode.Mode,
 	statusCode int,
 	message string,
-	typ ...string,
+	opts ...WrapperErrorOptionFunc,
 ) adaptor.Error {
-	respType := ErrorTypeAIPROXY
-	if len(typ) > 0 {
-		respType = typ[0]
+	opt := DefaultWrapperErrorOption()
+	for _, o := range opts {
+		o(&opt)
 	}
+
 	switch m {
 	case mode.Anthropic:
 		return NewAnthropicError(statusCode, AnthropicError{
 			Message: message,
-			Type:    respType,
+			Type:    opt.Type,
 		})
 	case mode.VideoGenerationsJobs,
 		mode.VideoGenerationsGetJobs,
@@ -40,7 +71,8 @@ func WrapperErrorWithMessage(
 	default:
 		return NewOpenAIError(statusCode, OpenAIError{
 			Message: message,
-			Type:    respType,
+			Type:    opt.Type,
+			Code:    opt.Code,
 		})
 	}
 }