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

bessbd pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git


The following commit(s) were added to refs/heads/main by this push:
     new 94df4bb  Fix PUT of multipart/related attachments support for 
Transfer-Encoding: chunked (#3360)
94df4bb is described below

commit 94df4bb2379eac40c9888a2ca8fb295242d023d6
Author: Bessenyei Balázs Donát <[email protected]>
AuthorDate: Wed Feb 3 10:54:22 2021 +0100

    Fix PUT of multipart/related attachments support for Transfer-Encoding: 
chunked (#3360)
    
    Transfer-Encoding: chunked causes the server to wait indefinitely, then 
issue a a 500 error when the client finally hangs up, when PUTing a 
multipart/related document + attachments.
    
    This commit fixes that issue by adding proper handling for chunked 
multipart/related requests.
---
 src/chttpd/src/chttpd_db.erl                              |  9 +++++++++
 src/chttpd/test/eunit/chttpd_db_attachment_size_tests.erl | 12 +++++++++++-
 src/couch/src/couch_httpd.erl                             |  3 ++-
 3 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/src/chttpd/src/chttpd_db.erl b/src/chttpd/src/chttpd_db.erl
index 3ca0824..7b4fdef 100644
--- a/src/chttpd/src/chttpd_db.erl
+++ b/src/chttpd/src/chttpd_db.erl
@@ -1407,6 +1407,15 @@ bulk_get_multipart_boundary() ->
 receive_request_data(Req) ->
     receive_request_data(Req, chttpd:body_length(Req)).
 
+receive_request_data(Req, Len) when Len == chunked ->
+    Ref = make_ref(),
+    ChunkFun = fun({_Length, Binary}, _State) ->
+        self() ! {chunk, Ref, Binary}
+    end,
+    couch_httpd:recv_chunked(Req, 4096, ChunkFun, ok),
+    GetChunk = fun GC() -> receive {chunk, Ref, Binary} -> {Binary, GC} end 
end,
+    {receive {chunk, Ref, Binary} -> Binary end, GetChunk};
+
 receive_request_data(Req, LenLeft) when LenLeft > 0 ->
     Len = erlang:min(4096, LenLeft),
     Data = chttpd:recv(Req, Len),
diff --git a/src/chttpd/test/eunit/chttpd_db_attachment_size_tests.erl 
b/src/chttpd/test/eunit/chttpd_db_attachment_size_tests.erl
index 0ab08dd..227b29c 100644
--- a/src/chttpd/test/eunit/chttpd_db_attachment_size_tests.erl
+++ b/src/chttpd/test/eunit/chttpd_db_attachment_size_tests.erl
@@ -56,7 +56,8 @@ attachment_size_test_() ->
                     fun put_inline/1,
                     fun put_simple/1,
                     fun put_simple_chunked/1,
-                    fun put_mp_related/1
+                    fun put_mp_related/1,
+                    fun put_chunked_mp_related/1
                 ]
             }
         }
@@ -111,6 +112,15 @@ put_mp_related(Url) ->
     end).
 
 
+put_chunked_mp_related(Url) ->
+    ?_test(begin
+       Headers = [?CONTENT_MULTI_RELATED],
+       Body = mp_body(50),
+       Status = put_req_chunked(Url ++ "/doc4", Headers, Body),
+       ?assert(Status =:= 201 orelse Status =:= 202)
+    end).
+
+
 % Helper functions
 
 create_db(Url) ->
diff --git a/src/couch/src/couch_httpd.erl b/src/couch/src/couch_httpd.erl
index fb03bac..d89c749 100644
--- a/src/couch/src/couch_httpd.erl
+++ b/src/couch/src/couch_httpd.erl
@@ -589,7 +589,8 @@ recv_chunked(#httpd{mochi_req=MochiReq}, MaxChunkSize, 
ChunkFun, InitState) ->
     % Fun is called once with each chunk
     % Fun({Length, Binary}, State)
     % called with Length == 0 on the last time.
-    MochiReq:stream_body(MaxChunkSize, ChunkFun, InitState).
+    MochiReq:stream_body(MaxChunkSize, ChunkFun, InitState,
+        config:get_integer("httpd", "max_http_request_size", 4294967296)).
 
 body_length(#httpd{mochi_req=MochiReq}) ->
     MochiReq:get(body_length).

Reply via email to