Return-Path: Delivered-To: apmail-couchdb-dev-archive@www.apache.org Received: (qmail 76421 invoked from network); 10 Jun 2010 15:03:07 -0000 Received: from unknown (HELO mail.apache.org) (140.211.11.3) by 140.211.11.9 with SMTP; 10 Jun 2010 15:03:07 -0000 Received: (qmail 7636 invoked by uid 500); 10 Jun 2010 15:03:06 -0000 Delivered-To: apmail-couchdb-dev-archive@couchdb.apache.org Received: (qmail 7575 invoked by uid 500); 10 Jun 2010 15:03:05 -0000 Mailing-List: contact dev-help@couchdb.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@couchdb.apache.org Delivered-To: mailing list dev@couchdb.apache.org Received: (qmail 7520 invoked by uid 99); 10 Jun 2010 15:03:05 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 10 Jun 2010 15:03:05 +0000 X-ASF-Spam-Status: No, hits=0.0 required=10.0 tests=FREEMAIL_FROM,RCVD_IN_DNSWL_NONE,SPF_PASS,T_TO_NO_BRKTS_FREEMAIL X-Spam-Check-By: apache.org Received-SPF: pass (nike.apache.org: domain of bonkydog@gmail.com designates 209.85.212.52 as permitted sender) Received: from [209.85.212.52] (HELO mail-vw0-f52.google.com) (209.85.212.52) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 10 Jun 2010 15:03:00 +0000 Received: by vws5 with SMTP id 5so44565vws.11 for ; Thu, 10 Jun 2010 08:02:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:mime-version:sender:received :in-reply-to:references:from:date:x-google-sender-auth:message-id :subject:to:content-type; bh=N5rqL6fwqQWbTf3ity7AJqB0mW0hL99Zv4q/zMhY2io=; b=GNQiXJrQXZIMJtQlocRdZ3PORCPuSzfcaxqM17BVtbMO4J5Vy0Bb7RnV6UOF0fPxp5 sK2Q0oL/ZRuS8xWPXjYNF0v2RnaSZkb5hIIj8l96X70hrRI+dqf5dBdYSh4PnMJ+OVEl aUpcdQbG7XT5YAZb1q0v0AWXbuIsK3xEKKdC8= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:sender:in-reply-to:references:from:date :x-google-sender-auth:message-id:subject:to:content-type; b=vL3cXjOv2TaxuhGdTdCyR7IbZiXtp60I+sY1Psf0208FlfU7OAWzbazSnjsmCTdld5 zLcCVGhB1/fgnGeM4kHdwBOHdFhKe4S5Mfi1YWoBAs3+ASog1ZCdxqnBwshjX2aZcCYS kef4kz0lP/Vo+xQRbUjkREnOj8/qQd099e10U= Received: by 10.224.53.91 with SMTP id l27mr237533qag.352.1276182148746; Thu, 10 Jun 2010 08:02:28 -0700 (PDT) MIME-Version: 1.0 Sender: bonkydog@gmail.com Received: by 10.229.33.75 with HTTP; Thu, 10 Jun 2010 08:02:10 -0700 (PDT) In-Reply-To: References: From: Brian Jenkins Date: Thu, 10 Jun 2010 08:02:10 -0700 X-Google-Sender-Auth: zw7kebGdoUIXyjtOfoBNpLSDvbw Message-ID: Subject: Re: X-HTTP-METHOD-OVERRIDE support To: dev@couchdb.apache.org Content-Type: text/plain; charset=ISO-8859-1 X-Virus-Checked: Checked by ClamAV on apache.org On Wed, Jun 9, 2010 at 11:19 PM, Brian Jenkins wrote: > > I've learned *just* enough Erlang to hack in support for X-HTTP-METHOD-OVERRIDE headers. > > It's in the trunk and 0.11.x branches here: > > http://github.com/bonkydog/couchdb > PS: Here's a patch --- 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