diff options
author | Bessenyei Balázs Donát <bessbd@users.noreply.github.com> | 2021-02-03 10:54:22 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-02-03 10:54:22 +0100 |
commit | 94df4bb2379eac40c9888a2ca8fb295242d023d6 (patch) | |
tree | be38e0933c20f03b23df0940b63addfbbf7b9dd5 | |
parent | 46b346e30b96d3774f83ee2d366e12dc1ce50749 (diff) | |
download | couchdb-94df4bb2379eac40c9888a2ca8fb295242d023d6.tar.gz |
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.
-rw-r--r-- | src/chttpd/src/chttpd_db.erl | 9 | ||||
-rw-r--r-- | src/chttpd/test/eunit/chttpd_db_attachment_size_tests.erl | 12 | ||||
-rw-r--r-- | 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 3ca082435..7b4fdef9c 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 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). |