You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@couchdb.apache.org by Brian Jenkins <br...@brianjenkins.org> on 2010/06/10 21:59:00 UTC

Patch: X-HTTP-METHOD-OVERRIDE header support

Hello.

Please excuse my Erlang -- I've learned just enough to hack in support
for X-HTTP-METHOD-OVERRIDE headers.

Also available in the trunk and 0.11.x branches here:
http://github.com/bonkydog/couchdb

Best,
Brian

---
 share/Makefile.am                        |    1 +
 share/www/script/couch_tests.js          |    1 +
 share/www/script/test/method_override.js |   36 ++++++++++++++++++++++++++++++
 src/couchdb/couch_httpd.erl              |   12 ++++++++-
 4 files changed, 48 insertions(+), 2 deletions(-)
 create mode 100644 share/www/script/test/method_override.js

diff --git a/share/Makefile.am b/share/Makefile.am
index 1622130..cb9aae2 100644
--- a/share/Makefile.am
+++ b/share/Makefile.am
@@ -136,6 +136,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 4225ce7..4f0d282 100644
--- a/share/www/script/couch_tests.js
+++ b/share/www/script/couch_tests.js
@@ -58,6 +58,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 0000000..bc4d52f
--- /dev/null
+++ b/share/www/script/test/method_override.js
@@ -0,0 +1,36 @@
+// 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:{"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:{"Method-Override" : "DELETE"}});
+  T(xhr.status == 200)
+
+  doc = db.open("fnord");
+  T(doc == null);
+
+};
\ No newline at end of file
diff --git a/src/couchdb/couch_httpd.erl b/src/couchdb/couch_httpd.erl
index a8f0bb5..558149f 100644
--- a/src/couchdb/couch_httpd.erl
+++ b/src/couchdb/couch_httpd.erl
@@ -218,9 +218,17 @@ 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("Method-Override"),
+    Method2 = case lists:member(MethodOverride, ["GET", "HEAD",
"POST", "PUT", "DELETE", "TRACE", "CONNECT"]) of
+        true -> ?LOG_INFO("MethodOverride: ~s (real method was ~s)",
[MethodOverride, Method1]), list_to_atom(MethodOverride);
+        _ -> 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,

--
1.7.1

Re: Patch: X-HTTP-METHOD-OVERRIDE header support

Posted by Robert Newson <ro...@gmail.com>.
jira ticket + attachment pls.

On Thu, Jun 10, 2010 at 8:59 PM, Brian Jenkins <br...@brianjenkins.org> wrote:
> Hello.
>
> Please excuse my Erlang -- I've learned just enough to hack in support
> for X-HTTP-METHOD-OVERRIDE headers.
>
> Also available in the trunk and 0.11.x branches here:
> http://github.com/bonkydog/couchdb
>
> Best,
> Brian
>
> ---
>  share/Makefile.am                        |    1 +
>  share/www/script/couch_tests.js          |    1 +
>  share/www/script/test/method_override.js |   36 ++++++++++++++++++++++++++++++
>  src/couchdb/couch_httpd.erl              |   12 ++++++++-
>  4 files changed, 48 insertions(+), 2 deletions(-)
>  create mode 100644 share/www/script/test/method_override.js
>
> diff --git a/share/Makefile.am b/share/Makefile.am
> index 1622130..cb9aae2 100644
> --- a/share/Makefile.am
> +++ b/share/Makefile.am
> @@ -136,6 +136,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 4225ce7..4f0d282 100644
> --- a/share/www/script/couch_tests.js
> +++ b/share/www/script/couch_tests.js
> @@ -58,6 +58,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 0000000..bc4d52f
> --- /dev/null
> +++ b/share/www/script/test/method_override.js
> @@ -0,0 +1,36 @@
> +// 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:{"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:{"Method-Override" : "DELETE"}});
> +  T(xhr.status == 200)
> +
> +  doc = db.open("fnord");
> +  T(doc == null);
> +
> +};
> \ No newline at end of file
> diff --git a/src/couchdb/couch_httpd.erl b/src/couchdb/couch_httpd.erl
> index a8f0bb5..558149f 100644
> --- a/src/couchdb/couch_httpd.erl
> +++ b/src/couchdb/couch_httpd.erl
> @@ -218,9 +218,17 @@ 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("Method-Override"),
> +    Method2 = case lists:member(MethodOverride, ["GET", "HEAD",
> "POST", "PUT", "DELETE", "TRACE", "CONNECT"]) of
> +        true -> ?LOG_INFO("MethodOverride: ~s (real method was ~s)",
> [MethodOverride, Method1]), list_to_atom(MethodOverride);
> +        _ -> 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,
>
> --
> 1.7.1
>