You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by da...@apache.org on 2009/03/13 22:12:45 UTC
svn commit: r753413 [1/2] - in /couchdb/branches/rep_security: ./ bin/
etc/couchdb/ etc/default/ share/server/ share/www/ share/www/script/
share/www/script/test/ share/www/style/ src/couchdb/ src/ibrowse/
Author: damien
Date: Fri Mar 13 21:12:44 2009
New Revision: 753413
URL: http://svn.apache.org/viewvc?rev=753413&view=rev
Log:
Merge from trunk. Test failures in list_views need to be fixed.
Added:
couchdb/branches/rep_security/share/www/script/test/attachment_names.js
- copied, changed from r753015, couchdb/trunk/share/www/script/test/attachment_names.js
couchdb/branches/rep_security/src/couchdb/couch_rep_sup.erl
- copied unchanged from r753015, couchdb/trunk/src/couchdb/couch_rep_sup.erl
Modified:
couchdb/branches/rep_security/ (props changed)
couchdb/branches/rep_security/CHANGES
couchdb/branches/rep_security/bin/couchdb.tpl.in
couchdb/branches/rep_security/etc/couchdb/default.ini.tpl.in
couchdb/branches/rep_security/etc/default/couchdb (props changed)
couchdb/branches/rep_security/share/server/main.js
couchdb/branches/rep_security/share/www/database.html
couchdb/branches/rep_security/share/www/index.html
couchdb/branches/rep_security/share/www/script/couch.js
couchdb/branches/rep_security/share/www/script/couch_tests.js
couchdb/branches/rep_security/share/www/script/futon.browse.js
couchdb/branches/rep_security/share/www/script/jquery.couch.js
couchdb/branches/rep_security/share/www/script/test/ (props changed)
couchdb/branches/rep_security/share/www/script/test/etags_views.js
couchdb/branches/rep_security/share/www/script/test/list_views.js
couchdb/branches/rep_security/share/www/script/test/replication.js
couchdb/branches/rep_security/share/www/script/test/show_documents.js
couchdb/branches/rep_security/share/www/style/layout.css
couchdb/branches/rep_security/src/couchdb/Makefile.am
couchdb/branches/rep_security/src/couchdb/couch_db.hrl
couchdb/branches/rep_security/src/couchdb/couch_doc.erl
couchdb/branches/rep_security/src/couchdb/couch_external_server.erl
couchdb/branches/rep_security/src/couchdb/couch_httpd.erl
couchdb/branches/rep_security/src/couchdb/couch_httpd_db.erl
couchdb/branches/rep_security/src/couchdb/couch_httpd_external.erl
couchdb/branches/rep_security/src/couchdb/couch_httpd_misc_handlers.erl
couchdb/branches/rep_security/src/couchdb/couch_httpd_show.erl
couchdb/branches/rep_security/src/couchdb/couch_httpd_view.erl
couchdb/branches/rep_security/src/couchdb/couch_os_process.erl
couchdb/branches/rep_security/src/couchdb/couch_rep.erl
couchdb/branches/rep_security/src/couchdb/couch_server_sup.erl
couchdb/branches/rep_security/src/couchdb/couch_util.erl
couchdb/branches/rep_security/src/ibrowse/ibrowse.erl
couchdb/branches/rep_security/src/ibrowse/ibrowse_http_client.erl
couchdb/branches/rep_security/src/ibrowse/ibrowse_test.erl
Propchange: couchdb/branches/rep_security/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Fri Mar 13 21:12:44 2009
@@ -1,2 +1,3 @@
+/couchdb/branches/design_resources:751716-751803
/couchdb/branches/form:729440-730015
-/couchdb/trunk:741843-750305
+/couchdb/trunk:741843-753015
Modified: couchdb/branches/rep_security/CHANGES
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/CHANGES?rev=753413&r1=753412&r2=753413&view=diff
==============================================================================
--- couchdb/branches/rep_security/CHANGES (original)
+++ couchdb/branches/rep_security/CHANGES Fri Mar 13 21:12:44 2009
@@ -17,6 +17,13 @@
* Added pagination to the database listing page.
* Implemented attachment uploading from the document page.
+Design Document Resource Paths:
+
+ * Added httpd_design_handlers config section.
+ * Moved _view to httpd_design_handlers.
+ * Added ability to render documents as non-JSON content-types with _show and
+ _list functions, which are also httpd_design_handlers.
+
Version 0.8.1-incubating
------------------------
Modified: couchdb/branches/rep_security/bin/couchdb.tpl.in
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/bin/couchdb.tpl.in?rev=753413&r1=753412&r2=753413&view=diff
==============================================================================
--- couchdb/branches/rep_security/bin/couchdb.tpl.in (original)
+++ couchdb/branches/rep_security/bin/couchdb.tpl.in Fri Mar 13 21:12:44 2009
@@ -207,7 +207,7 @@
export HEART_COMMAND
export HEART_BEAT_TIMEOUT
`eval $command -pidfile $PID_FILE -heart \
- > $STDOUT_FILE 2> $STDERR_FILE` || true
+ >> $STDOUT_FILE 2>> $STDERR_FILE` || true
PID=`_get_pid`
if test -n "$PID"; then
if kill -0 $PID 2> /dev/null; then
Modified: couchdb/branches/rep_security/etc/couchdb/default.ini.tpl.in
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/etc/couchdb/default.ini.tpl.in?rev=753413&r1=753412&r2=753413&view=diff
==============================================================================
--- couchdb/branches/rep_security/etc/couchdb/default.ini.tpl.in (original)
+++ couchdb/branches/rep_security/etc/couchdb/default.ini.tpl.in Fri Mar 13 21:12:44 2009
@@ -8,7 +8,7 @@
util_driver_dir = %couchprivlibdir%
max_document_size = 4294967296 ; 4 GB
max_attachment_chunk_size = 4294967296 ; 4GB
-view_timeout = 5000 ; 5 seconds
+os_process_timeout = 5000 ; 5 seconds. for view and external servers.
max_dbs_open = 100
[httpd]
@@ -52,13 +52,16 @@
_stats = {couch_httpd_stats_handlers, handle_stats_req}
[httpd_db_handlers]
-_view = {couch_httpd_view, handle_view_req}
+_design = {couch_httpd_db, handle_design_req}
_temp_view = {couch_httpd_view, handle_temp_view_req}
-_show = {couch_httpd_show, handle_doc_show_req}
-_list = {couch_httpd_show, handle_view_list_req}
; The external module takes an optional argument allowing you to narrow it to a
; single script. Otherwise the script name is inferred from the first path section
; after _external's own path.
; _mypath = {couch_httpd_external, handle_external_req, <<"mykey">>}
; _external = {couch_httpd_external, handle_external_req}
+
+[httpd_design_handlers]
+_view = {couch_httpd_view, handle_view_req}
+_show = {couch_httpd_show, handle_doc_show_req}
+_list = {couch_httpd_show, handle_view_list_req}
Propchange: couchdb/branches/rep_security/etc/default/couchdb
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Fri Mar 13 21:12:44 2009
@@ -1,3 +1,4 @@
+/couchdb/branches/design_resources/etc/default/couchdb:751716-751803
/couchdb/branches/form/etc/default/couchdb:729440-730015
-/couchdb/trunk/etc/default/couchdb:741843-750305
+/couchdb/trunk/etc/default/couchdb:741843-753015
/incubator/couchdb/trunk/etc/default/couchdb:642419-694440
Modified: couchdb/branches/rep_security/share/server/main.js
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/share/server/main.js?rev=753413&r1=753412&r2=753413&view=diff
==============================================================================
--- couchdb/branches/rep_security/share/server/main.js [utf-8] (original)
+++ couchdb/branches/rep_security/share/server/main.js [utf-8] Fri Mar 13 21:12:44 2009
@@ -364,10 +364,9 @@
var row_info = row_line[listFun];
runRenderFunction(listFun, [null, row, req, row_info]);
if (row_info.first_key == null) {
- row_info.first_key = row.key;
- } else {
- row_info.prev_key = row.key;
+ row_info.first_key = row.key;
}
+ row_info.prev_key = row.key;
row_info.row_number++;
row_line[listFun] = row_info;
break;
Modified: couchdb/branches/rep_security/share/www/database.html
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/share/www/database.html?rev=753413&r1=753412&r2=753413&view=diff
==============================================================================
--- couchdb/branches/rep_security/share/www/database.html [utf-8] (original)
+++ couchdb/branches/rep_security/share/www/database.html [utf-8] Fri Mar 13 21:12:44 2009
@@ -39,7 +39,12 @@
$(function() {
if (page.redirecting) return;
$("h1 strong").text(page.db.name);
- var viewPath = (page.viewName || "_all_docs").replace(/^_design\//, "_view/");
+ var viewPath = page.viewName || "_all_docs";
+ if (/^_design\//.test(viewPath)) {
+ var parts = viewPath.split("/");
+ parts.splice(2, 0, "_view");
+ viewPath = parts.join("/");
+ }
if (viewPath != "_temp_view" && viewPath != "_design_docs") {
$("h1 a.raw").attr("href", "/" + encodeURIComponent(page.db.name) +
"/" + viewPath);
Modified: couchdb/branches/rep_security/share/www/index.html
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/share/www/index.html?rev=753413&r1=753412&r2=753413&view=diff
==============================================================================
--- couchdb/branches/rep_security/share/www/index.html [utf-8] (original)
+++ couchdb/branches/rep_security/share/www/index.html [utf-8] Fri Mar 13 21:12:44 2009
@@ -63,7 +63,6 @@
<tr>
<th>Name</th>
<th class="size">Size</th>
- <th class="apps">Applications</th>
<th class="count">Number of Documents</th>
<th class="seq">Update Seq</th>
</tr>
Modified: couchdb/branches/rep_security/share/www/script/couch.js
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/share/www/script/couch.js?rev=753413&r1=753412&r2=753413&view=diff
==============================================================================
--- couchdb/branches/rep_security/share/www/script/couch.js [utf-8] (original)
+++ couchdb/branches/rep_security/share/www/script/couch.js [utf-8] Fri Mar 13 21:12:44 2009
@@ -153,12 +153,13 @@
}
this.view = function(viewname, options, keys) {
+ var viewParts = viewname.split('/');
+ var viewPath = this.uri + "_design/" + viewParts[0] + "/_view/"
+ + viewParts[1] + encodeOptions(options);
if(!keys) {
- this.last_req = this.request("GET", this.uri + "_view/" +
- viewname + encodeOptions(options));
+ this.last_req = this.request("GET", viewPath);
} else {
- this.last_req = this.request("POST", this.uri + "_view/" +
- viewname + encodeOptions(options), {
+ this.last_req = this.request("POST", viewPath, {
headers: {"Content-Type": "application/json"},
body: JSON.stringify({keys:keys})
});
@@ -310,10 +311,9 @@
CouchDB.replicate = function(source, target, rep_options) {
rep_options = rep_options || {};
var headers = rep_options.headers || {};
- var options = rep_options.options || {};
CouchDB.last_req = CouchDB.request("POST", "/_replicate", {
headers: headers,
- body: JSON.stringify({source: source, target: target, options: options})
+ body: JSON.stringify({source: source, target: target})
});
CouchDB.maybeThrowError(CouchDB.last_req);
return JSON.parse(CouchDB.last_req.responseText);
Modified: couchdb/branches/rep_security/share/www/script/couch_tests.js
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/share/www/script/couch_tests.js?rev=753413&r1=753412&r2=753413&view=diff
==============================================================================
--- couchdb/branches/rep_security/share/www/script/couch_tests.js [utf-8] (original)
+++ couchdb/branches/rep_security/share/www/script/couch_tests.js [utf-8] Fri Mar 13 21:12:44 2009
@@ -41,6 +41,7 @@
loadTest("large_docs.js");
loadTest("utf8.js");
loadTest("attachments.js");
+loadTest("attachment_names.js");
loadTest("attachment_paths.js");
loadTest("attachment_views.js");
loadTest("design_paths.js");
Modified: couchdb/branches/rep_security/share/www/script/futon.browse.js
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/share/www/script/futon.browse.js?rev=753413&r1=753412&r2=753413&view=diff
==============================================================================
--- couchdb/branches/rep_security/share/www/script/futon.browse.js [utf-8] (original)
+++ couchdb/branches/rep_security/share/www/script/futon.browse.js [utf-8] Fri Mar 13 21:12:44 2009
@@ -52,16 +52,9 @@
$("#databases tbody.content").append("<tr>" +
"<th><a href='database.html?" + encodeURIComponent(dbName) + "'>" +
dbName + "</a></th>" +
- "<td class='size'></td><td class='apps'></td><td class='count'></td>" +
+ "<td class='size'></td><td class='count'></td>" +
"<td class='seq'></td></tr>");
- var db = $.couch.db(dbName);
- db.allApps({
- eachApp : function(name, path) {
- $("#databases tbody.content tr:eq(" + idx + ")")
- .find("td.apps").append('<a href="'+path+'">'+name+'</a> ');
- }
- });
- db.info({
+ $.couch.db(dbName).info({
success: function(info) {
$("#databases tbody.content tr:eq(" + idx + ")")
.find("td.size").text($.futon.formatSize(info.disk_size)).end()
Modified: couchdb/branches/rep_security/share/www/script/jquery.couch.js
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/share/www/script/jquery.couch.js?rev=753413&r1=753412&r2=753413&view=diff
==============================================================================
--- couchdb/branches/rep_security/share/www/script/jquery.couch.js [utf-8] (original)
+++ couchdb/branches/rep_security/share/www/script/jquery.couch.js [utf-8] Fri Mar 13 21:12:44 2009
@@ -191,9 +191,9 @@
appName = appName.join('/');
index = ddoc.couchapp && ddoc.couchapp.index;
if (index) {
- appPath = ['', name, index[0], appName, index[1]].join('/');
+ appPath = ['', name, ddoc._id, index].join('/');
} else if (ddoc._attachments && ddoc._attachments["index.html"]) {
- appPath = ['', name, '_design', appName, "index.html"].join('/');
+ appPath = ['', name, ddoc._id, "index.html"].join('/');
}
if (appPath) options.eachApp(appName, appPath, ddoc);
}
@@ -298,8 +298,9 @@
},
view: function(name, options) {
options = options || {};
+ name = name.split('/');
$.ajax({
- type: "GET", url: this.uri + "_view/" + name + encodeOptions(options),
+ type: "GET", url: this.uri + "_design/" + name[0] + "/_view/" + name[1] + encodeOptions(options),
dataType: "json",
complete: function(req) {
var resp = $.httpData(req, "json");
Propchange: couchdb/branches/rep_security/share/www/script/test/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Fri Mar 13 21:12:44 2009
@@ -0,0 +1 @@
+/couchdb/trunk/share/www/script/test:750306-753015
Copied: couchdb/branches/rep_security/share/www/script/test/attachment_names.js (from r753015, couchdb/trunk/share/www/script/test/attachment_names.js)
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/share/www/script/test/attachment_names.js?p2=couchdb/branches/rep_security/share/www/script/test/attachment_names.js&p1=couchdb/trunk/share/www/script/test/attachment_names.js&r1=753015&r2=753413&rev=753413&view=diff
==============================================================================
--- couchdb/trunk/share/www/script/test/attachment_names.js (original)
+++ couchdb/branches/rep_security/share/www/script/test/attachment_names.js Fri Mar 13 21:12:44 2009
@@ -10,7 +10,7 @@
// License for the specific language governing permissions and limitations under
// the License.
-couchTests.attatchment_names = function(debug) {
+couchTests.attachment_names = function(debug) {
var db = new CouchDB("test_suite_db");
db.deleteDb();
db.createDb();
Modified: couchdb/branches/rep_security/share/www/script/test/etags_views.js
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/share/www/script/test/etags_views.js?rev=753413&r1=753412&r2=753413&view=diff
==============================================================================
--- couchdb/branches/rep_security/share/www/script/test/etags_views.js (original)
+++ couchdb/branches/rep_security/share/www/script/test/etags_views.js Fri Mar 13 21:12:44 2009
@@ -45,20 +45,20 @@
db.bulkSave(docs);
// verify get w/Etag on map view
- xhr = CouchDB.request("GET", "/test_suite_db/_view/etags/basicView");
+ xhr = CouchDB.request("GET", "/test_suite_db/_design/etags/_view/basicView");
T(xhr.status == 200);
var etag = xhr.getResponseHeader("etag");
- xhr = CouchDB.request("GET", "/test_suite_db/_view/etags/basicView", {
+ xhr = CouchDB.request("GET", "/test_suite_db/_design/etags/_view/basicView", {
headers: {"if-none-match": etag}
});
T(xhr.status == 304);
// TODO GET with keys (when that is available)
// reduce view
- xhr = CouchDB.request("GET", "/test_suite_db/_view/etags/withReduce");
+ xhr = CouchDB.request("GET", "/test_suite_db/_design/etags/_view/withReduce");
T(xhr.status == 200);
var etag = xhr.getResponseHeader("etag");
- xhr = CouchDB.request("GET", "/test_suite_db/_view/etags/withReduce", {
+ xhr = CouchDB.request("GET", "/test_suite_db/_design/etags/_view/withReduce", {
headers: {"if-none-match": etag}
});
T(xhr.status == 304);
Modified: couchdb/branches/rep_security/share/www/script/test/list_views.js
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/share/www/script/test/list_views.js?rev=753413&r1=753412&r2=753413&view=diff
==============================================================================
--- couchdb/branches/rep_security/share/www/script/test/list_views.js (original)
+++ couchdb/branches/rep_security/share/www/script/test/list_views.js Fri Mar 13 21:12:44 2009
@@ -143,8 +143,8 @@
T(view.total_rows == 10);
// standard get
- var xhr = CouchDB.request("GET", "/test_suite_db/_list/lists/simpleForm/basicView");
- T(xhr.status == 200);
+ var xhr = CouchDB.request("GET", "/test_suite_db/_design/lists/_list/simpleForm/basicView");
+ T(xhr.status == 200, "standard get should be 200");
T(/Total Rows/.test(xhr.responseText));
T(/Key: 1/.test(xhr.responseText));
T(/LineNo: 0/.test(xhr.responseText));
@@ -158,14 +158,14 @@
// test that etags are available
var etag = xhr.getResponseHeader("etag");
- xhr = CouchDB.request("GET", "/test_suite_db/_list/lists/simpleForm/basicView", {
+ xhr = CouchDB.request("GET", "/test_suite_db/_design/lists/_list/simpleForm/basicView", {
headers: {"if-none-match": etag}
});
T(xhr.status == 304);
// get with query params
- var xhr = CouchDB.request("GET", "/test_suite_db/_list/lists/simpleForm/basicView?startkey=3");
- T(xhr.status == 200);
+ var xhr = CouchDB.request("GET", "/test_suite_db/_design/lists/_list/simpleForm/basicView?startkey=3");
+ T(xhr.status == 200, "with query params");
T(/Total Rows/.test(xhr.responseText));
T(!(/Key: 1/.test(xhr.responseText)));
T(/FirstKey: 3/.test(xhr.responseText));
@@ -173,33 +173,33 @@
// with 0 rows
- var xhr = CouchDB.request("GET", "/test_suite_db/_list/lists/simpleForm/basicView?startkey=30");
- T(xhr.status == 200);
+ var xhr = CouchDB.request("GET", "/test_suite_db/_design/lists/_list/simpleForm/basicView?startkey=30");
+ T(xhr.status == 200, "0 rows");
T(/Total Rows/.test(xhr.responseText));
T(/Offset: null/.test(xhr.responseText));
// reduce with 0 rows
- var xhr = CouchDB.request("GET", "/test_suite_db/_list/lists/simpleForm/withReduce?startkey=30");
- T(xhr.status == 200);
+ var xhr = CouchDB.request("GET", "/test_suite_db/_design/lists/_list/simpleForm/withReduce?startkey=30");
+ T(xhr.status == 200, "reduce 0 rows");
T(/Total Rows/.test(xhr.responseText));
T(/Offset: undefined/.test(xhr.responseText));
// when there is a reduce present, but not used
- var xhr = CouchDB.request("GET", "/test_suite_db/_list/lists/simpleForm/withReduce?reduce=false");
- T(xhr.status == 200);
+ var xhr = CouchDB.request("GET", "/test_suite_db/_design/lists/_list/simpleForm/withReduce?reduce=false");
+ T(xhr.status == 200, "reduce false");
T(/Total Rows/.test(xhr.responseText));
T(/Key: 1/.test(xhr.responseText));
// when there is a reduce present, and used
- xhr = CouchDB.request("GET", "/test_suite_db/_list/lists/simpleForm/withReduce?group=true");
- T(xhr.status == 200);
+ xhr = CouchDB.request("GET", "/test_suite_db/_design/lists/_list/simpleForm/withReduce?group=true");
+ T(xhr.status == 200, "group reduce");
T(/Key: 1/.test(xhr.responseText));
// there should be etags on reduce as well
var etag = xhr.getResponseHeader("etag");
T(etag, "Etags should be served with reduce lists");
- xhr = CouchDB.request("GET", "/test_suite_db/_list/lists/simpleForm/withReduce?group=true", {
+ xhr = CouchDB.request("GET", "/test_suite_db/_design/lists/_list/simpleForm/withReduce?group=true", {
headers: {"if-none-match": etag}
});
T(xhr.status == 304);
@@ -208,13 +208,13 @@
var docs = makeDocs(11, 12);
db.bulkSave(docs);
- xhr = CouchDB.request("GET", "/test_suite_db/_list/lists/simpleForm/withReduce?group=true", {
+ xhr = CouchDB.request("GET", "/test_suite_db/_design/lists/_list/simpleForm/withReduce?group=true", {
headers: {"if-none-match": etag}
});
- T(xhr.status == 200);
+ T(xhr.status == 200, "reduce etag");
// with accept headers for HTML
- xhr = CouchDB.request("GET", "/test_suite_db/_list/lists/acceptSwitch/basicView", {
+ xhr = CouchDB.request("GET", "/test_suite_db/_design/lists/_list/acceptSwitch/basicView", {
headers: {
"Accept": 'text/html'
}
@@ -224,7 +224,7 @@
T(xhr.responseText.match(/Value/));
// now with xml
- xhr = CouchDB.request("GET", "/test_suite_db/_list/lists/acceptSwitch/basicView", {
+ xhr = CouchDB.request("GET", "/test_suite_db/_design/lists/_list/acceptSwitch/basicView", {
headers: {
"Accept": 'application/xml'
}
@@ -234,25 +234,42 @@
T(xhr.responseText.match(/entry/));
// now with extra qs params
- var xhr = CouchDB.request("GET", "/test_suite_db/_list/lists/qsParams/basicView?foo=blam");
+ var xhr = CouchDB.request("GET", "/test_suite_db/_design/lists/_list/qsParams/basicView?foo=blam");
T(xhr.responseText.match(/blam/));
// aborting iteration
- var xhr = CouchDB.request("GET", "/test_suite_db/_list/lists/stopIter/basicView");
+ var xhr = CouchDB.request("GET", "/test_suite_db/_design/lists/_list/stopIter/basicView");
T(xhr.responseText.match(/^head 0 1 2 tail$/));
- xhr = CouchDB.request("GET", "/test_suite_db/_list/lists/stopIter2/basicView");
+ xhr = CouchDB.request("GET", "/test_suite_db/_design/lists/_list/stopIter2/basicView");
T(xhr.responseText.match(/^head 0 1 2 tail$/));
// aborting iteration with reduce
- var xhr = CouchDB.request("GET", "/test_suite_db/_list/lists/stopIter/withReduce?group=true");
+ var xhr = CouchDB.request("GET", "/test_suite_db/_design/lists/_list/stopIter/withReduce?group=true");
T(xhr.responseText.match(/^head 0 1 2 tail$/));
- xhr = CouchDB.request("GET", "/test_suite_db/_list/lists/stopIter2/withReduce?group=true");
+ xhr = CouchDB.request("GET", "/test_suite_db/_design/lists/_list/stopIter2/withReduce?group=true");
T(xhr.responseText.match(/^head 0 1 2 tail$/));
// empty list
- var xhr = CouchDB.request("GET", "/test_suite_db/_list/lists/emptyList/basicView");
+ var xhr = CouchDB.request("GET", "/test_suite_db/_design/lists/_list/emptyList/basicView");
T(xhr.responseText.match(/^$/));
- xhr = CouchDB.request("GET", "/test_suite_db/_list/lists/emptyList/withReduce?group=true");
+ xhr = CouchDB.request("GET", "/test_suite_db/_design/lists/_list/emptyList/withReduce?group=true");
T(xhr.responseText.match(/^$/));
+ // multi-key fetch
+ var xhr = CouchDB.request("POST", "/test_suite_db/_design/lists/_list/simpleForm/basicView", {
+ body: '{"keys":[2,4,5,7]}'
+ });
+ T(xhr.status == 200, "multi key");
+ T(/Total Rows/.test(xhr.responseText));
+ T(!(/Key: 1/.test(xhr.responseText)));
+ T(/Key: 2/.test(xhr.responseText));
+ T(/FirstKey: 2/.test(xhr.responseText));
+ T(/LastKey: 7/.test(xhr.responseText));
+
+ // no multi-key fetch allowed when group=false
+ xhr = CouchDB.request("POST", "/test_suite_db/_design/lists/_list/simpleForm/withReduce?group=false", {
+ body: '{"keys":[2,4,5,7]}'
+ });
+ T(xhr.status == 400);
+ T(/query_parse_error/.test(xhr.responseText));
};
Modified: couchdb/branches/rep_security/share/www/script/test/replication.js
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/share/www/script/test/replication.js?rev=753413&r1=753412&r2=753413&view=diff
==============================================================================
--- couchdb/branches/rep_security/share/www/script/test/replication.js (original)
+++ couchdb/branches/rep_security/share/www/script/test/replication.js Fri Mar 13 21:12:44 2009
@@ -230,15 +230,5 @@
result2 = CouchDB.replicate(B, A);
T(result2.no_changes == true);
T(result2.session_id == result.session_id);
-
- // do a full (not incremental) replication
-
- result = CouchDB.replicate(B, A, {options:{full:true}})
-
- T(0 == result.history[0].start_last_seq);
- T(seqB == result.source_last_seq);
- T(result.history[0].end_last_seq == seqB);
- T(result.history[1].end_last_seq == seqB);
-
}
};
Modified: couchdb/branches/rep_security/share/www/script/test/show_documents.js
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/share/www/script/test/show_documents.js?rev=753413&r1=753412&r2=753413&view=diff
==============================================================================
--- couchdb/branches/rep_security/share/www/script/test/show_documents.js (original)
+++ couchdb/branches/rep_security/share/www/script/test/show_documents.js Fri Mar 13 21:12:44 2009
@@ -33,9 +33,16 @@
}
}),
"just-name" : stringFun(function(doc, req) {
- return {
- body : "Just " + doc.name
- };
+ if (doc) {
+ return {
+ body : "Just " + doc.name
+ };
+ } else {
+ return {
+ body : "No such doc",
+ code : 404
+ };
+ }
}),
"req-info" : stringFun(function(doc, req) {
return {
@@ -123,68 +130,72 @@
var docid = resp.id;
// show error
- var xhr = CouchDB.request("GET", "/test_suite_db/_show/");
- T(xhr.status == 404);
+ var xhr = CouchDB.request("GET", "/test_suite_db/_design/template/_show/");
+ T(xhr.status == 404, 'Should be missing');
T(JSON.parse(xhr.responseText).reason == "Invalid path.");
// hello template world
- xhr = CouchDB.request("GET", "/test_suite_db/_show/template/hello/"+docid);
+ xhr = CouchDB.request("GET", "/test_suite_db/_design/template/_show/hello/"+docid);
T(xhr.responseText == "Hello World");
// hello template world (no docid)
- xhr = CouchDB.request("GET", "/test_suite_db/_show/template/hello/");
+ xhr = CouchDB.request("GET", "/test_suite_db/_design/template/_show/hello");
T(xhr.responseText == "Empty World");
// // hello template world (non-existing docid)
- xhr = CouchDB.request("GET", "/test_suite_db/_show/template/hello/nonExistingDoc");
+ xhr = CouchDB.request("GET", "/test_suite_db/_design/template/_show/hello/nonExistingDoc");
T(xhr.responseText == "New World");
// show with doc
- xhr = CouchDB.request("GET", "/test_suite_db/_show/template/just-name/"+docid);
+ xhr = CouchDB.request("GET", "/test_suite_db/_design/template/_show/just-name/"+docid);
T(xhr.responseText == "Just Rusty");
+ // show with missing doc
+ xhr = CouchDB.request("GET", "/test_suite_db/_design/template/_show/just-name/missingdoc");
+
+ T(xhr.status == 404, 'Doc should be missing');
+ T(xhr.responseText == "No such doc");
// show with missing func
- xhr = CouchDB.request("GET", "/test_suite_db/_show/template/missing/"+docid);
- T(xhr.status == 404);
-
+ xhr = CouchDB.request("GET", "/test_suite_db/_design/template/_show/missing/"+docid);
+ T(xhr.status == 404, "function is missing");
+
// missing design doc
- xhr = CouchDB.request("GET", "/test_suite_db/_show/missingdoc/just-name/"+docid);
+ xhr = CouchDB.request("GET", "/test_suite_db/_design/missingddoc/_show/just-name/"+docid);
T(xhr.status == 404);
var resp = JSON.parse(xhr.responseText);
T(resp.error == "not_found");
// query parameters
- xhr = CouchDB.request("GET", "/test_suite_db/_show/template/req-info/"+docid+"?foo=bar", {
- headers: {
- "Accept": "text/html;text/plain;*/*",
- "X-Foo" : "bar"
- }
+ xhr = CouchDB.request("GET", "/test_suite_db/_design/template/_show/req-info/"+docid+"?foo=bar", {
+ headers: {
+ "Accept": "text/html;text/plain;*/*",
+ "X-Foo" : "bar"
+ }
});
var resp = JSON.parse(xhr.responseText);
T(equals(resp.headers["X-Foo"], "bar"));
T(equals(resp.query, {foo:"bar"}));
T(equals(resp.verb, "GET"));
- T(equals(resp.path[4], docid));
+ T(equals(resp.path[5], docid));
T(equals(resp.info.db_name, "test_suite_db"));
// returning a content-type
- xhr = CouchDB.request("GET", "/test_suite_db/_show/template/xml-type/"+docid);
+ xhr = CouchDB.request("GET", "/test_suite_db/_design/template/_show/xml-type/"+docid);
T("application/xml" == xhr.getResponseHeader("Content-Type"));
T("Accept" == xhr.getResponseHeader("Vary"));
// accept header switching
- // different mime has different etag
-
- xhr = CouchDB.request("GET", "/test_suite_db/_show/template/accept-switch/"+docid, {
- headers: {"Accept": "text/html;text/plain;*/*"}
+ // different mime has different etag
+ xhr = CouchDB.request("GET", "/test_suite_db/_design/template/_show/accept-switch/"+docid, {
+ headers: {"Accept": "text/html;text/plain;*/*"}
});
T("text/html" == xhr.getResponseHeader("Content-Type"));
T("Accept" == xhr.getResponseHeader("Vary"));
var etag = xhr.getResponseHeader("etag");
- xhr = CouchDB.request("GET", "/test_suite_db/_show/template/accept-switch/"+docid, {
- headers: {"Accept": "image/png;*/*"}
+ xhr = CouchDB.request("GET", "/test_suite_db/_design/template/_show/accept-switch/"+docid, {
+ headers: {"Accept": "image/png;*/*"}
});
T(xhr.responseText.match(/PNG/))
T("image/png" == xhr.getResponseHeader("Content-Type"));
@@ -193,12 +204,12 @@
// proper etags
// show with doc
- xhr = CouchDB.request("GET", "/test_suite_db/_show/template/just-name/"+docid);
+ xhr = CouchDB.request("GET", "/test_suite_db/_design/template/_show/just-name/"+docid);
// extract the ETag header values
etag = xhr.getResponseHeader("etag");
// get again with etag in request
- xhr = CouchDB.request("GET", "/test_suite_db/_show/template/just-name/"+docid, {
- headers: {"if-none-match": etag}
+ xhr = CouchDB.request("GET", "/test_suite_db/_design/template/_show/just-name/"+docid, {
+ headers: {"if-none-match": etag}
});
// should be 304
T(xhr.status == 304);
@@ -208,16 +219,16 @@
resp = db.save(doc);
T(resp.ok);
// req with same etag
- xhr = CouchDB.request("GET", "/test_suite_db/_show/template/just-name/"+docid, {
- headers: {"if-none-match": etag}
+ xhr = CouchDB.request("GET", "/test_suite_db/_design/template/_show/just-name/"+docid, {
+ headers: {"if-none-match": etag}
});
// status is 200
T(xhr.status == 200);
// get new etag and request again
etag = xhr.getResponseHeader("etag");
- xhr = CouchDB.request("GET", "/test_suite_db/_show/template/just-name/"+docid, {
- headers: {"if-none-match": etag}
+ xhr = CouchDB.request("GET", "/test_suite_db/_design/template/_show/just-name/"+docid, {
+ headers: {"if-none-match": etag}
});
// should be 304
T(xhr.status == 304);
@@ -225,9 +236,9 @@
// update design doc (but not function)
designDoc.isChanged = true;
T(db.save(designDoc).ok);
-
- xhr = CouchDB.request("GET", "/test_suite_db/_show/template/just-name/"+docid, {
- headers: {"if-none-match": etag}
+
+ xhr = CouchDB.request("GET", "/test_suite_db/_design/template/_show/just-name/"+docid, {
+ headers: {"if-none-match": etag}
});
// should be 304
T(xhr.status == 304);
@@ -240,49 +251,49 @@
}).toString();
T(db.save(designDoc).ok);
- xhr = CouchDB.request("GET", "/test_suite_db/_show/template/just-name/"+docid, {
- headers: {"if-none-match": etag}
+ xhr = CouchDB.request("GET", "/test_suite_db/_design/template/_show/just-name/"+docid, {
+ headers: {"if-none-match": etag}
});
// status is 200
T(xhr.status == 200);
// JS can't set etag
- xhr = CouchDB.request("GET", "/test_suite_db/_show/template/no-set-etag/"+docid);
+ xhr = CouchDB.request("GET", "/test_suite_db/_design/template/_show/no-set-etag/"+docid);
// extract the ETag header values
etag = xhr.getResponseHeader("etag");
T(etag != "skipped")
// test the respondWith mime matcher
- xhr = CouchDB.request("GET", "/test_suite_db/_show/template/respondWith/"+docid, {
- headers: {
- "Accept": 'text/html,application/atom+xml; q=0.9'
- }
+ xhr = CouchDB.request("GET", "/test_suite_db/_design/template/_show/respondWith/"+docid, {
+ headers: {
+ "Accept": 'text/html,application/atom+xml; q=0.9'
+ }
});
T(xhr.getResponseHeader("Content-Type") == "text/html");
T(xhr.responseText == "Ha ha, you said \"plankton\".");
// now with xml
- xhr = CouchDB.request("GET", "/test_suite_db/_show/template/respondWith/"+docid, {
- headers: {
- "Accept": 'application/xml'
- }
+ xhr = CouchDB.request("GET", "/test_suite_db/_design/template/_show/respondWith/"+docid, {
+ headers: {
+ "Accept": 'application/xml'
+ }
});
T(xhr.getResponseHeader("Content-Type") == "application/xml");
T(xhr.responseText.match(/node/));
T(xhr.responseText.match(/plankton/));
// registering types works
- xhr = CouchDB.request("GET", "/test_suite_db/_show/template/respondWith/"+docid, {
- headers: {
- "Accept": "application/x-foo"
- }
+ xhr = CouchDB.request("GET", "/test_suite_db/_design/template/_show/respondWith/"+docid, {
+ headers: {
+ "Accept": "application/x-foo"
+ }
});
T(xhr.getResponseHeader("Content-Type") == "application/x-foo");
T(xhr.responseText.match(/foofoo/));
// test the respondWith mime matcher without
- xhr = CouchDB.request("GET", "/test_suite_db/_show/template/respondWith/"+docid, {
+ xhr = CouchDB.request("GET", "/test_suite_db/_design/template/_show/respondWith/"+docid, {
headers: {
"Accept": 'text/html,application/atom+xml; q=0.9'
}
Modified: couchdb/branches/rep_security/share/www/style/layout.css
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/share/www/style/layout.css?rev=753413&r1=753412&r2=753413&view=diff
==============================================================================
--- couchdb/branches/rep_security/share/www/style/layout.css (original)
+++ couchdb/branches/rep_security/share/www/style/layout.css Fri Mar 13 21:12:44 2009
@@ -336,8 +336,8 @@
/* Database table */
-#databases thead th.apps, #databases thead th.size, #databases thead th.count, #databases thead th.seq,
-#databases thead th.apps, #databases tbody td.size, #databases tbody td.count, #databases tbody td.seq {
+#databases thead th.size, #databases thead th.count, #databases thead th.seq,
+#databases tbody td.size, #databases tbody td.count, #databases tbody td.seq {
text-align: right;
}
Modified: couchdb/branches/rep_security/src/couchdb/Makefile.am
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/src/couchdb/Makefile.am?rev=753413&r1=753412&r2=753413&view=diff
==============================================================================
--- couchdb/branches/rep_security/src/couchdb/Makefile.am (original)
+++ couchdb/branches/rep_security/src/couchdb/Makefile.am Fri Mar 13 21:12:44 2009
@@ -64,6 +64,7 @@
couch_query_servers.erl \
couch_ref_counter.erl \
couch_rep.erl \
+ couch_rep_sup.erl \
couch_server.erl \
couch_server_sup.erl \
couch_stats_aggregator.erl \
@@ -104,6 +105,7 @@
couch_query_servers.beam \
couch_ref_counter.beam \
couch_rep.beam \
+ couch_rep_sup.beam \
couch_server.beam \
couch_server_sup.beam \
couch_stats_aggregator.beam \
@@ -139,6 +141,7 @@
# couch_log.html \
# couch_query_servers.html \
# couch_rep.html \
+# couch_rep_sup.html \
# couch_server.html \
# couch_server_sup.html \
# couch_stream.html \
Modified: couchdb/branches/rep_security/src/couchdb/couch_db.hrl
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/src/couchdb/couch_db.hrl?rev=753413&r1=753412&r2=753413&view=diff
==============================================================================
--- couchdb/branches/rep_security/src/couchdb/couch_db.hrl (original)
+++ couchdb/branches/rep_security/src/couchdb/couch_db.hrl Fri Mar 13 21:12:44 2009
@@ -60,7 +60,9 @@
method,
path_parts,
db_url_handlers,
- user_ctx
+ user_ctx,
+ req_body = undefined,
+ design_url_handlers
}).
Modified: couchdb/branches/rep_security/src/couchdb/couch_doc.erl
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/src/couchdb/couch_doc.erl?rev=753413&r1=753412&r2=753413&view=diff
==============================================================================
--- couchdb/branches/rep_security/src/couchdb/couch_doc.erl (original)
+++ couchdb/branches/rep_security/src/couchdb/couch_doc.erl Fri Mar 13 21:12:44 2009
@@ -63,7 +63,13 @@
to_json_attachment_stubs(Attachments) ->
BinProps = lists:map(
- fun({Name, {Type, BinValue}}) ->
+ fun({Name, {Type, {_RcvFun, Length}}}) ->
+ {Name, {[
+ {<<"stub">>, true},
+ {<<"content_type">>, Type},
+ {<<"length">>, Length}
+ ]}};
+ ({Name, {Type, BinValue}}) ->
{Name, {[
{<<"stub">>, true},
{<<"content_type">>, Type},
@@ -78,7 +84,13 @@
to_json_attachments(Attachments) ->
BinProps = lists:map(
- fun({Name, {Type, BinValue}}) ->
+ fun({Name, {Type, {RcvFun, Length}}}) ->
+ Data = read_streamed_attachment(RcvFun, Length, _Acc = []),
+ {Name, {[
+ {<<"content_type">>, Type},
+ {<<"data">>, couch_util:encodeBase64(Data)}
+ ]}};
+ ({Name, {Type, BinValue}}) ->
{Name, {[
{<<"content_type">>, Type},
{<<"data">>, couch_util:encodeBase64(bin_to_binary(BinValue))}
@@ -157,7 +169,9 @@
Bins = lists:flatmap(fun({Name, {BinProps}}) ->
case proplists:get_value(<<"stub">>, BinProps) of
true ->
- [{Name, stub}];
+ Type = proplists:get_value(<<"content_type">>, BinProps),
+ Length = proplists:get_value(<<"length">>, BinProps),
+ [{Name, {stub, Type, Length}}];
_ ->
Value = proplists:get_value(<<"data">>, BinProps),
Type = proplists:get_value(<<"content_type">>, BinProps,
@@ -270,7 +284,7 @@
has_stubs(Bins);
has_stubs([]) ->
false;
-has_stubs([{_Name, stub}|_]) ->
+has_stubs([{_Name, {stub, _, _}}|_]) ->
true;
has_stubs([_Bin|Rest]) ->
has_stubs(Rest).
@@ -278,9 +292,15 @@
merge_stubs(#doc{attachments=MemBins}=StubsDoc, #doc{attachments=DiskBins}) ->
BinDict = dict:from_list(DiskBins),
MergedBins = lists:map(
- fun({Name, stub}) ->
+ fun({Name, {stub, _, _}}) ->
{Name, dict:fetch(Name, BinDict)};
({Name, Value}) ->
{Name, Value}
end, MemBins),
StubsDoc#doc{attachments= MergedBins}.
+
+read_streamed_attachment(_RcvFun, 0, Acc) ->
+ list_to_binary(lists:reverse(Acc));
+read_streamed_attachment(RcvFun, LenLeft, Acc) ->
+ Bin = RcvFun(),
+ read_streamed_attachment(RcvFun, LenLeft - size(Bin), [Bin|Acc]).
Modified: couchdb/branches/rep_security/src/couchdb/couch_external_server.erl
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/src/couchdb/couch_external_server.erl?rev=753413&r1=753412&r2=753413&view=diff
==============================================================================
--- couchdb/branches/rep_security/src/couchdb/couch_external_server.erl (original)
+++ couchdb/branches/rep_security/src/couchdb/couch_external_server.erl Fri Mar 13 21:12:44 2009
@@ -27,7 +27,7 @@
gen_server:cast(Pid, stop).
execute(Pid, JsonReq) ->
- gen_server:call(Pid, {execute, JsonReq}).
+ gen_server:call(Pid, {execute, JsonReq}, infinity).
% Gen Server Handlers
Modified: couchdb/branches/rep_security/src/couchdb/couch_httpd.erl
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/src/couchdb/couch_httpd.erl?rev=753413&r1=753412&r2=753413&view=diff
==============================================================================
--- couchdb/branches/rep_security/src/couchdb/couch_httpd.erl (original)
+++ couchdb/branches/rep_security/src/couchdb/couch_httpd.erl Fri Mar 13 21:12:44 2009
@@ -13,7 +13,7 @@
-module(couch_httpd).
-include("couch_db.hrl").
--export([start_link/0, stop/0, handle_request/3]).
+-export([start_link/0, stop/0, handle_request/4]).
-export([header_value/2,header_value/3,qs_value/2,qs_value/3,qs/1,path/1,absolute_uri/2]).
-export([verify_is_server_admin/1,unquote/1,quote/1,recv/2,recv_chunked/4,error_info/1]).
@@ -44,11 +44,18 @@
fun({UrlKey, SpecStr}) ->
{?l2b(UrlKey), make_arity_2_fun(SpecStr)}
end, couch_config:get("httpd_db_handlers")),
+
+ DesignUrlHandlersList = lists:map(
+ fun({UrlKey, SpecStr}) ->
+ {?l2b(UrlKey), make_arity_2_fun(SpecStr)}
+ end, couch_config:get("httpd_design_handlers")),
+
UrlHandlers = dict:from_list(UrlHandlersList),
DbUrlHandlers = dict:from_list(DbUrlHandlersList),
+ DesignUrlHandlers = dict:from_list(DesignUrlHandlersList),
Loop = fun(Req)->
apply(?MODULE, handle_request,
- [Req, UrlHandlers, DbUrlHandlers])
+ [Req, UrlHandlers, DbUrlHandlers, DesignUrlHandlers])
end,
% and off we go
@@ -101,7 +108,7 @@
mochiweb_http:stop(?MODULE).
-handle_request(MochiReq, UrlHandlers, DbUrlHandlers) ->
+handle_request(MochiReq, UrlHandlers, DbUrlHandlers, DesignUrlHandlers) ->
statistics(runtime), % prepare request_time counter, see end of function
AuthenticationFun = make_arity_1_fun(
couch_config:get("httpd", "authentication_handler")),
@@ -147,7 +154,8 @@
method = Method,
path_parts = [list_to_binary(couch_httpd:unquote(Part))
|| Part <- string:tokens(Path, "/")],
- db_url_handlers = DbUrlHandlers
+ db_url_handlers = DbUrlHandlers,
+ design_url_handlers = DesignUrlHandlers
},
DefaultFun = fun couch_httpd_db:handle_request/1,
HandlerFun = couch_util:dict_find(HandlerKey, UrlHandlers, DefaultFun),
@@ -347,7 +355,7 @@
send_response(#httpd{mochi_req=MochiReq}, Code, Headers, Body) ->
couch_stats_collector:increment({httpd_status_codes, Code}),
if Code >= 400 ->
- ?LOG_DEBUG("HTTPd ~p error response:~n ~s", [Code, Body]);
+ ?LOG_DEBUG("httpd ~p error response:~n ~s", [Code, Body]);
true -> ok
end,
{ok, MochiReq:respond({Code, Headers ++ server_header(), Body})}.
@@ -384,11 +392,12 @@
send_chunk(Resp, []).
-
error_info(bad_request) ->
{400, <<"bad_request">>, <<>>};
error_info({bad_request, Reason}) ->
{400, <<"bad_request">>, Reason};
+error_info({query_parse_error, Reason}) ->
+ {400, <<"query_parse_error">>, Reason};
error_info(not_found) ->
{404, <<"not_found">>, <<"Missing">>};
error_info({not_found, Reason}) ->
Modified: couchdb/branches/rep_security/src/couchdb/couch_httpd_db.erl
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/src/couchdb/couch_httpd_db.erl?rev=753413&r1=753412&r2=753413&view=diff
==============================================================================
--- couchdb/branches/rep_security/src/couchdb/couch_httpd_db.erl (original)
+++ couchdb/branches/rep_security/src/couchdb/couch_httpd_db.erl Fri Mar 13 21:12:44 2009
@@ -13,7 +13,7 @@
-module(couch_httpd_db).
-include("couch_db.hrl").
--export([handle_request/1, db_req/2, couch_doc_open/4]).
+-export([handle_request/1, handle_design_req/2, db_req/2, couch_doc_open/4]).
-import(couch_httpd,
[send_json/2,send_json/3,send_json/4,send_method_not_allowed/2,
@@ -41,6 +41,16 @@
do_db_req(Req, Handler)
end.
+handle_design_req(#httpd{
+ path_parts=[_DbName,_Design,_DesName, <<"_",_/binary>> = Action | _Rest],
+ design_url_handlers = DesignUrlHandlers
+ }=Req, Db) ->
+ Handler = couch_util:dict_find(Action, DesignUrlHandlers, fun db_req/2),
+ Handler(Req, Db);
+
+handle_design_req(Req, Db) ->
+ db_req(Req, Db).
+
create_db_req(#httpd{user_ctx=UserCtx}=Req, DbName) ->
ok = couch_httpd:verify_is_server_admin(Req),
case couch_server:create(DbName, [{user_ctx, UserCtx}]) of
@@ -116,6 +126,7 @@
Docs = lists:map(
fun({ObjProps} = JsonObj) ->
Doc = couch_doc:from_json_obj(JsonObj),
+ validate_attachment_names(Doc),
Id = case Doc#doc.id of
<<>> -> couch_util:new_uuid();
Id0 -> Id0
@@ -460,31 +471,6 @@
end_json_response(Resp)
end;
-db_doc_req(#httpd{method='POST'}=Req, Db, DocId) ->
- Form = couch_httpd:parse_form(Req),
- Rev = couch_doc:parse_rev(proplists:get_value("_rev", Form)),
- Doc = case couch_db:open_doc_revs(Db, DocId, [Rev], []) of
- {ok, [{ok, Doc0}]} -> Doc0#doc{revs=[Rev]};
- {ok, [Error]} -> throw(Error)
- end,
-
- NewAttachments = [
- {list_to_binary(Name), {list_to_binary(ContentType), Content}} ||
- {Name, {ContentType, _}, Content} <-
- proplists:get_all_values("_attachments", Form)
- ],
- #doc{attachments=Attachments} = Doc,
- NewDoc = Doc#doc{
- attachments = Attachments ++ NewAttachments
- },
- {ok, NewRev} = couch_db:update_doc(Db, NewDoc, []),
-
- send_json(Req, 201, [{"Etag", "\"" ++ NewRev ++ "\""}], {obj, [
- {ok, true},
- {id, DocId},
- {rev, NewRev}
- ]});
-
db_doc_req(#httpd{method='PUT'}=Req, Db, DocId) ->
update_doc(Req, Db, DocId, couch_httpd:json_body(Req));
@@ -545,6 +531,7 @@
update_doc(Req, Db, DocId, Json) ->
#doc{deleted=Deleted} = Doc = couch_doc:from_json_obj(Json),
+ validate_attachment_names(Doc),
ExplicitDocRev =
case Doc#doc.revs of
{Start,[RevId|_]} -> {Start, RevId};
@@ -629,8 +616,11 @@
db_attachment_req(#httpd{method=Method}=Req, Db, DocId, FileNameParts)
when (Method == 'PUT') or (Method == 'DELETE') ->
- FileName = list_to_binary(mochiweb_util:join(lists:map(fun binary_to_list/1,
- FileNameParts),"/")),
+ FileName = validate_attachment_name(
+ mochiweb_util:join(
+ lists:map(fun binary_to_list/1,
+ FileNameParts),"/")),
+
NewAttachment = case Method of
'DELETE' ->
[];
@@ -746,3 +736,44 @@
{list_to_binary(DocId), {Pos, [RevId]}}
end.
+validate_attachment_names(Doc) ->
+ lists:foreach(fun({Name, _}) ->
+ validate_attachment_name(Name)
+ end, Doc#doc.attachments).
+
+validate_attachment_name(Name) when is_list(Name) ->
+ validate_attachment_name(list_to_binary(Name));
+validate_attachment_name(<<"_",_/binary>>) ->
+ throw({bad_request, <<"Attachment name can't start with '_'">>});
+validate_attachment_name(Name) ->
+ case is_valid_utf8(Name) of
+ true -> Name;
+ false -> throw({bad_request, <<"Attachment name is not UTF-8 encoded">>})
+ end.
+
+%% borrowed from mochijson2:json_bin_is_safe()
+is_valid_utf8(<<>>) ->
+ true;
+is_valid_utf8(<<C, Rest/binary>>) ->
+ case C of
+ $\" ->
+ false;
+ $\\ ->
+ false;
+ $\b ->
+ false;
+ $\f ->
+ false;
+ $\n ->
+ false;
+ $\r ->
+ false;
+ $\t ->
+ false;
+ C when C >= 0, C < $\s; C >= 16#7f, C =< 16#10FFFF ->
+ false;
+ C when C < 16#7f ->
+ is_valid_utf8(Rest);
+ _ ->
+ false
+ end.
Modified: couchdb/branches/rep_security/src/couchdb/couch_httpd_external.erl
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/src/couchdb/couch_httpd_external.erl?rev=753413&r1=753412&r2=753413&view=diff
==============================================================================
--- couchdb/branches/rep_security/src/couchdb/couch_httpd_external.erl (original)
+++ couchdb/branches/rep_security/src/couchdb/couch_httpd_external.erl Fri Mar 13 21:12:44 2009
@@ -56,9 +56,13 @@
json_req_obj(#httpd{mochi_req=Req,
method=Verb,
- path_parts=Path
+ path_parts=Path,
+ req_body=ReqBody
}, Db) ->
- ReqBody = Req:recv_body(),
+ Body = case ReqBody of
+ undefined -> Req:recv_body();
+ Else -> Else
+ end,
ParsedForm = case Req:get_primary_header_value("content-type") of
"application/x-www-form-urlencoded" ++ _ ->
mochiweb_util:parse_qs(ReqBody);
@@ -74,7 +78,7 @@
{<<"path">>, Path},
{<<"query">>, to_json_terms(Req:parse_qs())},
{<<"headers">>, to_json_terms(Hlist)},
- {<<"body">>, ReqBody},
+ {<<"body">>, Body},
{<<"form">>, to_json_terms(ParsedForm)},
{<<"cookie">>, to_json_terms(Req:parse_cookie())}]}.
Modified: couchdb/branches/rep_security/src/couchdb/couch_httpd_misc_handlers.erl
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/src/couchdb/couch_httpd_misc_handlers.erl?rev=753413&r1=753412&r2=753413&view=diff
==============================================================================
--- couchdb/branches/rep_security/src/couchdb/couch_httpd_misc_handlers.erl (original)
+++ couchdb/branches/rep_security/src/couchdb/couch_httpd_misc_handlers.erl Fri Mar 13 21:12:44 2009
@@ -70,12 +70,12 @@
handle_task_status_req(Req) ->
send_method_not_allowed(Req, "GET,HEAD").
-% convert to list and add trailing slash if missing
+% add trailing slash if missing
fix_db_url(UrlBin) ->
- case lists:last(Url = ?b2l(UrlBin)) of
+ ?l2b(case lists:last(Url = ?b2l(UrlBin)) of
$/ -> Url;
_ -> Url ++ "/"
- end.
+ end).
get_rep_endpoint(_Req, {Props}) ->
@@ -91,12 +91,16 @@
handle_replicate_req(#httpd{method='POST'}=Req) ->
{Props} = couch_httpd:json_body(Req),
- Src = get_rep_endpoint(Req, proplists:get_value(<<"source">>, Props)),
- Tgt = get_rep_endpoint(Req, proplists:get_value(<<"target">>, Props)),
- {OptionsBin} = proplists:get_value(<<"options">>, Props, {[]}),
- Options = [{couch_util:to_existing_atom(K), V} || {K,V} <- OptionsBin],
- {ok, {JsonResults}} = couch_rep:replicate(Src, Tgt, Options),
- send_json(Req, {[{ok, true} | JsonResults]});
+ Source = get_rep_endpoint(Req, proplists:get_value(<<"source">>, Props)),
+ Target = get_rep_endpoint(Req, proplists:get_value(<<"target">>, Props)),
+ case couch_rep:replicate(Source, Target) of
+ {ok, {JsonResults}} ->
+ send_json(Req, {[{ok, true} | JsonResults]});
+ {error, {Type, Details}} ->
+ send_json(Req, 500, {[{error, Type}, {reason, Details}]});
+ {error, Reason} ->
+ send_json(Req, 500, {[{error, Reason}]})
+ end;
handle_replicate_req(Req) ->
send_method_not_allowed(Req, "POST").
Modified: couchdb/branches/rep_security/src/couchdb/couch_httpd_show.erl
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/src/couchdb/couch_httpd_show.erl?rev=753413&r1=753412&r2=753413&view=diff
==============================================================================
--- couchdb/branches/rep_security/src/couchdb/couch_httpd_show.erl (original)
+++ couchdb/branches/rep_security/src/couchdb/couch_httpd_show.erl Fri Mar 13 21:12:44 2009
@@ -24,7 +24,7 @@
handle_doc_show_req(#httpd{
method='GET',
- path_parts=[_, _, DesignName, ShowName, DocId]
+ path_parts=[_DbName, _Design, DesignName, _Show, ShowName, DocId]
}=Req, Db) ->
DesignId = <<"_design/", DesignName/binary>>,
#doc{body={Props}} = couch_httpd_db:couch_doc_open(Db, DesignId, nil, []),
@@ -39,7 +39,7 @@
handle_doc_show_req(#httpd{
method='GET',
- path_parts=[_, _, DesignName, ShowName]
+ path_parts=[_DbName, _Design, DesignName, _Show, ShowName]
}=Req, Db) ->
DesignId = <<"_design/", DesignName/binary>>,
#doc{body={Props}} = couch_httpd_db:couch_doc_open(Db, DesignId, nil, []),
@@ -53,18 +53,30 @@
handle_doc_show_req(Req, _Db) ->
send_method_not_allowed(Req, "GET,HEAD").
-handle_view_list_req(#httpd{method='GET',path_parts=[_, _, DesignName, ListName, ViewName]}=Req, Db) ->
+handle_view_list_req(#httpd{method='GET',
+ path_parts=[_DbName, _Design, DesignName, _List, ListName, ViewName]}=Req, Db) ->
DesignId = <<"_design/", DesignName/binary>>,
#doc{body={Props}} = couch_httpd_db:couch_doc_open(Db, DesignId, nil, []),
Lang = proplists:get_value(<<"language">>, Props, <<"javascript">>),
ListSrc = get_nested_json_value({Props}, [<<"lists">>, ListName]),
- send_view_list_response(Lang, ListSrc, ViewName, DesignId, Req, Db);
+ send_view_list_response(Lang, ListSrc, ViewName, DesignId, Req, Db, nil);
handle_view_list_req(#httpd{method='GET'}=Req, _Db) ->
send_error(Req, 404, <<"list_error">>, <<"Invalid path.">>);
+handle_view_list_req(#httpd{method='POST',
+ path_parts=[_DbName, _Design, DesignName, _List, ListName, ViewName]}=Req, Db) ->
+ DesignId = <<"_design/", DesignName/binary>>,
+ #doc{body={Props}} = couch_httpd_db:couch_doc_open(Db, DesignId, [], []),
+ Lang = proplists:get_value(<<"language">>, Props, <<"javascript">>),
+ ListSrc = get_nested_json_value({Props}, [<<"lists">>, ListName]),
+ ReqBody = couch_httpd:body(Req),
+ {Props2} = ?JSON_DECODE(ReqBody),
+ Keys = proplists:get_value(<<"keys">>, Props2, nil),
+ send_view_list_response(Lang, ListSrc, ViewName, DesignId, Req#httpd{req_body=ReqBody}, Db, Keys);
+
handle_view_list_req(Req, _Db) ->
- send_method_not_allowed(Req, "GET,HEAD").
+ send_method_not_allowed(Req, "GET,POST,HEAD").
get_nested_json_value({Props}, [Key|Keys]) ->
@@ -77,30 +89,71 @@
get_nested_json_value(_NotJSONObj, _) ->
throw({not_found, json_mismatch}).
-send_view_list_response(Lang, ListSrc, ViewName, DesignId, Req, Db) ->
+send_view_list_response(Lang, ListSrc, ViewName, DesignId, Req, Db, Keys) ->
#view_query_args{
stale = Stale,
reduce = Reduce
} = QueryArgs = couch_httpd_view:parse_view_query(Req, nil, nil, true),
case couch_view:get_map_view(Db, DesignId, ViewName, Stale) of
{ok, View, Group} ->
- output_map_list(Req, Lang, ListSrc, View, Group, Db, QueryArgs);
+ output_map_list(Req, Lang, ListSrc, View, Group, Db, QueryArgs, Keys);
{not_found, _Reason} ->
case couch_view:get_reduce_view(Db, DesignId, ViewName, Stale) of
{ok, ReduceView, Group} ->
+ couch_httpd_view:parse_view_query(Req, Keys, true, true), % just for validation
case Reduce of
false ->
MapView = couch_view:extract_map_view(ReduceView),
- output_map_list(Req, Lang, ListSrc, MapView, Group, Db, QueryArgs);
+ output_map_list(Req, Lang, ListSrc, MapView, Group, Db, QueryArgs, Keys);
_ ->
- output_reduce_list(Req, Lang, ListSrc, ReduceView, Group, Db, QueryArgs)
+ output_reduce_list(Req, Lang, ListSrc, ReduceView, Group, Db, QueryArgs, Keys)
end;
{not_found, Reason} ->
throw({not_found, Reason})
end
end.
-output_map_list(#httpd{mochi_req=MReq}=Req, Lang, ListSrc, View, Group, Db, QueryArgs) ->
+make_map_start_resp_fun(QueryServer, Req, Db, CurrentEtag) ->
+ fun(Req2, _Etag, TotalViewCount, Offset) ->
+ ExternalResp = couch_query_servers:render_list_head(QueryServer,
+ Req2, Db, TotalViewCount, Offset),
+ JsonResp = apply_etag(ExternalResp, CurrentEtag),
+ #extern_resp_args{
+ code = Code,
+ data = BeginBody,
+ ctype = CType,
+ headers = ExtHeaders
+ } = couch_httpd_external:parse_external_response(JsonResp),
+ JsonHeaders = couch_httpd_external:default_or_content_type(CType, ExtHeaders),
+ {ok, Resp} = start_chunked_response(Req, Code, JsonHeaders),
+ {ok, Resp, binary_to_list(BeginBody)}
+ end.
+
+make_map_send_row_fun(QueryServer, Req) ->
+ fun(Resp, Db2, {{Key, DocId}, Value},
+ RowFront, _IncludeDocs) ->
+ JsonResp = couch_query_servers:render_list_row(QueryServer,
+ Req, Db2, {{Key, DocId}, Value}),
+ #extern_resp_args{
+ stop = StopIter,
+ data = RowBody
+ } = couch_httpd_external:parse_external_response(JsonResp),
+ case StopIter of
+ true -> stop;
+ _ ->
+ RowFront2 = case RowFront of
+ nil -> [];
+ _ -> RowFront
+ end,
+ Chunk = RowFront2 ++ binary_to_list(RowBody),
+ case Chunk of
+ [] -> {ok, Resp};
+ _ -> send_chunk(Resp, Chunk)
+ end
+ end
+ end.
+
+output_map_list(#httpd{mochi_req=MReq}=Req, Lang, ListSrc, View, Group, Db, QueryArgs, nil) ->
#view_query_args{
limit = Limit,
direction = Dir,
@@ -119,43 +172,8 @@
% pass it into the view fold with closures
{ok, QueryServer} = couch_query_servers:start_view_list(Lang, ListSrc),
- StartListRespFun = fun(Req2, _Etag, TotalViewCount, Offset) ->
- ExternalResp = couch_query_servers:render_list_head(QueryServer,
- Req2, Db, TotalViewCount, Offset),
- JsonResp = apply_etag(ExternalResp, CurrentEtag),
- #extern_resp_args{
- code = Code,
- data = BeginBody,
- ctype = CType,
- headers = ExtHeaders
- } = couch_httpd_external:parse_external_response(JsonResp),
- JsonHeaders = couch_httpd_external:default_or_content_type(CType, ExtHeaders),
- {ok, Resp} = start_chunked_response(Req, Code, JsonHeaders),
- {ok, Resp, binary_to_list(BeginBody)}
- end,
-
- SendListRowFun = fun(Resp, Db2, {{Key, DocId}, Value},
- RowFront, _IncludeDocs) ->
- JsonResp = couch_query_servers:render_list_row(QueryServer,
- Req, Db2, {{Key, DocId}, Value}),
- #extern_resp_args{
- stop = StopIter,
- data = RowBody
- } = couch_httpd_external:parse_external_response(JsonResp),
- case StopIter of
- true -> stop;
- _ ->
- RowFront2 = case RowFront of
- nil -> [];
- _ -> RowFront
- end,
- Chunk = RowFront2 ++ binary_to_list(RowBody),
- case Chunk of
- [] -> {ok, Resp};
- _ -> send_chunk(Resp, Chunk)
- end
- end
- end,
+ StartListRespFun = make_map_start_resp_fun(QueryServer, Req, Db, CurrentEtag),
+ SendListRowFun = make_map_send_row_fun(QueryServer, Req),
FoldlFun = couch_httpd_view:make_view_fold_fun(Req, QueryArgs, CurrentEtag, Db, RowCount,
#view_fold_helper_funs{
@@ -166,9 +184,85 @@
FoldAccInit = {Limit, SkipCount, undefined, []},
FoldResult = couch_view:fold(View, Start, Dir, FoldlFun, FoldAccInit),
finish_list(Req, Db, QueryServer, CurrentEtag, FoldResult, StartListRespFun, RowCount)
+ end);
+
+output_map_list(#httpd{mochi_req=MReq}=Req, Lang, ListSrc, View, Group, Db, QueryArgs, Keys) ->
+ #view_query_args{
+ limit = Limit,
+ direction = Dir,
+ skip = SkipCount,
+ start_docid = StartDocId
+ } = QueryArgs,
+ {ok, RowCount} = couch_view:get_row_count(View),
+ Headers = MReq:get(headers),
+ Hlist = mochiweb_headers:to_list(Headers),
+ Accept = proplists:get_value('Accept', Hlist),
+ CurrentEtag = couch_httpd_view:view_group_etag(Group, {Lang, ListSrc, Accept}),
+ couch_httpd:etag_respond(Req, CurrentEtag, fun() ->
+ % get the os process here
+ % pass it into the view fold with closures
+ {ok, QueryServer} = couch_query_servers:start_view_list(Lang, ListSrc),
+
+ StartListRespFun = make_map_start_resp_fun(QueryServer, Req, Db, CurrentEtag),
+ SendListRowFun = make_map_send_row_fun(QueryServer, Req),
+
+ FoldAccInit = {Limit, SkipCount, undefined, []},
+ FoldResult = lists:foldl(
+ fun(Key, {ok, FoldAcc}) ->
+ FoldlFun = couch_httpd_view:make_view_fold_fun(Req, QueryArgs#view_query_args{
+ start_key = Key,
+ end_key = Key
+ }, CurrentEtag, Db, RowCount,
+ #view_fold_helper_funs{
+ reduce_count = fun couch_view:reduce_to_count/1,
+ start_response = StartListRespFun,
+ send_row = SendListRowFun
+ }),
+ couch_view:fold(View, {Key, StartDocId}, Dir, FoldlFun, FoldAcc)
+ end, {ok, FoldAccInit}, Keys),
+ finish_list(Req, Db, QueryServer, CurrentEtag, FoldResult, StartListRespFun, RowCount)
end).
-output_reduce_list(#httpd{mochi_req=MReq}=Req, Lang, ListSrc, View, Group, Db, QueryArgs) ->
+make_reduce_start_resp_fun(QueryServer, Req, Db, CurrentEtag) ->
+ fun(Req2, _Etag, _, _) ->
+ JsonResp = couch_query_servers:render_reduce_head(QueryServer,
+ Req2, Db),
+ JsonResp2 = apply_etag(JsonResp, CurrentEtag),
+ #extern_resp_args{
+ code = Code,
+ data = BeginBody,
+ ctype = CType,
+ headers = ExtHeaders
+ } = couch_httpd_external:parse_external_response(JsonResp2),
+ JsonHeaders = couch_httpd_external:default_or_content_type(CType, ExtHeaders),
+ {ok, Resp} = start_chunked_response(Req, Code, JsonHeaders),
+ {ok, Resp, binary_to_list(BeginBody)}
+ end.
+
+make_reduce_send_row_fun(QueryServer, Req, Db) ->
+ fun(Resp, {Key, Value}, RowFront) ->
+ JsonResp = couch_query_servers:render_reduce_row(QueryServer,
+ Req, Db, {Key, Value}),
+ #extern_resp_args{
+ stop = StopIter,
+ data = RowBody
+ } = couch_httpd_external:parse_external_response(JsonResp),
+ RowFront2 = case RowFront of
+ nil -> [];
+ _ -> RowFront
+ end,
+ case StopIter of
+ true -> stop;
+ _ ->
+ Chunk = RowFront2 ++ binary_to_list(RowBody),
+ case Chunk of
+ [] -> {ok, Resp};
+ _ -> send_chunk(Resp, Chunk)
+ end
+ end
+ end.
+
+output_reduce_list(#httpd{mochi_req=MReq}=Req, Lang, ListSrc, View, Group, Db, QueryArgs, nil) ->
#view_query_args{
limit = Limit,
direction = Dir,
@@ -187,42 +281,8 @@
Accept = proplists:get_value('Accept', Hlist),
CurrentEtag = couch_httpd_view:view_group_etag(Group, {Lang, ListSrc, Accept}),
couch_httpd:etag_respond(Req, CurrentEtag, fun() ->
- StartListRespFun = fun(Req2, _Etag, _, _) ->
- JsonResp = couch_query_servers:render_reduce_head(QueryServer,
- Req2, Db),
- JsonResp2 = apply_etag(JsonResp, CurrentEtag),
- #extern_resp_args{
- code = Code,
- data = BeginBody,
- ctype = CType,
- headers = ExtHeaders
- } = couch_httpd_external:parse_external_response(JsonResp2),
- JsonHeaders = couch_httpd_external:default_or_content_type(CType, ExtHeaders),
- {ok, Resp} = start_chunked_response(Req, Code, JsonHeaders),
- {ok, Resp, binary_to_list(BeginBody)}
- end,
-
- SendListRowFun = fun(Resp, {Key, Value}, RowFront) ->
- JsonResp = couch_query_servers:render_reduce_row(QueryServer,
- Req, Db, {Key, Value}),
- #extern_resp_args{
- stop = StopIter,
- data = RowBody
- } = couch_httpd_external:parse_external_response(JsonResp),
- RowFront2 = case RowFront of
- nil -> [];
- _ -> RowFront
- end,
- case StopIter of
- true -> stop;
- _ ->
- Chunk = RowFront2 ++ binary_to_list(RowBody),
- case Chunk of
- [] -> {ok, Resp};
- _ -> send_chunk(Resp, Chunk)
- end
- end
- end,
+ StartListRespFun = make_reduce_start_resp_fun(QueryServer, Req, Db, CurrentEtag),
+ SendListRowFun = make_reduce_send_row_fun(QueryServer, Req, Db),
{ok, GroupRowsFun, RespFun} = couch_httpd_view:make_reduce_fold_funs(Req,
GroupLevel, QueryArgs, CurrentEtag,
@@ -235,6 +295,42 @@
{EndKey, EndDocId}, GroupRowsFun, RespFun,
FoldAccInit),
finish_list(Req, Db, QueryServer, CurrentEtag, FoldResult, StartListRespFun, null)
+ end);
+
+output_reduce_list(#httpd{mochi_req=MReq}=Req, Lang, ListSrc, View, Group, Db, QueryArgs, Keys) ->
+ #view_query_args{
+ limit = Limit,
+ direction = Dir,
+ skip = SkipCount,
+ start_docid = StartDocId,
+ end_docid = EndDocId,
+ group_level = GroupLevel
+ } = QueryArgs,
+ % get the os process here
+ % pass it into the view fold with closures
+ {ok, QueryServer} = couch_query_servers:start_view_list(Lang, ListSrc),
+ Headers = MReq:get(headers),
+ Hlist = mochiweb_headers:to_list(Headers),
+ Accept = proplists:get_value('Accept', Hlist),
+ CurrentEtag = couch_httpd_view:view_group_etag(Group, {Lang, ListSrc, Accept, Keys}),
+
+ couch_httpd:etag_respond(Req, CurrentEtag, fun() ->
+ StartListRespFun = make_reduce_start_resp_fun(QueryServer, Req, Db, CurrentEtag),
+ SendListRowFun = make_reduce_send_row_fun(QueryServer, Req, Db),
+
+ {ok, GroupRowsFun, RespFun} = couch_httpd_view:make_reduce_fold_funs(Req,
+ GroupLevel, QueryArgs, CurrentEtag,
+ #reduce_fold_helper_funs{
+ start_response = StartListRespFun,
+ send_row = SendListRowFun
+ }),
+ FoldAccInit = {Limit, SkipCount, undefined, []},
+ FoldResult = lists:foldl(
+ fun(Key, {ok, FoldAcc}) ->
+ couch_view:fold_reduce(View, Dir, {Key, StartDocId},
+ {Key, EndDocId}, GroupRowsFun, RespFun, FoldAcc)
+ end, {ok, FoldAccInit}, Keys),
+ finish_list(Req, Db, QueryServer, CurrentEtag, FoldResult, StartListRespFun, null)
end).
finish_list(Req, Db, QueryServer, Etag, FoldResult, StartListRespFun, TotalRows) ->
Modified: couchdb/branches/rep_security/src/couchdb/couch_httpd_view.erl
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/src/couchdb/couch_httpd_view.erl?rev=753413&r1=753412&r2=753413&view=diff
==============================================================================
--- couchdb/branches/rep_security/src/couchdb/couch_httpd_view.erl (original)
+++ couchdb/branches/rep_security/src/couchdb/couch_httpd_view.erl Fri Mar 13 21:12:44 2009
@@ -49,13 +49,15 @@
couch_stats_collector:increment({httpd, view_reads}),
Result.
-handle_view_req(#httpd{method='GET',path_parts=[_,_, Id, ViewName]}=Req, Db) ->
- design_doc_view(Req, Db, Id, ViewName, nil);
+handle_view_req(#httpd{method='GET',
+ path_parts=[_Db, _Design, DName, _View, ViewName]}=Req, Db) ->
+ design_doc_view(Req, Db, DName, ViewName, nil);
-handle_view_req(#httpd{method='POST',path_parts=[_,_, Id, ViewName]}=Req, Db) ->
+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, Id, ViewName, Keys);
+ design_doc_view(Req, Db, DName, ViewName, Keys);
handle_view_req(Req, _Db) ->
send_method_not_allowed(Req, "GET,POST,HEAD").
Modified: couchdb/branches/rep_security/src/couchdb/couch_os_process.erl
URL: http://svn.apache.org/viewvc/couchdb/branches/rep_security/src/couchdb/couch_os_process.erl?rev=753413&r1=753412&r2=753413&view=diff
==============================================================================
--- couchdb/branches/rep_security/src/couchdb/couch_os_process.erl (original)
+++ couchdb/branches/rep_security/src/couchdb/couch_os_process.erl Fri Mar 13 21:12:44 2009
@@ -51,7 +51,7 @@
gen_server:call(Pid, read).
prompt(Pid, Data) ->
- gen_server:call(Pid, {prompt, Data}).
+ gen_server:call(Pid, {prompt, Data}, infinity).
async(Pid, Data, CallBack) ->
gen_server:cast(Pid, {async, Data, CallBack}).
@@ -99,12 +99,14 @@
% gen_server API
init([Command, Options, PortOptions]) ->
+ BaseTimeOut = list_to_integer(couch_config:get(
+ "couchdb", "os_process_timeout", "5000")),
BaseProc = #os_proc{
command=Command,
port=open_port({spawn, Command}, PortOptions),
writer=fun writejson/2,
reader=fun readjson/1,
- timeout=5000
+ timeout=BaseTimeOut
},
OsProc =
lists:foldl(fun(Opt, Proc) ->