summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--share/www/script/test/basics.js28
-rw-r--r--share/www/script/test/view_errors.js14
-rw-r--r--src/couchdb/couch_httpd_db.erl25
-rw-r--r--src/couchdb/couch_httpd_view.erl18
4 files changed, 78 insertions, 7 deletions
diff --git a/share/www/script/test/basics.js b/share/www/script/test/basics.js
index 8adf5a84..2eb49ebe 100644
--- a/share/www/script/test/basics.js
+++ b/share/www/script/test/basics.js
@@ -168,4 +168,32 @@ couchTests.basics = function(debug) {
// deleting a non-existent doc should be 404
xhr = CouchDB.request("DELETE", "/test_suite_db/doc-does-not-exist");
T(xhr.status == 404);
+
+ // Check some common error responses.
+ // PUT body not an object
+ xhr = CouchDB.request("PUT", "/test_suite_db/bar", {body: "[]"});
+ T(xhr.status == 400);
+ result = JSON.parse(xhr.responseText);
+ T(result.error == "bad_request");
+ T(result.reason == "Document must be a JSON object");
+
+ // Body of a _bulk_docs is not an object
+ xhr = CouchDB.request("POST", "/test_suite_db/_bulk_docs", {body: "[]"});
+ T(xhr.status == 400);
+ result = JSON.parse(xhr.responseText);
+ T(result.error == "bad_request");
+ T(result.reason == "Body must be a JSON object");
+
+ // Body of an _all_docs multi-get is not a {"key": [...]} structure.
+ xhr = CouchDB.request("POST", "/test_suite_db/_all_docs", {body: "[]"});
+ T(xhr.status == 400);
+ result = JSON.parse(xhr.responseText);
+ T(result.error == "bad_request");
+ T(result.reason == "Body must be a JSON object");
+ var data = "{\"keys\": 1}";
+ xhr = CouchDB.request("POST", "/test_suite_db/_all_docs", {body:data});
+ T(xhr.status == 400);
+ result = JSON.parse(xhr.responseText);
+ T(result.error == "bad_request");
+ T(result.reason == "`keys` member must be a array.");
};
diff --git a/share/www/script/test/view_errors.js b/share/www/script/test/view_errors.js
index 60ccca59..b9a6aa63 100644
--- a/share/www/script/test/view_errors.js
+++ b/share/www/script/test/view_errors.js
@@ -94,4 +94,18 @@ couchTests.view_errors = function(debug) {
} catch(e) {
T(e.error == "query_parse_error");
}
+
+ // Check error responses for invalid multi-get bodies.
+ var path = "/test_suite_db/_design/test/_view/no_reduce";
+ var xhr = CouchDB.request("POST", path, {body: "[]"});
+ T(xhr.status == 400);
+ result = JSON.parse(xhr.responseText);
+ T(result.error == "bad_request");
+ T(result.reason == "Body must be a JSON object");
+ var data = "{\"keys\": 1}";
+ xhr = CouchDB.request("POST", path, {body:data});
+ T(xhr.status == 400);
+ result = JSON.parse(xhr.responseText);
+ T(result.error == "bad_request");
+ T(result.reason == "`keys` member must be a array.");
};
diff --git a/src/couchdb/couch_httpd_db.erl b/src/couchdb/couch_httpd_db.erl
index 209dc75e..bacce4ae 100644
--- a/src/couchdb/couch_httpd_db.erl
+++ b/src/couchdb/couch_httpd_db.erl
@@ -126,7 +126,13 @@ db_req(#httpd{path_parts=[_,<<"_ensure_full_commit">>]}=Req, _Db) ->
db_req(#httpd{method='POST',path_parts=[_,<<"_bulk_docs">>]}=Req, Db) ->
couch_stats_collector:increment({httpd, bulk_requests}),
- {JsonProps} = couch_httpd:json_body(Req),
+ JsonProps =
+ case couch_httpd:json_body(Req) of
+ {Fields} ->
+ Fields;
+ _ ->
+ throw({bad_request, "Body must be a JSON object"})
+ end,
DocsArray = proplists:get_value(<<"docs">>, JsonProps),
case couch_httpd:header_value(Req, "X-Couch-Full-Commit", "false") of
"true" ->
@@ -220,9 +226,20 @@ db_req(#httpd{method='GET',path_parts=[_,<<"_all_docs">>]}=Req, Db) ->
all_docs_view(Req, Db, nil);
db_req(#httpd{method='POST',path_parts=[_,<<"_all_docs">>]}=Req, Db) ->
- {Props} = couch_httpd:json_body(Req),
- Keys = proplists:get_value(<<"keys">>, Props, nil),
- all_docs_view(Req, Db, Keys);
+ case couch_httpd:json_body(Req) of
+ {Fields} ->
+ case proplists:get_value(<<"keys">>, Fields, nil) of
+ nil ->
+ ?LOG_DEBUG("POST to _all_docs with no keys member.", []),
+ all_docs_view(Req, Db, nil);
+ Keys when is_list(Keys) ->
+ all_docs_view(Req, Db, Keys);
+ _ ->
+ throw({bad_request, "`keys` member must be a array."})
+ end;
+ _ ->
+ throw({bad_request, "Body must be a JSON object"})
+ end;
db_req(#httpd{path_parts=[_,<<"_all_docs">>]}=Req, _Db) ->
send_method_not_allowed(Req, "GET,HEAD,POST");
diff --git a/src/couchdb/couch_httpd_view.erl b/src/couchdb/couch_httpd_view.erl
index 4054eb05..0348cf8b 100644
--- a/src/couchdb/couch_httpd_view.erl
+++ b/src/couchdb/couch_httpd_view.erl
@@ -56,9 +56,21 @@ handle_view_req(#httpd{method='GET',
handle_view_req(#httpd{method='POST',
path_parts=[_Db, _Design, DName, _View, ViewName]}=Req, Db) ->
- {Props} = couch_httpd:json_body(Req),
- Keys = proplists:get_value(<<"keys">>, Props, nil),
- design_doc_view(Req, Db, DName, ViewName, Keys);
+ case couch_httpd:json_body(Req) of
+ {Fields} ->
+ case proplists:get_value(<<"keys">>, Fields, nil) of
+ nil ->
+ Fmt = "POST to view ~p/~p in database ~p with no keys member.",
+ ?LOG_DEBUG(Fmt, [DName, ViewName, Db]),
+ design_doc_view(Req, Db, DName, ViewName, nil);
+ Keys when is_list(Keys) ->
+ design_doc_view(Req, Db, DName, ViewName, Keys);
+ _ ->
+ throw({bad_request, "`keys` member must be a array."})
+ end;
+ _ ->
+ throw({bad_request, "Body must be a JSON object"})
+ end;
handle_view_req(Req, _Db) ->
send_method_not_allowed(Req, "GET,POST,HEAD").