diff options
-rw-r--r-- | THANKS | 1 | ||||
-rw-r--r-- | share/Makefile.am | 1 | ||||
-rw-r--r-- | share/www/script/couch_tests.js | 1 | ||||
-rw-r--r-- | share/www/script/test/method_override.js | 40 | ||||
-rw-r--r-- | src/couchdb/couch_httpd.erl | 21 |
5 files changed, 62 insertions, 2 deletions
@@ -61,5 +61,6 @@ suggesting improvements or submitting changes. Some of these people are: * Jason Smith <jhs@proven-corporation.com> * Dmitry Unkovsky <oil.crayons@gmail.com> * Zachary Zolton <zachary.zolton@gmail.com> + * Brian Jenkins <bonkydog@bonkydog.com> For a list of authors see the `AUTHORS` file. diff --git a/share/Makefile.am b/share/Makefile.am index 9c68e159..fc052de0 100644 --- a/share/Makefile.am +++ b/share/Makefile.am @@ -138,6 +138,7 @@ nobase_dist_localdata_DATA = \ www/script/test/lorem.txt \ www/script/test/lorem_b64.txt \ www/script/test/lots_of_docs.js \ + www/script/test/method_override.js \ www/script/test/multiple_rows.js \ www/script/test/oauth.js \ www/script/test/proxyauth.js \ diff --git a/share/www/script/couch_tests.js b/share/www/script/couch_tests.js index 383d2ee6..dc283bba 100644 --- a/share/www/script/couch_tests.js +++ b/share/www/script/couch_tests.js @@ -59,6 +59,7 @@ loadTest("jsonp.js"); loadTest("large_docs.js"); loadTest("list_views.js"); loadTest("lots_of_docs.js"); +loadTest("method_override.js"); loadTest("multiple_rows.js"); loadScript("script/oauth.js"); loadScript("script/sha1.js"); diff --git a/share/www/script/test/method_override.js b/share/www/script/test/method_override.js new file mode 100644 index 00000000..26e9bee0 --- /dev/null +++ b/share/www/script/test/method_override.js @@ -0,0 +1,40 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +// Allow broken HTTP clients to fake a full method vocabulary with an X-HTTP-METHOD-OVERRIDE header +couchTests.method_override = function(debug) { + var result = JSON.parse(CouchDB.request("GET", "/").responseText); + T(result.couchdb == "Welcome"); + + var db = new CouchDB("test_suite_db", {"X-Couch-Full-Commit":"false"}); + db.deleteDb(); + + db.createDb(); + + var doc = {bob : "connie"}; + xhr = CouchDB.request("POST", "/test_suite_db/fnord", {body: JSON.stringify(doc), headers:{"X-HTTP-Method-Override" : "PUT"}}); + T(xhr.status == 201); + + doc = db.open("fnord"); + T(doc.bob == "connie"); + + xhr = CouchDB.request("POST", "/test_suite_db/fnord?rev=" + doc._rev, {headers:{"X-HTTP-Method-Override" : "DELETE"}}); + T(xhr.status == 200) + + xhr = CouchDB.request("GET", "/test_suite_db/fnord2", {body: JSON.stringify(doc), headers:{"X-HTTP-Method-Override" : "PUT"}}); + // Method Override is ignored when original Method isn't POST + T(xhr.status == 404); + + doc = db.open("fnord"); + T(doc == null); + +}; diff --git a/src/couchdb/couch_httpd.erl b/src/couchdb/couch_httpd.erl index 331546eb..cb71203a 100644 --- a/src/couchdb/couch_httpd.erl +++ b/src/couchdb/couch_httpd.erl @@ -218,9 +218,26 @@ handle_request_int(MochiReq, DefaultFun, Meth -> couch_util:to_existing_atom(Meth) end, increment_method_stats(Method1), + + % allow broken HTTP clients to fake a full method vocabulary with an X-HTTP-METHOD-OVERRIDE header + MethodOverride = MochiReq:get_primary_header_value("X-HTTP-Method-Override"), + Method2 = case lists:member(MethodOverride, ["GET", "HEAD", "POST", "PUT", "DELETE", "TRACE", "CONNECT", "COPY"]) of + true -> + ?LOG_INFO("MethodOverride: ~s (real method was ~s)", [MethodOverride, Method1]), + case Method1 of + 'POST' -> list_to_atom(MethodOverride); + _ -> + % Ignore X-HTTP-Method-Override when the original verb isn't POST. + % I'd like to send a 406 error to the client, but that'd require a nasty refactor. + % throw({not_acceptable, <<"X-HTTP-Method-Override may only be used with POST requests.">>}) + Method1 + end; + _ -> Method1 + end, + % alias HEAD to GET as mochiweb takes care of stripping the body - Method = case Method1 of - 'HEAD' -> 'GET'; + Method = case Method2 of + 'HEAD' -> 'GET'; Other -> Other end, |