From 2ee6c926c3d283ec8662d6fa33bcaaa00f054026 Mon Sep 17 00:00:00 2001 From: Andrei Mihu Date: Mon, 30 Oct 2023 20:42:04 +0000 Subject: [PATCH] Revert allowing request bodies on RPC GET operations. --- CHANGELOG.md | 1 - server/api_rpc.go | 52 +++++++++++++++++++++++------------------------ 2 files changed, 26 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5610b0986b..e1ff138c7c 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,6 @@ The format is based on [keep a changelog](http://keepachangelog.com) and this pr ## [Unreleased] ### Changed -- RPC now allows a request payload on GET requests. - RPC now allows omitting the `unwrap` parameter for requests with empty payloads. ## [3.18.0] - 2023-10-24 diff --git a/server/api_rpc.go b/server/api_rpc.go index 5746af2389..5d3663eaaf 100644 --- a/server/api_rpc.go +++ b/server/api_rpc.go @@ -142,48 +142,48 @@ func (s *ApiServer) RpcFuncHttp(w http.ResponseWriter, r *http.Request) { // indicate that raw behaviour is expected. _, unwrap := queryParams["unwrap"] - // Prepare input to function. Attempt to read request body no matter what the HTTP method is. + // Prepare input to function. var payload string - if b, err := io.ReadAll(r.Body); err == nil && len(b) > 0 { - recvBytes = len(b) - // Maybe attempt to decode to a JSON string to mimic existing GRPC Gateway behaviour. - if !unwrap { - err = json.Unmarshal(b, &payload) - if err != nil { + if r.Method == "POST" { + b, err := io.ReadAll(r.Body) + if err != nil { + // Request body too large. + if err.Error() == "http: request body too large" { w.Header().Set("content-type", "application/json") w.WriteHeader(http.StatusBadRequest) - sentBytes, err = w.Write(badJSONBytes) + sentBytes, err = w.Write(requestBodyTooLargeBytes) if err != nil { s.logger.Debug("Error writing response to client", zap.Error(err)) } return } - } else { - payload = string(b) - } - } else if err == io.EOF && r.Method == http.MethodGet { - // GET requests with no request body always return an EOF immediately. A body is not usually - // expected, so treat this as a simple GET with no request body rather than an error. - } else if err != nil { - // Request body too large. - if err.Error() == "http: request body too large" { + + // Other error reading request body. w.Header().Set("content-type", "application/json") - w.WriteHeader(http.StatusBadRequest) - sentBytes, err = w.Write(requestBodyTooLargeBytes) + w.WriteHeader(http.StatusInternalServerError) + sentBytes, err = w.Write(internalServerErrorBytes) if err != nil { s.logger.Debug("Error writing response to client", zap.Error(err)) } return } + recvBytes = len(b) - // Other error reading request body. - w.Header().Set("content-type", "application/json") - w.WriteHeader(http.StatusInternalServerError) - sentBytes, err = w.Write(internalServerErrorBytes) - if err != nil { - s.logger.Debug("Error writing response to client", zap.Error(err)) + // Maybe attempt to decode to a JSON string to mimic existing GRPC Gateway behaviour. + if recvBytes > 0 && !unwrap { + err = json.Unmarshal(b, &payload) + if err != nil { + w.Header().Set("content-type", "application/json") + w.WriteHeader(http.StatusBadRequest) + sentBytes, err = w.Write(badJSONBytes) + if err != nil { + s.logger.Debug("Error writing response to client", zap.Error(err)) + } + return + } + } else { + payload = string(b) } - return } queryParams.Del("http_key")