summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Avdey <eiri@eiri.ca>2021-02-17 16:50:02 -0400
committerEric Avdey <eiri@eiri.ca>2021-02-17 16:50:02 -0400
commit525716f1ce5f349da683363c73222179887b34a9 (patch)
tree3a19d8321c45f75baea9451afa3764ae50aa0474
parent0805b99699388a02943877ddb2da8f3229e089a1 (diff)
downloadcouchdb-3087-read-body-on-post-to-changes.tar.gz
Read and validate JSON payload on POST to _changes3087-read-body-on-post-to-changes
-rw-r--r--src/chttpd/src/chttpd_db.erl8
-rw-r--r--test/elixir/test/changes_test.exs58
2 files changed, 65 insertions, 1 deletions
diff --git a/src/chttpd/src/chttpd_db.erl b/src/chttpd/src/chttpd_db.erl
index 876371fc4..27a564be8 100644
--- a/src/chttpd/src/chttpd_db.erl
+++ b/src/chttpd/src/chttpd_db.erl
@@ -85,7 +85,13 @@ handle_request(#httpd{path_parts=[DbName|RestParts],method=Method}=Req)->
handle_changes_req(#httpd{method='POST'}=Req, Db) ->
chttpd:validate_ctype(Req, "application/json"),
- handle_changes_req1(Req, Db);
+ case chttpd:body_length(Req) of
+ 0 ->
+ handle_changes_req1(Req, Db);
+ _ ->
+ {JsonProps} = chttpd:json_body_obj(Req),
+ handle_changes_req1(Req#httpd{req_body = {JsonProps}}, Db)
+ end;
handle_changes_req(#httpd{method='GET'}=Req, Db) ->
handle_changes_req1(Req, Db);
handle_changes_req(#httpd{path_parts=[_,<<"_changes">>]}=Req, _Db) ->
diff --git a/test/elixir/test/changes_test.exs b/test/elixir/test/changes_test.exs
index 5bb376b9c..fe7329176 100644
--- a/test/elixir/test/changes_test.exs
+++ b/test/elixir/test/changes_test.exs
@@ -228,6 +228,64 @@ defmodule ChangesTest do
end
@tag :with_db
+ test "changes filtering on custom filter", context do
+ db_name = context[:db_name]
+ create_filters_view(db_name)
+
+ resp = Couch.post("/#{db_name}/_changes?filter=changes_filter/bop")
+ assert Enum.empty?(resp.body["results"]), "db must be empty"
+
+ {:ok, doc_resp} = create_doc(db_name, %{bop: "foom"})
+ rev = doc_resp.body["rev"]
+ create_doc(db_name, %{bop: false})
+
+ resp = Couch.post("/#{db_name}/_changes?filter=changes_filter/bop")
+ assert length(resp.body["results"]) == 1
+ change_rev = get_change_rev_at(resp.body["results"], 0)
+ assert change_rev == rev
+
+ resp = Couch.post("/#{db_name}/_changes?filter=changes_filter/bop",
+ body: %{doc_ids: ["doc1", "doc3", "doc4"]},
+ headers: ["Content-Type": "application/json"]
+ )
+ assert length(resp.body["results"]) == 1
+ change_rev = get_change_rev_at(resp.body["results"], 0)
+ assert change_rev == rev
+ end
+
+ @tag :with_db
+ test "changes fail on invalid payload", context do
+ db_name = context[:db_name]
+ create_filters_view(db_name)
+
+ resp = Couch.post("/#{db_name}/_changes?filter=changes_filter/bop",
+ body: "[\"doc1\"]",
+ headers: ["Content-Type": "application/json"]
+ )
+ assert resp.status_code == 400
+ assert resp.body["error"] == "bad_request"
+ assert resp.body["reason"] == "Request body must be a JSON object"
+
+ resp = Couch.post("/#{db_name}/_changes?filter=changes_filter/bop",
+ body: "{\"doc_ids\": [\"doc1\",",
+ headers: ["Content-Type": "application/json"]
+ )
+ assert resp.status_code == 400
+ assert resp.body["error"] == "bad_request"
+ assert resp.body["reason"] == "invalid UTF-8 JSON"
+
+ set_config({"httpd", "max_http_request_size", "16"})
+
+ resp = Couch.post("/#{db_name}/_changes?filter=changes_filter/bop",
+ body: %{doc_ids: ["doc1", "doc3", "doc4"]},
+ headers: ["Content-Type": "application/json"]
+ )
+ assert resp.status_code == 413
+ assert resp.body["error"] == "too_large"
+ assert resp.body["reason"] == "the request entity is too large"
+ end
+
+ @tag :with_db
test "COUCHDB-1037-empty result for ?limit=1&filter=foo/bar in some cases",
context do
db_name = context[:db_name]