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} ->
