mirror of
https://github.com/router-for-me/CLIProxyAPI.git
synced 2026-09-03 06:35:00 +08:00
fix(cliproxy): centralize client error status mapping and apply context cancellation/deadline HTTP codes
Closes: #4601
This commit is contained in:
@@ -17,6 +17,7 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/router-for-me/CLIProxyAPI/v7/internal/clienterror"
|
||||
"github.com/router-for-me/CLIProxyAPI/v7/internal/config"
|
||||
"github.com/router-for-me/CLIProxyAPI/v7/internal/logging"
|
||||
"github.com/router-for-me/CLIProxyAPI/v7/internal/runtime/executor/helps"
|
||||
@@ -175,7 +176,7 @@ func (h *Handler) Handle(c *gin.Context) {
|
||||
|
||||
body, errRead := readBody(c.Request.Body)
|
||||
if errRead != nil {
|
||||
status := http.StatusBadRequest
|
||||
status := clienterror.HTTPStatusFromErrorOr(errRead, http.StatusBadRequest)
|
||||
if errors.Is(errRead, errBodyTooLarge) {
|
||||
status = http.StatusRequestEntityTooLarge
|
||||
}
|
||||
@@ -246,7 +247,7 @@ func (h *Handler) Handle(c *gin.Context) {
|
||||
authIndex: selectedIndex,
|
||||
})
|
||||
if errSDP != nil {
|
||||
c.JSON(http.StatusBadGateway, gin.H{"error": errSDP.Error()})
|
||||
c.JSON(clienterror.HTTPStatusFromErrorOr(errSDP, http.StatusBadGateway), gin.H{"error": errSDP.Error()})
|
||||
return
|
||||
}
|
||||
defer func() {
|
||||
@@ -291,7 +292,7 @@ func (h *Handler) Handle(c *gin.Context) {
|
||||
if selection != nil {
|
||||
selection.End("attempt_canceled")
|
||||
}
|
||||
c.JSON(http.StatusRequestTimeout, gin.H{"error": errContext.Error()})
|
||||
c.JSON(clienterror.HTTPStatusFromErrorOr(errContext, http.StatusRequestTimeout), gin.H{"error": errContext.Error()})
|
||||
return
|
||||
}
|
||||
resp, errRequest := performRequest(selected)
|
||||
@@ -300,7 +301,7 @@ func (h *Handler) Handle(c *gin.Context) {
|
||||
selection.End("request_failed")
|
||||
}
|
||||
helps.RecordAPIResponseError(ctx, runtimeConfig, errRequest)
|
||||
c.JSON(http.StatusBadGateway, gin.H{"error": errRequest.Error()})
|
||||
c.JSON(clienterror.HTTPStatusFromErrorOr(errRequest, http.StatusBadGateway), gin.H{"error": errRequest.Error()})
|
||||
return
|
||||
}
|
||||
if selection != nil && resp.StatusCode == http.StatusUnauthorized {
|
||||
@@ -327,7 +328,7 @@ func (h *Handler) Handle(c *gin.Context) {
|
||||
if errRequest != nil {
|
||||
selection.End("retry_failed")
|
||||
helps.RecordAPIResponseError(ctx, runtimeConfig, errRequest)
|
||||
c.JSON(http.StatusBadGateway, gin.H{"error": errRequest.Error()})
|
||||
c.JSON(clienterror.HTTPStatusFromErrorOr(errRequest, http.StatusBadGateway), gin.H{"error": errRequest.Error()})
|
||||
return
|
||||
}
|
||||
if resp.StatusCode == http.StatusUnauthorized {
|
||||
@@ -361,10 +362,12 @@ func (h *Handler) Handle(c *gin.Context) {
|
||||
if errResponse != nil {
|
||||
helps.RecordAPIResponseError(ctx, runtimeConfig, errResponse)
|
||||
message := "Failed to read Codex live response"
|
||||
status := clienterror.HTTPStatusFromErrorOr(errResponse, http.StatusBadGateway)
|
||||
if errors.Is(errResponse, errBodyTooLarge) {
|
||||
message = "Codex live response body too large"
|
||||
status = http.StatusBadGateway
|
||||
}
|
||||
c.JSON(http.StatusBadGateway, gin.H{"error": message})
|
||||
c.JSON(status, gin.H{"error": message})
|
||||
return
|
||||
}
|
||||
helps.AppendAPIResponseChunk(ctx, runtimeConfig, responseBody)
|
||||
@@ -389,7 +392,7 @@ func (h *Handler) Handle(c *gin.Context) {
|
||||
}
|
||||
downstreamAnswer, errAnswer := mediaSession.AcceptUpstreamAnswer(ctx, upstreamAnswer)
|
||||
if errAnswer != nil {
|
||||
c.JSON(http.StatusBadGateway, gin.H{"error": errAnswer.Error()})
|
||||
c.JSON(clienterror.HTTPStatusFromErrorOr(errAnswer, http.StatusBadGateway), gin.H{"error": errAnswer.Error()})
|
||||
return
|
||||
}
|
||||
responseBodyToWrite = []byte(downstreamAnswer)
|
||||
@@ -718,10 +721,7 @@ func writeResponseHeaders(destination, source http.Header) {
|
||||
}
|
||||
|
||||
func writeSelectionError(c *gin.Context, err error) {
|
||||
status := http.StatusServiceUnavailable
|
||||
if statusError, ok := err.(interface{ StatusCode() int }); ok && statusError.StatusCode() > 0 {
|
||||
status = statusError.StatusCode()
|
||||
}
|
||||
status := clienterror.HTTPStatusFromErrorOr(err, http.StatusServiceUnavailable)
|
||||
for _, value := range auth.SafeResponseHeaders(err).Values("Retry-After") {
|
||||
c.Writer.Header().Add("Retry-After", value)
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/router-for-me/CLIProxyAPI/v7/internal/clienterror"
|
||||
"github.com/router-for-me/CLIProxyAPI/v7/internal/config"
|
||||
"github.com/router-for-me/CLIProxyAPI/v7/internal/logging"
|
||||
"github.com/router-for-me/CLIProxyAPI/v7/internal/runtime/executor/helps"
|
||||
@@ -550,7 +551,7 @@ func callIDFromLocation(location string) string {
|
||||
}
|
||||
|
||||
func handleSidebandDialError(c *gin.Context, ctx context.Context, cfg *config.Config, response *http.Response, errDial error) {
|
||||
status := http.StatusBadGateway
|
||||
status := clienterror.HTTPStatusFromErrorOr(errDial, http.StatusBadGateway)
|
||||
if response != nil {
|
||||
if response.StatusCode > 0 {
|
||||
status = response.StatusCode
|
||||
|
||||
Reference in New Issue
Block a user