mirror of
https://github.com/QuantumNous/new-api.git
synced 2026-03-30 04:40:59 +00:00
🧹 fix: harden request-body size handling and error unwrapping
Tighten oversized request handling across relay paths and make error matching reliable. - Align `MAX_REQUEST_BODY_MB` fallback to `32` in request body reader and decompression middleware - Stop ignoring `GetRequestBody` errors in relay retry paths; return consistent **413** on oversized bodies (400 for other read errors) - Add `Unwrap()` to `types.NewAPIError` so `errors.Is/As` can match wrapped underlying errors - `go test ./...` passes
This commit is contained in:
@@ -40,7 +40,7 @@ func GetRequestBody(c *gin.Context) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
maxMB := constant.MaxRequestBodyMB
|
maxMB := constant.MaxRequestBodyMB
|
||||||
if maxMB <= 0 {
|
if maxMB <= 0 {
|
||||||
maxMB = 64
|
maxMB = 32
|
||||||
}
|
}
|
||||||
maxBytes := int64(maxMB) << 20
|
maxBytes := int64(maxMB) << 20
|
||||||
|
|
||||||
|
|||||||
@@ -179,15 +179,24 @@ func Relay(c *gin.Context, relayFormat types.RelayFormat) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for ; retryParam.GetRetry() <= common.RetryTimes; retryParam.IncreaseRetry() {
|
for ; retryParam.GetRetry() <= common.RetryTimes; retryParam.IncreaseRetry() {
|
||||||
channel, err := getChannel(c, relayInfo, retryParam)
|
channel, channelErr := getChannel(c, relayInfo, retryParam)
|
||||||
if err != nil {
|
if channelErr != nil {
|
||||||
logger.LogError(c, err.Error())
|
logger.LogError(c, channelErr.Error())
|
||||||
newAPIError = err
|
newAPIError = channelErr
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
addUsedChannel(c, channel.Id)
|
addUsedChannel(c, channel.Id)
|
||||||
requestBody, _ := common.GetRequestBody(c)
|
requestBody, bodyErr := common.GetRequestBody(c)
|
||||||
|
if bodyErr != nil {
|
||||||
|
// Ensure consistent 413 for oversized bodies even when error occurs later (e.g., retry path)
|
||||||
|
if common.IsRequestBodyTooLargeError(bodyErr) || errors.Is(bodyErr, common.ErrRequestBodyTooLarge) {
|
||||||
|
newAPIError = types.NewErrorWithStatusCode(bodyErr, types.ErrorCodeReadRequestBodyFailed, http.StatusRequestEntityTooLarge, types.ErrOptionWithSkipRetry())
|
||||||
|
} else {
|
||||||
|
newAPIError = types.NewErrorWithStatusCode(bodyErr, types.ErrorCodeReadRequestBodyFailed, http.StatusBadRequest, types.ErrOptionWithSkipRetry())
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
c.Request.Body = io.NopCloser(bytes.NewBuffer(requestBody))
|
c.Request.Body = io.NopCloser(bytes.NewBuffer(requestBody))
|
||||||
|
|
||||||
switch relayFormat {
|
switch relayFormat {
|
||||||
@@ -473,7 +482,15 @@ func RelayTask(c *gin.Context) {
|
|||||||
logger.LogInfo(c, fmt.Sprintf("using channel #%d to retry (remain times %d)", channel.Id, retryParam.GetRetry()))
|
logger.LogInfo(c, fmt.Sprintf("using channel #%d to retry (remain times %d)", channel.Id, retryParam.GetRetry()))
|
||||||
//middleware.SetupContextForSelectedChannel(c, channel, originalModel)
|
//middleware.SetupContextForSelectedChannel(c, channel, originalModel)
|
||||||
|
|
||||||
requestBody, _ := common.GetRequestBody(c)
|
requestBody, err := common.GetRequestBody(c)
|
||||||
|
if err != nil {
|
||||||
|
if common.IsRequestBodyTooLargeError(err) || errors.Is(err, common.ErrRequestBodyTooLarge) {
|
||||||
|
taskErr = service.TaskErrorWrapperLocal(err, "read_request_body_failed", http.StatusRequestEntityTooLarge)
|
||||||
|
} else {
|
||||||
|
taskErr = service.TaskErrorWrapperLocal(err, "read_request_body_failed", http.StatusBadRequest)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
c.Request.Body = io.NopCloser(bytes.NewBuffer(requestBody))
|
c.Request.Body = io.NopCloser(bytes.NewBuffer(requestBody))
|
||||||
taskErr = taskRelayHandler(c, relayInfo)
|
taskErr = taskRelayHandler(c, relayInfo)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ func DecompressRequestMiddleware() gin.HandlerFunc {
|
|||||||
}
|
}
|
||||||
maxMB := constant.MaxRequestBodyMB
|
maxMB := constant.MaxRequestBodyMB
|
||||||
if maxMB <= 0 {
|
if maxMB <= 0 {
|
||||||
maxMB = 64
|
maxMB = 32
|
||||||
}
|
}
|
||||||
maxBytes := int64(maxMB) << 20
|
maxBytes := int64(maxMB) << 20
|
||||||
|
|
||||||
|
|||||||
@@ -94,6 +94,14 @@ type NewAPIError struct {
|
|||||||
StatusCode int
|
StatusCode int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unwrap enables errors.Is / errors.As to work with NewAPIError by exposing the underlying error.
|
||||||
|
func (e *NewAPIError) Unwrap() error {
|
||||||
|
if e == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return e.Err
|
||||||
|
}
|
||||||
|
|
||||||
func (e *NewAPIError) GetErrorCode() ErrorCode {
|
func (e *NewAPIError) GetErrorCode() ErrorCode {
|
||||||
if e == nil {
|
if e == nil {
|
||||||
return ""
|
return ""
|
||||||
|
|||||||
Reference in New Issue
Block a user