diff options
author | John Christopher Anderson <jchris@apache.org> | 2008-12-27 03:55:18 +0000 |
---|---|---|
committer | John Christopher Anderson <jchris@apache.org> | 2008-12-27 03:55:18 +0000 |
commit | cf018e7bf9b5673a1bd885e23dac7c92ee2fe968 (patch) | |
tree | 82fc7aeb57c452d82c56b0f62ad02850e27473b3 | |
parent | 39fb8f339e7a0f19aa77e28d3ed131b786b618ce (diff) |
design docs use slashes. attachements with slashes in the name can be accessed with slashes in the url
git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@729587 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | share/www/script/couch_tests.js | 193 | ||||
-rw-r--r-- | src/couchdb/couch_httpd_db.erl | 16 |
2 files changed, 201 insertions, 8 deletions
diff --git a/share/www/script/couch_tests.js b/share/www/script/couch_tests.js index d5cd7ff9..8a00dc93 100644 --- a/share/www/script/couch_tests.js +++ b/share/www/script/couch_tests.js @@ -912,6 +912,197 @@ var tests = { }, + attachment_paths : function(debug) { + var db = new CouchDB("test_suite_db"); + db.deleteDb(); + db.createDb(); + if (debug) debugger; + + + // first just save a regular doc with an attachment that has a slash in the url. + // (also gonna run an encoding check case) + var binAttDoc = { + _id: "bin_doc", + _attachments:{ + "foo/bar.txt": { + content_type:"text/plain", + data: "VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRleHQ=" + }, + "foo%2Fbaz.txt": { + content_type:"text/plain", + data: "V2UgbGlrZSBwZXJjZW50IHR3byBGLg==" + } + } + } + + T(db.save(binAttDoc).ok); + + var xhr = CouchDB.request("GET", "/test_suite_db/bin_doc/foo/bar.txt"); + T(xhr.responseText == "This is a base64 encoded text"); + T(xhr.getResponseHeader("Content-Type") == "text/plain"); + + // lets try it with an escaped attachment id... + // weird that it's at two urls + var xhr = CouchDB.request("GET", "/test_suite_db/bin_doc/foo%2Fbar.txt"); + T(xhr.status == 200); + // xhr.responseText == "This is a base64 encoded text" + + var xhr = CouchDB.request("GET", "/test_suite_db/bin_doc/foo/baz.txt"); + T(xhr.status == 404); + + var xhr = CouchDB.request("GET", "/test_suite_db/bin_doc/foo%252Fbaz.txt"); + T(xhr.status == 200); + T(xhr.responseText == "We like percent two F."); + + // require a _rev to PUT + var xhr = CouchDB.request("PUT", "/test_suite_db/bin_doc/foo/attachment.txt", { + headers:{"Content-Type":"text/plain;charset=utf-8"}, + body:"Just some text" + }); + T(xhr.status == 412); + + var xhr = CouchDB.request("PUT", "/test_suite_db/bin_doc/foo/bar2.txt?rev=" + binAttDoc._rev, { + body:"This is no base64 encoded text", + headers:{"Content-Type": "text/plain;charset=utf-8"} + }); + T(xhr.status == 201); + var rev = JSON.parse(xhr.responseText).rev; + + binAttDoc = db.open("bin_doc"); + + T(binAttDoc._attachments["foo/bar.txt"] !== undefined); + T(binAttDoc._attachments["foo%2Fbaz.txt"] !== undefined); + T(binAttDoc._attachments["foo/bar2.txt"] !== undefined); + T(binAttDoc._attachments["foo/bar2.txt"].content_type == "text/plain;charset=utf-8"); + T(binAttDoc._attachments["foo/bar2.txt"].length == 30); + + //// now repeat the while thing with a design doc + + // first just save a regular doc with an attachment that has a slash in the url. + // (also gonna run an encoding check case) + var binAttDoc = { + _id: "_design/bin_doc", + _attachments:{ + "foo/bar.txt": { + content_type:"text/plain", + data: "VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRleHQ=" + }, + "foo%2Fbaz.txt": { + content_type:"text/plain", + data: "V2UgbGlrZSBwZXJjZW50IHR3byBGLg==" + } + } + } + + T(db.save(binAttDoc).ok); + + var xhr = CouchDB.request("GET", "/test_suite_db/_design%2Fbin_doc/foo/bar.txt"); + T(xhr.responseText == "This is a base64 encoded text"); + T(xhr.getResponseHeader("Content-Type") == "text/plain"); + + // lets try it with an escaped attachment id... + // weird that it's at two urls + var xhr = CouchDB.request("GET", "/test_suite_db/_design%2Fbin_doc/foo%2Fbar.txt"); + T(xhr.responseText == "This is a base64 encoded text"); + T(xhr.status == 200); + + // err, 3 urls + var xhr = CouchDB.request("GET", "/test_suite_db/_design/bin_doc/foo%2Fbar.txt"); + T(xhr.responseText == "This is a base64 encoded text"); + T(xhr.status == 200); + + // I mean um, 4 urls + var xhr = CouchDB.request("GET", "/test_suite_db/_design/bin_doc/foo/bar.txt"); + T(xhr.responseText == "This is a base64 encoded text"); + T(xhr.status == 200); + + var xhr = CouchDB.request("GET", "/test_suite_db/_design%2Fbin_doc/foo/baz.txt"); + T(xhr.status == 404); + + var xhr = CouchDB.request("GET", "/test_suite_db/_design%2Fbin_doc/foo%252Fbaz.txt"); + T(xhr.status == 200); + T(xhr.responseText == "We like percent two F."); + + // require a _rev to PUT + var xhr = CouchDB.request("PUT", "/test_suite_db/_design%2Fbin_doc/foo/attachment.txt", { + headers:{"Content-Type":"text/plain;charset=utf-8"}, + body:"Just some text" + }); + T(xhr.status == 412); + + var xhr = CouchDB.request("PUT", "/test_suite_db/_design%2Fbin_doc/foo/bar2.txt?rev=" + binAttDoc._rev, { + body:"This is no base64 encoded text", + headers:{"Content-Type": "text/plain;charset=utf-8"} + }); + T(xhr.status == 201); + var rev = JSON.parse(xhr.responseText).rev; + + binAttDoc = db.open("_design/bin_doc"); + + T(binAttDoc._attachments["foo/bar.txt"] !== undefined); + T(binAttDoc._attachments["foo/bar2.txt"] !== undefined); + T(binAttDoc._attachments["foo/bar2.txt"].content_type == "text/plain;charset=utf-8"); + T(binAttDoc._attachments["foo/bar2.txt"].length == 30); + + }, + + 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", + 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) + }, + content_negotiation: function(debug) { var db = new CouchDB("test_suite_db"); db.deleteDb(); @@ -950,7 +1141,7 @@ var tests = { } var designDoc = { - _id:"_design/test", + _id:"_design/test", // turn off couch.js id escaping? language: "javascript", views: { all_docs_twice: {map: "function(doc) { emit(doc.integer, null); emit(doc.integer, null) }"}, diff --git a/src/couchdb/couch_httpd_db.erl b/src/couchdb/couch_httpd_db.erl index 119c20ee..16956a86 100644 --- a/src/couchdb/couch_httpd_db.erl +++ b/src/couchdb/couch_httpd_db.erl @@ -243,7 +243,7 @@ db_req(#httpd{method='GET',path_parts=[_,<<"_admins">>]}=Req, Db) -> db_req(#httpd{path_parts=[_,<<"_admins">>]}=Req, _Db) -> send_method_not_allowed(Req, "PUT,GET"); -db_req(#httpd{method='POST',path_parts=[DbName,<<"_design">>,Name|Rest]}=Req, +db_req(#httpd{path_parts=[DbName,<<"_design">>,Name|Rest]}=Req, Db) -> % Special case to enable using an unencoded in the URL of design docs, as % slashes in document IDs must otherwise be URL encoded @@ -252,8 +252,8 @@ db_req(#httpd{method='POST',path_parts=[DbName,<<"_design">>,Name|Rest]}=Req, db_req(#httpd{path_parts=[_, DocId]}=Req, Db) -> db_doc_req(Req, Db, DocId); -db_req(#httpd{path_parts=[_, DocId, FileName]}=Req, Db) -> - db_attachment_req(Req, Db, DocId, FileName). +db_req(#httpd{path_parts=[_, DocId | FileNameParts]}=Req, Db) -> + db_attachment_req(Req, Db, DocId, FileNameParts). all_docs_view(Req, Db, Keys) -> #view_query_args{ @@ -510,7 +510,8 @@ couch_doc_open(Db, DocId, Rev, Options) -> % Attachment request handlers -db_attachment_req(#httpd{method='GET'}=Req, Db, DocId, FileName) -> +db_attachment_req(#httpd{method='GET'}=Req, Db, DocId, FileNameParts) -> + FileName = list_to_binary(mochiweb_util:join(lists:map(fun binary_to_list/1, FileNameParts),"/")), case couch_db:open_doc(Db, DocId, []) of {ok, #doc{attachments=Attachments}} -> case proplists:get_value(FileName, Attachments) of @@ -539,9 +540,10 @@ db_attachment_req(#httpd{method='GET'}=Req, Db, DocId, FileName) -> throw(Error) end; -db_attachment_req(#httpd{method=Method}=Req, Db, DocId, FileName) - when (Method == 'PUT') or (Method == 'DELETE') -> +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),"/")), NewAttachment = case Method of 'DELETE' -> []; @@ -573,7 +575,7 @@ db_attachment_req(#httpd{method=Method}=Req, Db, DocId, FileName) {rev, UpdatedRev} ]}); -db_attachment_req(Req, _Db, _DocId, _FileName) -> +db_attachment_req(Req, _Db, _DocId, _FileNameParts) -> send_method_not_allowed(Req, "DELETE,GET,HEAD,PUT"). |