diff options
author | Robert Newson <rnewson@apache.org> | 2012-08-31 12:16:17 +0100 |
---|---|---|
committer | Robert Newson <rnewson@apache.org> | 2012-08-31 12:22:17 +0100 |
commit | 272d641529e6cde5a24ed73e827e27ef52c87d2a (patch) | |
tree | 336a297a9d233e1260fca9db26be469dab2d2e9f | |
parent | 4067f743026fbaf8d48fe000d90a26a5c38c988a (diff) | |
download | couchdb-272d641529e6cde5a24ed73e827e27ef52c87d2a.tar.gz |
COUCHDB-1026 - encode database name when rewriting
-rw-r--r-- | CHANGES | 4 | ||||
-rw-r--r-- | NEWS | 1 | ||||
-rw-r--r-- | share/www/script/test/rewrite.js | 217 | ||||
-rw-r--r-- | src/couchdb/couch_httpd_rewrite.erl | 2 |
4 files changed, 115 insertions, 109 deletions
@@ -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 ------------- @@ -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"), |