From dev-return-10385-apmail-couchdb-dev-archive=couchdb.apache.org@couchdb.apache.org Thu Jun 24 05:31:27 2010 Return-Path: Delivered-To: apmail-couchdb-dev-archive@www.apache.org Received: (qmail 90049 invoked from network); 24 Jun 2010 05:31:27 -0000 Received: from unknown (HELO mail.apache.org) (140.211.11.3) by 140.211.11.9 with SMTP; 24 Jun 2010 05:31:27 -0000 Received: (qmail 29367 invoked by uid 500); 24 Jun 2010 05:31:27 -0000 Delivered-To: apmail-couchdb-dev-archive@couchdb.apache.org Received: (qmail 28836 invoked by uid 500); 24 Jun 2010 05:31:24 -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 28828 invoked by uid 99); 24 Jun 2010 05:31:23 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 24 Jun 2010 05:31:23 +0000 X-ASF-Spam-Status: No, hits=-0.9 required=10.0 tests=AWL,FREEMAIL_FROM,SPF_PASS,T_TO_NO_BRKTS_FREEMAIL X-Spam-Check-By: apache.org Received-SPF: pass (athena.apache.org: domain of paul.joseph.davis@gmail.com designates 209.85.214.180 as permitted sender) Received: from [209.85.214.180] (HELO mail-iw0-f180.google.com) (209.85.214.180) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 24 Jun 2010 05:31:17 +0000 Received: by iwn2 with SMTP id 2so4554785iwn.11 for ; Wed, 23 Jun 2010 22:30:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:mime-version:received:in-reply-to :references:from:date:message-id:subject:to:content-type :content-transfer-encoding; bh=RUWcG8ToWFJTUWKEhRD8xLfGFQnQlA/DSpSvM1pXFIs=; b=Ppd1T6NJvJm0JocX2r7+Pbudg9KnYNo93OoC2p3ovRzeaVmacba4NYgdRU2tjvf44U fVixHWmTECHvh805HmtHFbqmLFSabMkF6g/nqG4M7t8Yjbib3yzZa+3nZwIfgVlMAOAd +rP8iTguFAAobNPVVrCjB+vhVzeoTCgXYSNbo= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :content-type:content-transfer-encoding; b=FQ3PAW8HnKWkM6vAH0tLkUjghailw6Vuw4BCm5vgQFQV4HrDUvI/pNFZIAq7NX02UV 6Uk8/nJAlaOXq31pTg6oU7qz9QI974aE7Cu8SY8QEd4AKg9mAjuQVWL+zXEbJs7htkJA MTKkwPfnc3nHxPpwddeFuXSrrOhMvAOQtZWv8= Received: by 10.231.126.79 with SMTP id b15mr9155419ibs.80.1277357456602; Wed, 23 Jun 2010 22:30:56 -0700 (PDT) MIME-Version: 1.0 Received: by 10.231.14.199 with HTTP; Wed, 23 Jun 2010 22:30:36 -0700 (PDT) In-Reply-To: <20100624052131.C3F5F23889E3@eris.apache.org> References: <20100624052131.C3F5F23889E3@eris.apache.org> From: Paul Davis Date: Thu, 24 Jun 2010 01:30:36 -0400 Message-ID: Subject: Re: svn commit: r957422 - in /couchdb/trunk: share/www/script/ share/www/script/test/ src/couchdb/ To: dev@couchdb.apache.org Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable On Thu, Jun 24, 2010 at 1:21 AM, wrote: > Author: jchris > Date: Thu Jun 24 05:21:30 2010 > New Revision: 957422 > > URL: http://svn.apache.org/viewvc?rev=3D957422&view=3Drev > Log: > use JSON content type in replicator, require it in the _bulk_docs and oth= er POST apis > > Modified: > =A0 =A0couchdb/trunk/share/www/script/couch.js > =A0 =A0couchdb/trunk/share/www/script/test/basics.js > =A0 =A0couchdb/trunk/share/www/script/test/batch_save.js > =A0 =A0couchdb/trunk/share/www/script/test/stats.js > =A0 =A0couchdb/trunk/src/couchdb/couch_httpd.erl > =A0 =A0couchdb/trunk/src/couchdb/couch_httpd_auth.erl > =A0 =A0couchdb/trunk/src/couchdb/couch_httpd_db.erl > =A0 =A0couchdb/trunk/src/couchdb/couch_httpd_show.erl > =A0 =A0couchdb/trunk/src/couchdb/couch_rep.erl > =A0 =A0couchdb/trunk/src/couchdb/couch_rep_writer.erl > =A0 =A0couchdb/trunk/src/couchdb/couch_util.erl > > Modified: couchdb/trunk/share/www/script/couch.js > URL: http://svn.apache.org/viewvc/couchdb/trunk/share/www/script/couch.js= ?rev=3D957422&r1=3D957421&r2=3D957422&view=3Ddiff > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D > --- couchdb/trunk/share/www/script/couch.js [utf-8] (original) > +++ couchdb/trunk/share/www/script/couch.js [utf-8] Thu Jun 24 05:21:30 2= 010 > @@ -398,6 +398,8 @@ CouchDB.newXhr =3D function() { > > =A0CouchDB.request =3D function(method, uri, options) { > =A0 options =3D options || {}; > + =A0options.headers =3D options.headers || {}; > + =A0options.headers["Content-Type"] =3D options.headers["Content-Type"] = || "application/json"; > =A0 var req =3D CouchDB.newXhr(); > =A0 if(uri.substr(0, "http://".length) !=3D "http://") { > =A0 =A0 uri =3D CouchDB.urlPrefix + uri > > Modified: couchdb/trunk/share/www/script/test/basics.js > URL: http://svn.apache.org/viewvc/couchdb/trunk/share/www/script/test/bas= ics.js?rev=3D957422&r1=3D957421&r2=3D957422&view=3Ddiff > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D > --- couchdb/trunk/share/www/script/test/basics.js (original) > +++ couchdb/trunk/share/www/script/test/basics.js Thu Jun 24 05:21:30 201= 0 > @@ -152,7 +152,8 @@ couchTests.basics =3D function(debug) { > > =A0 // test that the POST response has a Location header > =A0 var xhr =3D CouchDB.request("POST", "/test_suite_db", { > - =A0 =A0body: JSON.stringify({"foo":"bar"}) > + =A0 =A0body: JSON.stringify({"foo":"bar"}), > + =A0 =A0headers: {"Content-Type": "application/json"} > =A0 }); > =A0 var resp =3D JSON.parse(xhr.responseText); > =A0 T(resp.ok); > @@ -164,6 +165,7 @@ couchTests.basics =3D function(debug) { > > =A0 // test that that POST's with an _id aren't overriden with a UUID. > =A0 var xhr =3D CouchDB.request("POST", "/test_suite_db", { > + =A0 =A0headers: {"Content-Type": "application/json"}, > =A0 =A0 body: JSON.stringify({"_id": "oppossum", "yar": "matey"}) > =A0 }); > =A0 var resp =3D JSON.parse(xhr.responseText); > @@ -202,7 +204,10 @@ couchTests.basics =3D function(debug) { > =A0 =A0 result =3D JSON.parse(xhr.responseText); > =A0 =A0 T(result.error =3D=3D "doc_validation"); > > - =A0 =A0xhr =3D CouchDB.request("POST", "/test_suite_db/", {body: data})= ; > + =A0 =A0xhr =3D CouchDB.request("POST", "/test_suite_db/", { > + =A0 =A0 =A0headers: {"Content-Type": "application/json"}, > + =A0 =A0 =A0body: data > + =A0 =A0}); > =A0 =A0 T(xhr.status =3D=3D 500); > =A0 =A0 result =3D JSON.parse(xhr.responseText); > =A0 =A0 T(result.error =3D=3D "doc_validation"); > > Modified: couchdb/trunk/share/www/script/test/batch_save.js > URL: http://svn.apache.org/viewvc/couchdb/trunk/share/www/script/test/bat= ch_save.js?rev=3D957422&r1=3D957421&r2=3D957422&view=3Ddiff > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D > --- couchdb/trunk/share/www/script/test/batch_save.js (original) > +++ couchdb/trunk/share/www/script/test/batch_save.js Thu Jun 24 05:21:30= 2010 > @@ -36,7 +36,10 @@ couchTests.batch_save =3D function(debug) > > =A0 // repeat the tests for POST > =A0 for(i=3D0; i < 100; i++) { > - =A0 =A0var resp =3D db.request("POST", db.uri + "?batch=3Dok", {body: J= SON.stringify({a:1})}); > + =A0 =A0var resp =3D db.request("POST", db.uri + "?batch=3Dok", { > + =A0 =A0 =A0headers: {"Content-Type": "application/json"}, > + =A0 =A0 =A0body: JSON.stringify({a:1}) > + =A0 =A0}); > =A0 =A0 T(JSON.parse(resp.responseText).ok); > =A0 } > > > Modified: couchdb/trunk/share/www/script/test/stats.js > URL: http://svn.apache.org/viewvc/couchdb/trunk/share/www/script/test/sta= ts.js?rev=3D957422&r1=3D957421&r2=3D957422&view=3Ddiff > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D > --- couchdb/trunk/share/www/script/test/stats.js (original) > +++ couchdb/trunk/share/www/script/test/stats.js Thu Jun 24 05:21:30 2010 > @@ -160,7 +160,10 @@ couchTests.stats =3D function(debug) { > > =A0 runTest("couchdb", "database_writes", { > =A0 =A0 run: function(db) { > - =A0 =A0 =A0CouchDB.request("POST", "/test_suite_db", {body: '{"a": "1"}= '}) > + =A0 =A0 =A0CouchDB.request("POST", "/test_suite_db", { > + =A0 =A0 =A0 =A0headers: {"Content-Type": "application/json"}, > + =A0 =A0 =A0 =A0body: '{"a": "1"}' > + =A0 =A0 =A0}) > =A0 =A0 }, > =A0 =A0 test: function(before, after) { > =A0 =A0 =A0 TEquals(before+1, after, "POST'ing new docs increments doc wr= ites."); > > Modified: couchdb/trunk/src/couchdb/couch_httpd.erl > URL: http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/couch_httpd.e= rl?rev=3D957422&r1=3D957421&r2=3D957422&view=3Ddiff > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D > --- couchdb/trunk/src/couchdb/couch_httpd.erl (original) > +++ couchdb/trunk/src/couchdb/couch_httpd.erl Thu Jun 24 05:21:30 2010 > @@ -25,7 +25,7 @@ > =A0-export([start_json_response/2, start_json_response/3, end_json_respon= se/1]). > =A0-export([send_response/4,send_method_not_allowed/2,send_error/4, send_= redirect/2,send_chunked_error/2]). > =A0-export([send_json/2,send_json/3,send_json/4,last_chunk/1,parse_multip= art_request/3]). > --export([accepted_encodings/1,handle_request_int/5]). > +-export([accepted_encodings/1,handle_request_int/5,validate_referer/1,va= lidate_ctype/2]). > > =A0start_link() -> > =A0 =A0 % read config and register for configuration changes > @@ -321,6 +321,34 @@ vhost_global(VhostGlobals, MochiReq) -> > =A0 =A0 end, > =A0 =A0 [true] =3D=3D [true||V <- VhostGlobals, V =3D=3D Front]. > > +validate_referer(Req) -> > + =A0 =A0Host =3D host_for_request(Req), > + =A0 =A0Referer =3D header_value(Req, "Referer", fail), > + =A0 =A0case Referer of > + =A0 =A0fail -> > + =A0 =A0 =A0 =A0throw({bad_request, <<"Referer header required.">>}); > + =A0 =A0Referer -> > + =A0 =A0 =A0 =A0{_,RefererHost,_,_,_} =3D mochiweb_util:urlsplit(Referer= ), > + =A0 =A0 =A0 =A0if > + =A0 =A0 =A0 =A0 =A0 =A0RefererHost =3D:=3D Host -> ok; > + =A0 =A0 =A0 =A0 =A0 =A0true -> throw({bad_request, <<"Referer header mu= st match host.">>}) > + =A0 =A0 =A0 =A0end > + =A0 =A0end. > + > +validate_ctype(Req, Ctype) -> > + =A0 =A0case couch_httpd:header_value(Req, "Content-Type") of > + =A0 =A0undefined -> > + =A0 =A0 =A0 =A0throw({bad_ctype, "Content-Type must be "++Ctype}); > + =A0 =A0ReqCtype -> > + =A0 =A0 =A0 =A0% ?LOG_ERROR("Ctype ~p ReqCtype ~p",[Ctype,ReqCtype]), > + =A0 =A0 =A0 =A0case re:split(ReqCtype, ";", [{return, list}]) of > + =A0 =A0 =A0 =A0[Ctype] -> ok; > + =A0 =A0 =A0 =A0[Ctype, _Rest] -> ok; > + =A0 =A0 =A0 =A0_Else -> > + =A0 =A0 =A0 =A0 =A0 =A0throw({bad_ctype, "Content-Type must be "++Ctype= }) > + =A0 =A0 =A0 =A0end > + =A0 =A0end. > + > =A0% Utilities > > =A0partition(Path) -> > @@ -367,9 +395,9 @@ qs(#httpd{mochi_req=3DMochiReq}) -> > =A0path(#httpd{mochi_req=3DMochiReq}) -> > =A0 =A0 MochiReq:get(path). > > -absolute_uri(#httpd{mochi_req=3DMochiReq}, Path) -> > +host_for_request(#httpd{mochi_req=3DMochiReq}) -> > =A0 =A0 XHost =3D couch_config:get("httpd", "x_forwarded_host", "X-Forwar= ded-Host"), > - =A0 =A0Host =3D case MochiReq:get_header_value(XHost) of > + =A0 =A0case MochiReq:get_header_value(XHost) of > =A0 =A0 =A0 =A0 undefined -> > =A0 =A0 =A0 =A0 =A0 =A0 case MochiReq:get_header_value("Host") of > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 undefined -> > @@ -379,7 +407,10 @@ absolute_uri(#httpd{mochi_req=3DMochiReq}, > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 Value1 > =A0 =A0 =A0 =A0 =A0 =A0 end; > =A0 =A0 =A0 =A0 Value -> Value > - =A0 =A0end, > + =A0 =A0end. > + > +absolute_uri(#httpd{mochi_req=3DMochiReq}=3DReq, Path) -> > + =A0 =A0Host =3D host_for_request(Req), > =A0 =A0 XSsl =3D couch_config:get("httpd", "x_forwarded_ssl", "X-Forwarde= d-Ssl"), > =A0 =A0 Scheme =3D case MochiReq:get_header_value(XSsl) of > =A0 =A0 =A0 =A0 "on" -> "https"; > > Modified: couchdb/trunk/src/couchdb/couch_httpd_auth.erl > URL: http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/couch_httpd_a= uth.erl?rev=3D957422&r1=3D957421&r2=3D957422&view=3Ddiff > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D > --- couchdb/trunk/src/couchdb/couch_httpd_auth.erl (original) > +++ couchdb/trunk/src/couchdb/couch_httpd_auth.erl Thu Jun 24 05:21:30 20= 10 > @@ -251,6 +251,7 @@ ensure_cookie_auth_secret() -> > =A0handle_session_req(#httpd{method=3D'POST', mochi_req=3DMochiReq}=3DReq= ) -> > =A0 =A0 ReqBody =3D MochiReq:recv_body(), > =A0 =A0 Form =3D case MochiReq:get_primary_header_value("content-type") o= f > + =A0 =A0 =A0 =A0% content type should be json > =A0 =A0 =A0 =A0 "application/x-www-form-urlencoded" ++ _ -> > =A0 =A0 =A0 =A0 =A0 =A0 mochiweb_util:parse_qs(ReqBody); > =A0 =A0 =A0 =A0 _ -> > > Modified: couchdb/trunk/src/couchdb/couch_httpd_db.erl > URL: http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/couch_httpd_d= b.erl?rev=3D957422&r1=3D957421&r2=3D957422&view=3Ddiff > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D > --- couchdb/trunk/src/couchdb/couch_httpd_db.erl (original) > +++ couchdb/trunk/src/couchdb/couch_httpd_db.erl Thu Jun 24 05:21:30 2010 > @@ -112,6 +112,7 @@ handle_changes_req(#httpd{path_parts=3D[_, > =A0 =A0 send_method_not_allowed(Req, "GET,HEAD"). > > =A0handle_compact_req(#httpd{method=3D'POST',path_parts=3D[DbName,_,Id|_]= }=3DReq, _Db) -> > + =A0 =A0couch_httpd:validate_ctype(Req, "application/json"), > =A0 =A0 ok =3D couch_view_compactor:start_compact(DbName, Id), > =A0 =A0 send_json(Req, 202, {[{ok, true}]}); > > @@ -195,6 +196,7 @@ db_req(#httpd{method=3D'GET',path_parts=3D[_ > =A0 =A0 send_json(Req, {DbInfo}); > > =A0db_req(#httpd{method=3D'POST',path_parts=3D[DbName]}=3DReq, Db) -> > + =A0 =A0couch_httpd:validate_ctype(Req, "application/json"), > =A0 =A0 Doc =3D couch_doc:from_json_obj(couch_httpd:json_body(Req)), > =A0 =A0 Doc2 =3D case Doc#doc.id of > =A0 =A0 =A0 =A0 <<"">> -> > @@ -262,6 +264,7 @@ db_req(#httpd{path_parts=3D[_,<<"_ensure_f > > =A0db_req(#httpd{method=3D'POST',path_parts=3D[_,<<"_bulk_docs">>]}=3DReq= , Db) -> > =A0 =A0 couch_stats_collector:increment({httpd, bulk_requests}), > + =A0 =A0couch_httpd:validate_ctype(Req, "application/json"), > =A0 =A0 {JsonProps} =3D couch_httpd:json_body_obj(Req), > =A0 =A0 DocsArray =3D couch_util:get_value(<<"docs">>, JsonProps), > =A0 =A0 case couch_httpd:header_value(Req, "X-Couch-Full-Commit") of > @@ -323,6 +326,7 @@ db_req(#httpd{path_parts=3D[_,<<"_bulk_doc > =A0 =A0 send_method_not_allowed(Req, "POST"); > > =A0db_req(#httpd{method=3D'POST',path_parts=3D[_,<<"_purge">>]}=3DReq, Db= ) -> > + =A0 =A0couch_httpd:validate_ctype(Req, "application/json"), > =A0 =A0 {IdsRevs} =3D couch_httpd:json_body_obj(Req), > =A0 =A0 IdsRevs2 =3D [{Id, couch_doc:parse_revs(Revs)} || {Id, Revs} <- I= dsRevs], > > @@ -367,7 +371,6 @@ db_req(#httpd{method=3D'POST',path_parts=3D[ > =A0db_req(#httpd{path_parts=3D[_,<<"_missing_revs">>]}=3DReq, _Db) -> > =A0 =A0 send_method_not_allowed(Req, "POST"); > > - > =A0db_req(#httpd{method=3D'POST',path_parts=3D[_,<<"_revs_diff">>]}=3DReq= , Db) -> > =A0 =A0 {JsonDocIdRevs} =3D couch_httpd:json_body_obj(Req), > =A0 =A0 JsonDocIdRevs2 =3D > @@ -586,14 +589,11 @@ db_doc_req(#httpd{method=3D'GET'}=3DReq, Db, > =A0 =A0 =A0 =A0 end > =A0 =A0 end; > > + > =A0db_doc_req(#httpd{method=3D'POST'}=3DReq, Db, DocId) -> > + =A0 =A0couch_httpd:validate_referer(Req), > =A0 =A0 couch_doc:validate_docid(DocId), > - =A0 =A0case couch_httpd:header_value(Req, "Content-Type") of > - =A0 =A0"multipart/form-data" ++ =A0_Rest -> > - =A0 =A0 =A0 =A0ok; > - =A0 =A0_Else -> > - =A0 =A0 =A0 =A0throw({bad_ctype, <<"Invalid Content-Type header for for= m upload">>}) > - =A0 =A0end, > + =A0 =A0couch_httpd:validate_ctype(Req, "multipart/form-data"), > =A0 =A0 Form =3D couch_httpd:parse_form(Req), > =A0 =A0 case proplists:is_defined("_doc", Form) of > =A0 =A0 true -> > > Modified: couchdb/trunk/src/couchdb/couch_httpd_show.erl > URL: http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/couch_httpd_s= how.erl?rev=3D957422&r1=3D957421&r2=3D957422&view=3Ddiff > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D > --- couchdb/trunk/src/couchdb/couch_httpd_show.erl (original) > +++ couchdb/trunk/src/couchdb/couch_httpd_show.erl Thu Jun 24 05:21:30 20= 10 > @@ -145,7 +145,7 @@ send_doc_update_response(Req, Db, DDoc, > =A0 =A0 =A0 =A0 =A0 =A0 {200, JsonResp} > =A0 =A0 end, > > - =A0 =A0JsonResp2 =3D json_apply_field({<<"code">>, Code}, JsonResp1), > + =A0 =A0JsonResp2 =3D couch_util:json_apply_field({<<"code">>, Code}, Js= onResp1), > =A0 =A0 % todo set location field > =A0 =A0 couch_httpd_external:send_external_response(Req, JsonResp2). > > @@ -376,21 +376,6 @@ render_head_for_empty_list(StartListResp > =A0render_head_for_empty_list(StartListRespFun, Req, Etag, CurrentSeq, To= talRows) -> > =A0 =A0 StartListRespFun(Req, Etag, TotalRows, null, [], CurrentSeq). > > - > -% Maybe this is in the proplists API > -% todo move to couch_util > -json_apply_field(H, {L}) -> > - =A0 =A0json_apply_field(H, L, []). > -json_apply_field({Key, NewValue}, [{Key, _OldVal} | Headers], Acc) -> > - =A0 =A0% drop matching keys > - =A0 =A0json_apply_field({Key, NewValue}, Headers, Acc); > -json_apply_field({Key, NewValue}, [{OtherKey, OtherVal} | Headers], Acc)= -> > - =A0 =A0% something else is next, leave it alone. > - =A0 =A0json_apply_field({Key, NewValue}, Headers, [{OtherKey, OtherVal}= | Acc]); > -json_apply_field({Key, NewValue}, [], Acc) -> > - =A0 =A0% end of list, add ours > - =A0 =A0{[{Key, NewValue}|Acc]}. > - > =A0apply_etag({ExternalResponse}, CurrentEtag) -> > =A0 =A0 % Here we embark on the delicate task of replacing or creating th= e > =A0 =A0 % headers on the JsonResponse object. We need to control the Etag= and > @@ -404,8 +389,8 @@ apply_etag({ExternalResponse}, CurrentEt > =A0 =A0 JsonHeaders -> > =A0 =A0 =A0 =A0 {[case Field of > =A0 =A0 =A0 =A0 {<<"headers">>, JsonHeaders} -> % add our headers > - =A0 =A0 =A0 =A0 =A0 =A0JsonHeadersEtagged =3D json_apply_field({<<"Etag= ">>, CurrentEtag}, JsonHeaders), > - =A0 =A0 =A0 =A0 =A0 =A0JsonHeadersVaried =3D json_apply_field({<<"Vary"= >>, <<"Accept">>}, JsonHeadersEtagged), > + =A0 =A0 =A0 =A0 =A0 =A0JsonHeadersEtagged =3D couch_util:json_apply_fie= ld({<<"Etag">>, CurrentEtag}, JsonHeaders), > + =A0 =A0 =A0 =A0 =A0 =A0JsonHeadersVaried =3D couch_util:json_apply_fiel= d({<<"Vary">>, <<"Accept">>}, JsonHeadersEtagged), > =A0 =A0 =A0 =A0 =A0 =A0 {<<"headers">>, JsonHeadersVaried}; > =A0 =A0 =A0 =A0 _ -> % skip non-header fields > =A0 =A0 =A0 =A0 =A0 =A0 Field > > Modified: couchdb/trunk/src/couchdb/couch_rep.erl > URL: http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/couch_rep.erl= ?rev=3D957422&r1=3D957421&r2=3D957422&view=3Ddiff > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D > --- couchdb/trunk/src/couchdb/couch_rep.erl (original) > +++ couchdb/trunk/src/couchdb/couch_rep.erl Thu Jun 24 05:21:30 2010 > @@ -653,10 +653,11 @@ commit_to_both(Source, Target, RequiredS > =A0 =A0 end, > =A0 =A0 {SourceStartTime, TargetStartTime}. > > -ensure_full_commit(#http_db{} =3D Target) -> > +ensure_full_commit(#http_db{headers =3D Headers} =3D Target) -> > =A0 =A0 Req =3D Target#http_db{ > =A0 =A0 =A0 =A0 resource =3D "_ensure_full_commit", > - =A0 =A0 =A0 =A0method =3D post > + =A0 =A0 =A0 =A0method =3D post, > + =A0 =A0 =A0 =A0headers =3D [{"content-type", "application/json"} | Head= ers] > =A0 =A0 }, > =A0 =A0 {ResultProps} =3D couch_rep_httpc:request(Req), > =A0 =A0 true =3D couch_util:get_value(<<"ok">>, ResultProps), > @@ -677,11 +678,12 @@ ensure_full_commit(Target) -> > =A0 =A0 =A0 =A0 InstanceStartTime > =A0 =A0 end. > > -ensure_full_commit(#http_db{} =3D Source, RequiredSeq) -> > +ensure_full_commit(#http_db{headers =3D Headers} =3D Source, RequiredSeq= ) -> > =A0 =A0 Req =3D Source#http_db{ > =A0 =A0 =A0 =A0 resource =3D "_ensure_full_commit", > =A0 =A0 =A0 =A0 method =3D post, > - =A0 =A0 =A0 =A0qs =3D [{seq, RequiredSeq}] > + =A0 =A0 =A0 =A0qs =3D [{seq, RequiredSeq}], > + =A0 =A0 =A0 =A0headers =3D [{"content-type", "application/json"} | Head= ers] > =A0 =A0 }, > =A0 =A0 {ResultProps} =3D couch_rep_httpc:request(Req), > =A0 =A0 case couch_util:get_value(<<"ok">>, ResultProps) of > > Modified: couchdb/trunk/src/couchdb/couch_rep_writer.erl > URL: http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/couch_rep_wri= ter.erl?rev=3D957422&r1=3D957421&r2=3D957422&view=3Ddiff > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D > --- couchdb/trunk/src/couchdb/couch_rep_writer.erl (original) > +++ couchdb/trunk/src/couchdb/couch_rep_writer.erl Thu Jun 24 05:21:30 20= 10 > @@ -76,8 +76,9 @@ write_bulk_docs(#http_db{headers =3D Heade > =A0 =A0 =A0 =A0 resource =3D "_bulk_docs", > =A0 =A0 =A0 =A0 method =3D post, > =A0 =A0 =A0 =A0 body =3D {[{new_edits, false}, {docs, JsonDocs}]}, > - =A0 =A0 =A0 =A0headers =3D [{"x-couch-full-commit", "false"} | Headers] > + =A0 =A0 =A0 =A0headers =3D couch_util:proplist_apply_field({"Content-Ty= pe", "application/json"}, [{"X-Couch-Full-Commit", "false"} | Headers]) > =A0 =A0 }, > + =A0 =A0?LOG_ERROR("headers ~p",[Request#http_db.headers]), > =A0 =A0 ErrorsJson =3D case couch_rep_httpc:request(Request) of > =A0 =A0 {FailProps} -> > =A0 =A0 =A0 =A0 exit({target_error, couch_util:get_value(<<"error">>, Fai= lProps)}); > > Modified: couchdb/trunk/src/couchdb/couch_util.erl > URL: http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/couch_util.er= l?rev=3D957422&r1=3D957421&r2=3D957422&view=3Ddiff > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D > --- couchdb/trunk/src/couchdb/couch_util.erl (original) > +++ couchdb/trunk/src/couchdb/couch_util.erl Thu Jun 24 05:21:30 2010 > @@ -19,6 +19,7 @@ > =A0-export([encodeBase64Url/1, decodeBase64Url/1]). > =A0-export([to_hex/1, parse_term/1, dict_find/3]). > =A0-export([file_read_size/1, get_nested_json_value/2, json_user_ctx/1]). > +-export([proplist_apply_field/2, json_apply_field/2]). > =A0-export([to_binary/1, to_integer/1, to_list/1, url_encode/1]). > =A0-export([json_encode/1, json_decode/1]). > =A0-export([verify/2,simple_call/2,shutdown_sync/1]). > @@ -143,6 +144,19 @@ get_nested_json_value(Value, []) -> > =A0get_nested_json_value(_NotJSONObj, _) -> > =A0 =A0 throw({not_found, json_mismatch}). > > +proplist_apply_field(H, L) -> > + =A0 =A0{R} =3D json_apply_field(H, {L}), > + =A0 =A0R. > + > +json_apply_field(H, {L}) -> > + =A0 =A0json_apply_field(H, L, []). > +json_apply_field({Key, NewValue}, [{Key, _OldVal} | Headers], Acc) -> > + =A0 =A0json_apply_field({Key, NewValue}, Headers, Acc); > +json_apply_field({Key, NewValue}, [{OtherKey, OtherVal} | Headers], Acc)= -> > + =A0 =A0json_apply_field({Key, NewValue}, Headers, [{OtherKey, OtherVal}= | Acc]); > +json_apply_field({Key, NewValue}, [], Acc) -> > + =A0 =A0{[{Key, NewValue}|Acc]}. > + > =A0json_user_ctx(#db{name=3DDbName, user_ctx=3DCtx}) -> > =A0 =A0 {[{<<"db">>, DbName}, > =A0 =A0 =A0 =A0 =A0 =A0 {<<"name">>,Ctx#user_ctx.name}, > > > Why the change to requiring the JSON header? I thought we'd always left that lax for the clients that are stuck in 1980. Also, are we ok in requiring exactly application/json and not the non-RFC-compliant things like text/json et al? Paul