summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBessenyei Balázs Donát <bessbd@users.noreply.github.com>2021-02-02 17:46:02 +0100
committerGitHub <noreply@github.com>2021-02-02 17:46:02 +0100
commit235d1e946891e310f301e00551155c205c293ceb (patch)
tree5274d8ece18b191d444467f1be9c65ab6a8a48ed
parent0837b5162708d1c4482e404cc7488f70f2d1e301 (diff)
downloadcouchdb-235d1e946891e310f301e00551155c205c293ceb.tar.gz
Fix PUT of multipart/related attachments support for Transfer-Encoding: chunked (#3340)
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.
-rw-r--r--src/chttpd/src/chttpd_db.erl9
-rw-r--r--src/chttpd/test/eunit/chttpd_db_attachment_size_tests.erl12
-rw-r--r--src/couch/src/couch_httpd.erl3
3 files changed, 22 insertions, 2 deletions
diff --git a/src/chttpd/src/chttpd_db.erl b/src/chttpd/src/chttpd_db.erl
index 0e3701aba..876371fc4 100644
--- a/src/chttpd/src/chttpd_db.erl
+++ b/src/chttpd/src/chttpd_db.erl
@@ -1242,6 +1242,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 0ab08dd80..227b29c5b 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 fb03bacb3..d89c74957 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).