summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Newson <rnewson@apache.org>2012-08-31 12:16:17 +0100
committerRobert Newson <rnewson@apache.org>2012-08-31 12:22:17 +0100
commit272d641529e6cde5a24ed73e827e27ef52c87d2a (patch)
tree336a297a9d233e1260fca9db26be469dab2d2e9f
parent4067f743026fbaf8d48fe000d90a26a5c38c988a (diff)
downloadcouchdb-272d641529e6cde5a24ed73e827e27ef52c87d2a.tar.gz
COUCHDB-1026 - encode database name when rewriting
-rw-r--r--CHANGES4
-rw-r--r--NEWS1
-rw-r--r--share/www/script/test/rewrite.js217
-rw-r--r--src/couchdb/couch_httpd_rewrite.erl2
4 files changed, 115 insertions, 109 deletions
diff --git a/CHANGES b/CHANGES
index a56f63783..94f2c175d 100644
--- a/CHANGES
+++ b/CHANGES
@@ -50,6 +50,10 @@ UUID Algorithms:
* Added the utc_id algorithm.
+URL Rewriter & Vhosts:
+
+ * database name is encoded during rewriting (allowing embedded /'s, etc)
+
Version 1.2.1
-------------
diff --git a/NEWS b/NEWS
index d4e50e52a..08088a72b 100644
--- a/NEWS
+++ b/NEWS
@@ -23,6 +23,7 @@ This version has not been released yet.
* Moved the JS test suite to the CLI
* Make password hashing synchronous when using the /_config/admins API.
* Added utc_id UUID algorithm.
+ * encode database name during URL rewriting.
Version 1.2.1
-------------
diff --git a/share/www/script/test/rewrite.js b/share/www/script/test/rewrite.js
index 352e6b99b..ed7d26cb0 100644
--- a/share/www/script/test/rewrite.js
+++ b/share/www/script/test/rewrite.js
@@ -13,33 +13,33 @@
couchTests.rewrite = function(debug) {
- // this test _rewrite handler
-
-
- var db = new CouchDB("test_suite_db", {"X-Couch-Full-Commit":"false"});
- db.deleteDb();
- db.createDb();
-
-
if (debug) debugger;
- run_on_modified_server(
- [{section: "httpd",
- key: "authentication_handlers",
- value: "{couch_httpd_auth, special_test_authentication_handler}"},
- {section:"httpd",
- key: "WWW-Authenticate",
- value: "X-Couch-Test-Auth"}],
+ var dbNames = ["test_suite_db", "test_suite_db/with_slashes"];
+ for (var i=0; i < dbNames.length; i++) {
+ var db = new CouchDB(dbNames[i]);
+ var dbName = encodeURIComponent(dbNames[i]);
+ db.deleteDb();
+ db.createDb();
+
+
+ run_on_modified_server(
+ [{section: "httpd",
+ key: "authentication_handlers",
+ value: "{couch_httpd_auth, special_test_authentication_handler}"},
+ {section:"httpd",
+ key: "WWW-Authenticate",
+ value: "X-Couch-Test-Auth"}],
function(){
var designDoc = {
_id:"_design/test",
language: "javascript",
- _attachments:{
- "foo.txt": {
- content_type:"text/plain",
- data: "VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRleHQ="
- }
- },
+ _attachments:{
+ "foo.txt": {
+ content_type:"text/plain",
+ data: "VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRleHQ="
+ }
+ },
rewrites: [
{
"from": "foo",
@@ -84,18 +84,18 @@ couchTests.rewrite = function(debug) {
"method": "GET"
},
{
- "from": "/welcome4/*",
- "to" : "_show/welcome3",
- "query": {
- "name": "*"
- }
+ "from": "/welcome4/*",
+ "to" : "_show/welcome3",
+ "query": {
+ "name": "*"
+ }
},
{
- "from": "/welcome5/*",
- "to" : "_show/*",
- "query": {
- "name": "*"
- }
+ "from": "/welcome5/*",
+ "to" : "_show/*",
+ "query": {
+ "name": "*"
+ }
},
{
"from": "basicView",
@@ -194,8 +194,8 @@ couchTests.rewrite = function(debug) {
if (!firstKey) firstKey = row.key;
prevKey = row.key;
send('\n<li>Key: '+row.key
- +' Value: '+row.value
- +' LineNo: '+row_number+'</li>');
+ +' Value: '+row.value
+ +' LineNo: '+row_number+'</li>');
}
return '</ul><p>FirstKey: '+ firstKey + ' LastKey: '+ prevKey+'</p>';
}),
@@ -270,7 +270,7 @@ couchTests.rewrite = function(debug) {
}
}
}
-
+
db.save(designDoc);
var docs = makeDocs(0, 10);
@@ -287,16 +287,16 @@ couchTests.rewrite = function(debug) {
db.bulkSave(docs2);
// test simple rewriting
-
- req = CouchDB.request("GET", "/test_suite_db/_design/test/_rewrite/foo");
+
+ req = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/foo");
T(req.responseText == "This is a base64 encoded text");
T(req.getResponseHeader("Content-Type") == "text/plain");
- req = CouchDB.request("GET", "/test_suite_db/_design/test/_rewrite/foo2");
+ req = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/foo2");
T(req.responseText == "This is a base64 encoded text");
T(req.getResponseHeader("Content-Type") == "text/plain");
-
+
// test POST
// hello update world
@@ -305,111 +305,111 @@ couchTests.rewrite = function(debug) {
T(resp.ok);
var docid = resp.id;
- xhr = CouchDB.request("PUT", "/test_suite_db/_design/test/_rewrite/hello/"+docid);
+ xhr = CouchDB.request("PUT", "/"+dbName+"/_design/test/_rewrite/hello/"+docid);
T(xhr.status == 201);
T(xhr.responseText == "hello doc");
T(/charset=utf-8/.test(xhr.getResponseHeader("Content-Type")))
-
+
doc = db.open(docid);
T(doc.world == "hello");
- req = CouchDB.request("GET", "/test_suite_db/_design/test/_rewrite/welcome?name=user");
+ req = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/welcome?name=user");
T(req.responseText == "Welcome user");
- req = CouchDB.request("GET", "/test_suite_db/_design/test/_rewrite/welcome/user");
+ req = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/welcome/user");
T(req.responseText == "Welcome user");
- req = CouchDB.request("GET", "/test_suite_db/_design/test/_rewrite/welcome2");
+ req = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/welcome2");
T(req.responseText == "Welcome user");
- xhr = CouchDB.request("PUT", "/test_suite_db/_design/test/_rewrite/welcome3/test");
+ xhr = CouchDB.request("PUT", "/"+dbName+"/_design/test/_rewrite/welcome3/test");
T(xhr.status == 201);
T(xhr.responseText == "New World");
T(/charset=utf-8/.test(xhr.getResponseHeader("Content-Type")));
- xhr = CouchDB.request("GET", "/test_suite_db/_design/test/_rewrite/welcome3/test");
+ xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/welcome3/test");
T(xhr.responseText == "Welcome test");
- req = CouchDB.request("GET", "/test_suite_db/_design/test/_rewrite/welcome4/user");
+ req = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/welcome4/user");
T(req.responseText == "Welcome user");
- req = CouchDB.request("GET", "/test_suite_db/_design/test/_rewrite/welcome5/welcome3");
+ req = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/welcome5/welcome3");
T(req.responseText == "Welcome welcome3");
-
- xhr = CouchDB.request("GET", "/test_suite_db/_design/test/_rewrite/basicView");
+
+ xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/basicView");
T(xhr.status == 200, "view call");
T(/{"total_rows":9/.test(xhr.responseText));
- xhr = CouchDB.request("GET", "/test_suite_db/_design/test/_rewrite/");
+ xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/");
T(xhr.status == 200, "view call");
T(/{"total_rows":9/.test(xhr.responseText));
// get with query params
- xhr = CouchDB.request("GET", "/test_suite_db/_design/test/_rewrite/simpleForm/basicView?startkey=3&endkey=8");
+ xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/simpleForm/basicView?startkey=3&endkey=8");
T(xhr.status == 200, "with query params");
T(!(/Key: 1/.test(xhr.responseText)));
T(/FirstKey: 3/.test(xhr.responseText));
T(/LastKey: 8/.test(xhr.responseText));
- xhr = CouchDB.request("GET", "/test_suite_db/_design/test/_rewrite/simpleForm/basicViewFixed");
+ xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/simpleForm/basicViewFixed");
T(xhr.status == 200, "with query params");
T(!(/Key: 1/.test(xhr.responseText)));
T(/FirstKey: 3/.test(xhr.responseText));
T(/LastKey: 8/.test(xhr.responseText));
// get with query params
- xhr = CouchDB.request("GET", "/test_suite_db/_design/test/_rewrite/simpleForm/basicViewFixed?startkey=4");
+ xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/simpleForm/basicViewFixed?startkey=4");
T(xhr.status == 200, "with query params");
T(!(/Key: 1/.test(xhr.responseText)));
T(/FirstKey: 3/.test(xhr.responseText));
T(/LastKey: 8/.test(xhr.responseText));
-
+
// get with query params
- xhr = CouchDB.request("GET", "/test_suite_db/_design/test/_rewrite/simpleForm/basicViewPath/3/8");
+ xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/simpleForm/basicViewPath/3/8");
T(xhr.status == 200, "with query params");
T(!(/Key: 1/.test(xhr.responseText)));
T(/FirstKey: 3/.test(xhr.responseText));
T(/LastKey: 8/.test(xhr.responseText));
// get with query params
- xhr = CouchDB.request("GET", "/test_suite_db/_design/test/_rewrite/simpleForm/complexView");
+ xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/simpleForm/complexView");
T(xhr.status == 200, "with query params");
T(/FirstKey: [1, 2]/.test(xhr.responseText));
- xhr = CouchDB.request("GET", "/test_suite_db/_design/test/_rewrite/simpleForm/complexView2");
+ xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/simpleForm/complexView2");
T(xhr.status == 200, "with query params");
T(/Value: doc 3/.test(xhr.responseText));
- xhr = CouchDB.request("GET", "/test_suite_db/_design/test/_rewrite/simpleForm/complexView3");
+ xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/simpleForm/complexView3");
T(xhr.status == 200, "with query params");
T(/Value: doc 4/.test(xhr.responseText));
- xhr = CouchDB.request("GET", "/test_suite_db/_design/test/_rewrite/simpleForm/complexView4");
+ xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/simpleForm/complexView4");
T(xhr.status == 200, "with query params");
T(/Value: doc 5/.test(xhr.responseText));
- xhr = CouchDB.request("GET", "/test_suite_db/_design/test/_rewrite/simpleForm/complexView5/test/essai");
+ xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/simpleForm/complexView5/test/essai");
T(xhr.status == 200, "with query params");
T(/Value: doc 4/.test(xhr.responseText));
- xhr = CouchDB.request("GET", "/test_suite_db/_design/test/_rewrite/simpleForm/complexView6?a=test&b=essai");
+ xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/simpleForm/complexView6?a=test&b=essai");
T(xhr.status == 200, "with query params");
T(/Value: doc 4/.test(xhr.responseText));
- xhr = CouchDB.request("GET", "/test_suite_db/_design/test/_rewrite/simpleForm/complexView7/test/essai?doc=true");
+ xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/simpleForm/complexView7/test/essai?doc=true");
T(xhr.status == 200, "with query params");
var result = JSON.parse(xhr.responseText);
T(typeof(result.rows[0].doc) === "object");
// test path relative to server
designDoc.rewrites.push({
- "from": "uuids",
- "to": "../../../_uuids"
+ "from": "uuids",
+ "to": "../../../_uuids"
});
T(db.save(designDoc).ok);
- var xhr = CouchDB.request("GET", "/test_suite_db/_design/test/_rewrite/uuids");
+ var xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/uuids");
T(xhr.status == 500);
var result = JSON.parse(xhr.responseText);
T(result.error == "insecure_rewrite_rule");
@@ -418,59 +418,60 @@ couchTests.rewrite = function(debug) {
[{section: "httpd",
key: "secure_rewrites",
value: "false"}],
- function() {
- var xhr = CouchDB.request("GET", "/test_suite_db/_design/test/_rewrite/uuids?cache=bust");
- T(xhr.status == 200);
- var result = JSON.parse(xhr.responseText);
- T(result.uuids.length == 1);
- var first = result.uuids[0];
- });
- });
+ function() {
+ var xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/uuids?cache=bust");
+ T(xhr.status == 200);
+ var result = JSON.parse(xhr.responseText);
+ T(result.uuids.length == 1);
+ var first = result.uuids[0];
+ });
+ });
- // test invalid rewrites
- // string
- var ddoc = {
- _id: "_design/invalid",
- rewrites: "[{\"from\":\"foo\",\"to\":\"bar\"}]"
- }
- db.save(ddoc);
- var res = CouchDB.request("GET", "/test_suite_db/_design/invalid/_rewrite/foo");
- TEquals(400, res.status, "should return 400");
+ // test invalid rewrites
+ // string
+ var ddoc = {
+ _id: "_design/invalid",
+ rewrites: "[{\"from\":\"foo\",\"to\":\"bar\"}]"
+ }
+ db.save(ddoc);
+ var res = CouchDB.request("GET", "/"+dbName+"/_design/invalid/_rewrite/foo");
+ TEquals(400, res.status, "should return 400");
- var ddoc_requested_path = {
- _id: "_design/requested_path",
- rewrites:[
+ var ddoc_requested_path = {
+ _id: "_design/requested_path",
+ rewrites:[
{"from": "show", "to": "_show/origin/0"},
{"from": "show_rewritten", "to": "_rewrite/show"}
- ],
- shows: {
+ ],
+ shows: {
origin: stringFun(function(doc, req) {
- return req.headers["x-couchdb-requested-path"];
- })}
- };
+ return req.headers["x-couchdb-requested-path"];
+ })}
+ };
- db.save(ddoc_requested_path);
- var url = "/test_suite_db/_design/requested_path/_rewrite/show";
- var res = CouchDB.request("GET", url);
- TEquals(url, res.responseText, "should return the original url");
+ db.save(ddoc_requested_path);
+ var url = "/"+dbName+"/_design/requested_path/_rewrite/show";
+ var res = CouchDB.request("GET", url);
+ TEquals(url, res.responseText, "should return the original url");
- var url = "/test_suite_db/_design/requested_path/_rewrite/show_rewritten";
- var res = CouchDB.request("GET", url);
- TEquals(url, res.responseText, "returned the original url");
+ var url = "/"+dbName+"/_design/requested_path/_rewrite/show_rewritten";
+ var res = CouchDB.request("GET", url);
+ TEquals(url, res.responseText, "returned the original url");
- var ddoc_loop = {
- _id: "_design/loop",
- rewrites: [{ "from": "loop", "to": "_rewrite/loop"}]
- };
- db.save(ddoc_loop);
+ var ddoc_loop = {
+ _id: "_design/loop",
+ rewrites: [{ "from": "loop", "to": "_rewrite/loop"}]
+ };
+ db.save(ddoc_loop);
- run_on_modified_server(
- [{section: "httpd",
- key: "rewrite_limit",
- value: "2"}],
+ run_on_modified_server(
+ [{section: "httpd",
+ key: "rewrite_limit",
+ value: "2"}],
function(){
- var url = "/test_suite_db/_design/loop/_rewrite/loop";
+ var url = "/"+dbName+"/_design/loop/_rewrite/loop";
var xhr = CouchDB.request("GET", url);
T(xhr.status = 400);
- });
+ });
+ }
}
diff --git a/src/couchdb/couch_httpd_rewrite.erl b/src/couchdb/couch_httpd_rewrite.erl
index 3e97258df..756cdefb2 100644
--- a/src/couchdb/couch_httpd_rewrite.erl
+++ b/src/couchdb/couch_httpd_rewrite.erl
@@ -116,7 +116,7 @@ handle_rewrite_req(#httpd{
% we are in a design handler
DesignId = <<"_design/", DesignName/binary>>,
- Prefix = <<"/", DbName/binary, "/", DesignId/binary>>,
+ Prefix = <<"/", (?l2b(couch_util:url_encode(DbName)))/binary, "/", DesignId/binary>>,
QueryList = lists:map(fun decode_query_value/1, couch_httpd:qs(Req)),
MaxRewritesList = couch_config:get("httpd", "rewrite_limit", "100"),