From 8d703a3fb4de55ed6b5558e80cb6278e4d4dde95 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Thu, 10 Jun 2021 16:11:24 +0200 Subject: [PATCH] :sparkles: Write transit data to response output-stream. Previously, all responses from GET and POST requests are serialized to a byte array (using transit) which is returned as response body. With this commit, the response body of POST requests is written directly to the response output-stream, reducing the memmory need to perform that operation. The responses for GET request still uses the old mechanism because we need the whole response as byte array for calculate the ETAG and check it before returning the body. --- backend/src/app/http/middleware.clj | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/backend/src/app/http/middleware.clj b/backend/src/app/http/middleware.clj index 91c275cf02..b979b8431a 100644 --- a/backend/src/app/http/middleware.clj +++ b/backend/src/app/http/middleware.clj @@ -13,6 +13,7 @@ [buddy.core.codecs :as bc] [buddy.core.hash :as bh] [clojure.java.io :as io] + [ring.core.protocols :as rp] [ring.middleware.cookies :refer [wrap-cookies]] [ring.middleware.keyword-params :refer [wrap-keyword-params]] [ring.middleware.multipart-params :refer [wrap-multipart-params]] @@ -73,17 +74,28 @@ {:name ::parse-request-body :compile (constantly wrap-parse-request-body)}) +(defn- transit-streamable-body + [data opts] + (reify rp/StreamableResponseBody + (write-body-to-stream [_ response output-stream] + (try + (let [tw (t/writer output-stream opts)] + (t/write! tw data)) + (finally + (.close ^java.io.OutputStream output-stream)))))) + (defn- impl-format-response-body - [response] + [response request] (let [body (:body response) - type :json-verbose] + opts {:type :json-verbose}] (cond (coll? body) (-> response - (assoc :body (t/encode body {:type type})) - (update :headers assoc - "content-type" - "application/transit+json")) + (update :headers assoc "content-type" "application/transit+json") + (assoc :body + (if (= :post (:request-method request)) + (transit-streamable-body body opts) + (t/encode body opts)))) (nil? body) (assoc response :status 204 :body "") @@ -96,7 +108,7 @@ (fn [request] (let [response (handler request)] (cond-> response - (map? response) (impl-format-response-body))))) + (map? response) (impl-format-response-body request))))) (def format-response-body {:name ::format-response-body