diff options
-rw-r--r-- | share/www/script/test/basics.js | 28 | ||||
-rw-r--r-- | share/www/script/test/view_errors.js | 14 | ||||
-rw-r--r-- | src/couchdb/couch_httpd_db.erl | 25 | ||||
-rw-r--r-- | src/couchdb/couch_httpd_view.erl | 18 |
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"). |