summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Avdey <eiri@eiri.ca>2021-08-25 09:10:35 -0300
committerEric Avdey <eiri@eiri.ca>2021-08-25 09:10:35 -0300
commitfb55897a93e7aaa8ea5b8284549bd07d489fc5b8 (patch)
tree9d4e62537e1c797b2f12f57b8cd079035652975a
parent1b8d4b73bc9ea67bfe0df5a41e24ea864f4c846d (diff)
downloadcouchdb-fix-delete-chunked-response.tar.gz
Discard a payload on a delete attachment requestfix-delete-chunked-response
While including a payload within a DELETE request is not forbidden by RFC7231 its presence on a delete attachment request leaves a mochiweb acceptor in a semi-opened state since mochiweb's using lazy load for the request bodies. This makes a next immediate request to the same acceptor to hung until previous request's receive timeout. This PR adds a step to explicitly "drain" and discard an entity body on a delete attachment request to prevent that.
-rw-r--r--src/chttpd/src/chttpd_db.erl3
-rw-r--r--test/elixir/test/attachments_test.exs15
2 files changed, 18 insertions, 0 deletions
diff --git a/src/chttpd/src/chttpd_db.erl b/src/chttpd/src/chttpd_db.erl
index ffdab2a29..e803454f4 100644
--- a/src/chttpd/src/chttpd_db.erl
+++ b/src/chttpd/src/chttpd_db.erl
@@ -857,6 +857,9 @@ db_req(#httpd{path_parts=[_DbName, <<"_local">> | _Rest]}, _Db) ->
db_req(#httpd{path_parts=[_, DocId]}=Req, Db) ->
db_doc_req(Req, Db, DocId);
+db_req(#httpd{method='DELETE', path_parts=[_, DocId | FileNameParts]}=Req, Db) ->
+ chttpd:body(Req),
+ db_attachment_req(Req, Db, DocId, FileNameParts);
db_req(#httpd{path_parts=[_, DocId | FileNameParts]}=Req, Db) ->
db_attachment_req(Req, Db, DocId, FileNameParts).
diff --git a/test/elixir/test/attachments_test.exs b/test/elixir/test/attachments_test.exs
index c89486a8e..2bf38de95 100644
--- a/test/elixir/test/attachments_test.exs
+++ b/test/elixir/test/attachments_test.exs
@@ -124,6 +124,21 @@ defmodule AttachmentsTest do
end
@tag :with_db
+ test "delete attachment request with a payload should not block following requests", context do
+ db_name = context[:db_name]
+
+ resp = Couch.put("/#{db_name}/bin_doc", body: @bin_att_doc, query: %{w: 3})
+ assert resp.status_code in [201, 202]
+ rev = resp.body["rev"]
+
+ resp = Couch.delete("/#{db_name}/bin_doc/foo.txt", body: 'some payload', query: %{w: 3, rev: rev}, ibrowse: [{:max_sessions, 1}, {:max_pipeline_size, 1}])
+ assert resp.status_code == 200
+
+ resp = Couch.get("/", timeout: 1000, ibrowse: [{:max_sessions, 1}, {:max_pipeline_size, 1}])
+ assert resp.status_code == 200
+ end
+
+ @tag :with_db
test "saves binary", context do
db_name = context[:db_name]