diff options
-rw-r--r-- | share/www/script/couch_tests.js | 100 | ||||
-rw-r--r-- | src/couchdb/couch_httpd.erl | 9 | ||||
-rw-r--r-- | src/couchdb/couch_httpd_db.erl | 7 |
3 files changed, 63 insertions, 53 deletions
diff --git a/share/www/script/couch_tests.js b/share/www/script/couch_tests.js index 3e2bb381..a7a341e9 100644 --- a/share/www/script/couch_tests.js +++ b/share/www/script/couch_tests.js @@ -1235,60 +1235,64 @@ var tests = { }, design_paths : function(debug) { - var db = new CouchDB("test_suite_db"); - db.deleteDb(); - db.createDb(); if (debug) debugger; - - // create a ddoc w bulk_docs - db.bulkSave([{ - _id : "_design/test", - views : { - "testing" : { - "map" : "function(){emit(1,1)}" - } - } - }]) - - // ddoc is getable - var xhr = CouchDB.request("GET", "/test_suite_db/_design/test"); - var resp = JSON.parse(xhr.responseText); - T(resp._id == "_design/test"); - - // it's at 2 urls... - var xhr = CouchDB.request("GET", "/test_suite_db/_design%2Ftest"); - var resp = JSON.parse(xhr.responseText); - T(resp._id == "_design/test"); - - // ensure that views are addressable - resp = db.view("test/testing") - T(resp.total_rows == 0) - - // create a ddoc by putting to url with raw slash - var xhr = CouchDB.request("PUT", "/test_suite_db/_design/test2",{ - body : JSON.stringify({ - _id : "_design/test2", + 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(); + + // create a ddoc w bulk_docs + db.bulkSave([{ + _id : "_design/test", views : { "testing" : { "map" : "function(){emit(1,1)}" } } - }) - }); - - // ddoc is getable - var xhr = CouchDB.request("GET", "/test_suite_db/_design/test2"); - var resp = JSON.parse(xhr.responseText); - T(resp._id == "_design/test2"); - - // it's at 2 urls... - var xhr = CouchDB.request("GET", "/test_suite_db/_design%2Ftest2"); - var resp = JSON.parse(xhr.responseText); - T(resp._id == "_design/test2"); - - // ensure that views are addressable - resp = db.view("test2/testing") - T(resp.total_rows == 0) + }]); + + // ddoc is getable + var xhr = CouchDB.request("GET", "/"+dbName+"/_design/test"); + var resp = JSON.parse(xhr.responseText); + T(resp._id == "_design/test"); + + // it's at 2 urls... + var xhr = CouchDB.request("GET", "/"+dbName+"/_design%2Ftest"); + var resp = JSON.parse(xhr.responseText); + T(resp._id == "_design/test"); + + // ensure that views are addressable + resp = db.view("test/testing") + T(resp.total_rows == 0) + + // create a ddoc by putting to url with raw slash + var xhr = CouchDB.request("PUT", "/"+dbName+"/_design/test2",{ + body : JSON.stringify({ + _id : "_design/test2", + views : { + "testing" : { + "map" : "function(){emit(1,1)}" + } + } + }) + }); + + // ddoc is getable + var xhr = CouchDB.request("GET", "/"+dbName+"/_design/test2"); + var resp = JSON.parse(xhr.responseText); + T(resp._id == "_design/test2"); + + // it's at 2 urls... + var xhr = CouchDB.request("GET", "/"+dbName+"/_design%2Ftest2"); + var resp = JSON.parse(xhr.responseText); + T(resp._id == "_design/test2"); + + // ensure that views are addressable + resp = db.view("test2/testing"); + T(resp.total_rows == 0); + }; }, content_negotiation: function(debug) { diff --git a/src/couchdb/couch_httpd.erl b/src/couchdb/couch_httpd.erl index e6b1c895..a9c7320a 100644 --- a/src/couchdb/couch_httpd.erl +++ b/src/couchdb/couch_httpd.erl @@ -16,7 +16,7 @@ -export([start_link/0, stop/0, handle_request/3]). -export([header_value/2,header_value/3,qs_value/2,qs_value/3,qs/1,path/1]). --export([verify_is_server_admin/1,unquote/1,recv/2]). +-export([verify_is_server_admin/1,unquote/1,quote/1,recv/2]). -export([parse_form/1,json_body/1,body/1,doc_etag/1]). -export([primary_header_value/2,partition/1,serve_file/3]). -export([start_chunked_response/3,send_chunk/2]). @@ -152,7 +152,9 @@ handle_request(MochiReq, UrlHandlers, DbUrlHandlers) -> try HandlerFun(HttpReq#httpd{user_ctx=AuthenticationFun(HttpReq)}) catch - _Tag:Error -> + Tag:Error -> + ?LOG_ERROR("Uncaught error in HTTP request: ~p",[{Tag, Error}]), + ?LOG_DEBUG("Stacktrace: ~p",[erlang:get_stacktrace()]), send_error(HttpReq, Error) end, @@ -241,6 +243,9 @@ path(#httpd{mochi_req=MochiReq}) -> unquote(UrlEncodedString) -> mochiweb_util:unquote(UrlEncodedString). +quote(UrlDecodedString) -> + mochiweb_util:quote_plus(UrlDecodedString). + parse_form(#httpd{mochi_req=MochiReq}) -> mochiweb_multipart:parse_form(MochiReq). diff --git a/src/couchdb/couch_httpd_db.erl b/src/couchdb/couch_httpd_db.erl index cdebb1e3..fc13622d 100644 --- a/src/couchdb/couch_httpd_db.erl +++ b/src/couchdb/couch_httpd_db.erl @@ -256,9 +256,10 @@ db_req(#httpd{path_parts=[_,<<"_admins">>]}=Req, _Db) -> % Special case to enable using an unencoded slash in the URL of design docs, % as slashes in document IDs must otherwise be URL encoded. db_req(#httpd{method='GET',mochi_req=MochiReq, path_parts=[DbName,<<"_design/",_/binary>>|_]}=Req, _Db) -> - PathFront = "/" ++ binary_to_list(DbName) ++ "/_design", - {ok, [PathFront|PathTail]} = regexp:split(MochiReq:get(raw_path),"%2F"), - RedirectTo = PathFront ++ "/" ++ mochiweb_util:join(PathTail, "%2F"), + PathFront = "/" ++ couch_httpd:quote(binary_to_list(DbName)) ++ "/", + RawSplit = regexp:split(MochiReq:get(raw_path),"_design%2F"), + {ok, [PathFront|PathTail]} = RawSplit, + RedirectTo = PathFront ++ "_design/" ++ mochiweb_util:join(PathTail, "%2F"), couch_httpd:send_response(Req, 301, [{"Location", RedirectTo}], <<>>); db_req(#httpd{path_parts=[_DbName,<<"_design">>,Name]}=Req, Db) -> |