This is an automated email from the ASF dual-hosted git repository.

rnewson pushed a commit to branch compress-responses-on-demand
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 4da002b64808097b36f0c57b4a65b5b40a0caa81
Author: Robert Newson <[email protected]>
AuthorDate: Thu Aug 6 09:41:13 2026 +0100

    compress responses if client accepts
---
 src/chttpd/src/chttpd.erl     | 12 +++++++++++-
 src/couch/src/couch_httpd.erl | 26 ++++++++++++++++++++++++--
 2 files changed, 35 insertions(+), 3 deletions(-)

diff --git a/src/chttpd/src/chttpd.erl b/src/chttpd/src/chttpd.erl
index a078df2af..ebfc113e4 100644
--- a/src/chttpd/src/chttpd.erl
+++ b/src/chttpd/src/chttpd.erl
@@ -921,7 +921,17 @@ start_chunked_response(#httpd{mochi_req = MochiReq} = Req, 
Code, Headers0) ->
 send_chunk({remote, _Pid, _Ref} = Resp, Data) ->
     couch_httpd:send_chunk(Resp, Data);
 send_chunk(Resp, Data) ->
-    Resp:write_chunk(Data),
+    case erlang:get(chunked_response_zstream) of
+        undefined ->
+            Resp:write_chunk(Data);
+        Z ->
+            Flush =
+                if
+                    Data == [] -> finish;
+                    true -> sync
+                end,
+            Resp:write_chunk(zlib:deflate(Z, Data, Flush))
+    end,
     {ok, Resp}.
 
 send_response(Req, Code, Headers0, Body) ->
diff --git a/src/couch/src/couch_httpd.erl b/src/couch/src/couch_httpd.erl
index 0a9e39e7a..06637c6b2 100644
--- a/src/couch/src/couch_httpd.erl
+++ b/src/couch/src/couch_httpd.erl
@@ -858,7 +858,17 @@ http_1_0_keep_alive(Req, Headers) ->
 
 start_chunked_response(#httpd{mochi_req = MochiReq} = Req, Code, Headers0) ->
     Headers1 = add_headers(Req, Headers0),
-    Resp = handle_response(Req, Code, Headers1, chunked, respond),
+    Headers2 =
+        case accepts_gzip(Req) of
+            true ->
+                Z = zlib:open(),
+                ok = zlib:deflateInit(Z),
+                erlang:put(chunked_response_zstream, Z),
+                [{~"Content-Encoding", ~"gzip"} | Headers1];
+            false ->
+                Headers1
+        end,
+    Resp = handle_response(Req, Code, Headers2, chunked, respond),
     case MochiReq:get(method) of
         'HEAD' -> throw({http_head_abort, Resp});
         _ -> ok
@@ -1395,10 +1405,22 @@ before_response(Req0, Code0, Headers0, {json, JsonObj}) 
->
     {ok, {Req1, Code1, Headers1, Body1}} =
         chttpd_plugin:before_response(Req0, Code0, Headers0, JsonObj),
     Body2 = [start_jsonp(), ?JSON_ENCODE(Body1), end_jsonp(), $\n],
-    {ok, {Req1, Code1, Headers1, Body2}};
+    {Headers2, Body3} = maybe_compress_request_body(Req0, Headers1, Body2),
+    {ok, {Req1, Code1, Headers2, Body3}};
 before_response(Req0, Code0, Headers0, Args0) ->
     chttpd_plugin:before_response(Req0, Code0, Headers0, Args0).
 
+maybe_compress_request_body(Req, Headers, Body) ->
+    case accepts_gzip(Req) of
+        true ->
+            {[{~"Content-Encoding", ~"gzip"} | Headers], zlib:gzip(Body)};
+        false ->
+            {Headers, Body}
+    end.
+
+accepts_gzip(#httpd{} = Req) ->
+    lists:member("gzip", accepted_encodings(Req)).
+
 respond_(#httpd{mochi_req = MochiReq} = Req, Code, Headers, Args, Type) ->
     case MochiReq:get(socket) of
         {remote, Pid, Ref} ->

Reply via email to