From 506f1117dd2ba09dd76e26cf993fdc107e253f74 Mon Sep 17 00:00:00 2001 From: Luis Pater Date: Tue, 25 Nov 2025 11:37:02 +0800 Subject: [PATCH] **fix(handlers): refactor API response capture to append data safely** - Introduced `appendAPIResponse` helper to preserve and append data to existing API responses. - Ensured newline inclusion when appending, if necessary. - Improved `nil` and data type checks for response handling. - Updated middleware to skip request logging for `GET` requests. --- internal/api/middleware/request_logging.go | 6 +++++ sdk/api/handlers/handlers.go | 31 +++++++++++++++++++--- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/internal/api/middleware/request_logging.go b/internal/api/middleware/request_logging.go index 63a5dbfc..0bef6752 100644 --- a/internal/api/middleware/request_logging.go +++ b/internal/api/middleware/request_logging.go @@ -6,6 +6,7 @@ package middleware import ( "bytes" "io" + "net/http" "strings" "github.com/gin-gonic/gin" @@ -24,6 +25,11 @@ func RequestLoggingMiddleware(logger logging.RequestLogger) gin.HandlerFunc { return } + if c.Request.Method == http.MethodGet { + c.Next() + return + } + path := c.Request.URL.Path if !shouldLogRequest(path) { c.Next() diff --git a/sdk/api/handlers/handlers.go b/sdk/api/handlers/handlers.go index 7c64aaba..76280b3a 100644 --- a/sdk/api/handlers/handlers.go +++ b/sdk/api/handlers/handlers.go @@ -4,6 +4,7 @@ package handlers import ( + "bytes" "fmt" "net/http" "strings" @@ -120,11 +121,11 @@ func (h *BaseAPIHandler) GetContextWithCancel(handler interfaces.APIHandler, c * data := params[0] switch data.(type) { case []byte: - c.Set("API_RESPONSE", data.([]byte)) + appendAPIResponse(c, data.([]byte)) case error: - c.Set("API_RESPONSE", []byte(data.(error).Error())) + appendAPIResponse(c, []byte(data.(error).Error())) case string: - c.Set("API_RESPONSE", []byte(data.(string))) + appendAPIResponse(c, []byte(data.(string))) case bool: case nil: } @@ -135,6 +136,28 @@ func (h *BaseAPIHandler) GetContextWithCancel(handler interfaces.APIHandler, c * } } +// appendAPIResponse preserves any previously captured API response and appends new data. +func appendAPIResponse(c *gin.Context, data []byte) { + if c == nil || len(data) == 0 { + return + } + + if existing, exists := c.Get("API_RESPONSE"); exists { + if existingBytes, ok := existing.([]byte); ok && len(existingBytes) > 0 { + combined := make([]byte, 0, len(existingBytes)+len(data)+1) + combined = append(combined, existingBytes...) + if existingBytes[len(existingBytes)-1] != '\n' { + combined = append(combined, '\n') + } + combined = append(combined, data...) + c.Set("API_RESPONSE", combined) + return + } + } + + c.Set("API_RESPONSE", bytes.Clone(data)) +} + // ExecuteWithAuthManager executes a non-streaming request via the core auth manager. // This path is the only supported execution route. func (h *BaseAPIHandler) ExecuteWithAuthManager(ctx context.Context, handlerType, modelName string, rawJSON []byte, alt string) ([]byte, *interfaces.ErrorMessage) { @@ -297,7 +320,7 @@ func (h *BaseAPIHandler) ExecuteStreamWithAuthManager(ctx context.Context, handl func (h *BaseAPIHandler) getRequestDetails(modelName string) (providers []string, normalizedModel string, metadata map[string]any, err *interfaces.ErrorMessage) { // Resolve "auto" model to an actual available model first resolvedModelName := util.ResolveAutoModel(modelName) - + providerName, extractedModelName, isDynamic := h.parseDynamicModel(resolvedModelName) // First, normalize the model name to handle suffixes like "-thinking-128"