From ff1618779bc85d8f16d6aeebec461fad51b008c5 Mon Sep 17 00:00:00 2001 From: Jan Lehnardt Date: Thu, 4 Feb 2010 23:09:06 +0000 Subject: re-enable 404 handling in show functions while retaining user-friendly error behaviour git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@906721 13f79535-47bb-0310-9956-ffa450edef68 --- share/server/render.js | 6 +++++- share/www/script/test/show_documents.js | 20 ++++++++++++++++---- src/couchdb/couch_httpd_show.erl | 32 ++++++++++++++++++++++---------- 3 files changed, 43 insertions(+), 15 deletions(-) diff --git a/share/server/render.js b/share/server/render.js index 45782d76..11c76373 100644 --- a/share/server/render.js +++ b/share/server/render.js @@ -227,7 +227,11 @@ var Render = (function() { throw(["error", "render_error", "undefined response from show function"]); } } catch(e) { - renderError(e, fun.toSource()); + if(args[0] === null) { + throw(["error", "not_found", "document not found"]); + } else { + renderError(e, fun.toSource()); + } } }; diff --git a/share/www/script/test/show_documents.js b/share/www/script/test/show_documents.js index bdb1b73e..2e895838 100644 --- a/share/www/script/test/show_documents.js +++ b/share/www/script/test/show_documents.js @@ -22,10 +22,15 @@ couchTests.show_documents = function(debug) { shows: { "hello" : stringFun(function(doc, req) { log("hello fun"); + log(req); if (doc) { return "Hello World"; } else { - return "Empty World"; + if(req.id) { + return "New World"; + } else { + return "Empty World"; + } } }), "just-name" : stringFun(function(doc, req) { @@ -56,6 +61,9 @@ couchTests.show_documents = function(debug) { "empty" : stringFun(function(doc, req) { return ""; }), + "fail" : stringFun(function(doc, req) { + return doc._id; + }), "xml-type" : stringFun(function(doc, req) { return { "headers" : { @@ -161,7 +169,7 @@ couchTests.show_documents = function(debug) { T(xhr.responseText == ""); // // hello template world (non-existing docid) - xhr = CouchDB.request("GET", "/test_suite_db/_design/template/_show/hello/nonExistingDoc"); + xhr = CouchDB.request("GET", "/test_suite_db/_design/template/_show/fail/nonExistingDoc"); T(xhr.status == 404); var resp = JSON.parse(xhr.responseText); T(resp.error == "not_found"); @@ -173,8 +181,7 @@ couchTests.show_documents = function(debug) { // show with missing doc xhr = CouchDB.request("GET", "/test_suite_db/_design/template/_show/just-name/missingdoc"); T(xhr.status == 404); - var resp = JSON.parse(xhr.responseText); - T(resp.error == "not_found"); + TEquals("No such doc", xhr.responseText); // show with missing func xhr = CouchDB.request("GET", "/test_suite_db/_design/template/_show/missing/"+docid); @@ -350,5 +357,10 @@ couchTests.show_documents = function(debug) { db.save(doc3); xhr = CouchDB.request("GET", "/test_suite_db/_design/template/_show/withSlash/a/b/c"); T(xhr.status == 200); + + // hello template world (non-existing docid) + xhr = CouchDB.request("GET", "/test_suite_db/_design/template/_show/hello/nonExistingDoc"); + T(xhr.responseText == "New World"); + }; diff --git a/src/couchdb/couch_httpd_show.erl b/src/couchdb/couch_httpd_show.erl index 3e660be1..18f24e85 100644 --- a/src/couchdb/couch_httpd_show.erl +++ b/src/couchdb/couch_httpd_show.erl @@ -13,7 +13,7 @@ -module(couch_httpd_show). -export([handle_doc_show_req/3, handle_doc_update_req/3, handle_view_list_req/3, - handle_doc_show/5, handle_view_list/6, get_fun_key/3]). + handle_view_list/6, get_fun_key/3]). -include("couch_db.hrl"). @@ -23,31 +23,40 @@ start_chunked_response/3, send_error/4]). -% /db/_design/foo/show/bar/docid +% /db/_design/foo/_show/bar/docid % show converts a json doc to a response of any content-type. % it looks up the doc an then passes it to the query server. % then it sends the response from the query server to the http client. + +maybe_open_doc(Db, DocId) -> + case catch couch_httpd_db:couch_doc_open(Db, DocId, nil, [conflicts]) of + {not_found, missing} -> nil; + Doc -> Doc + end. handle_doc_show_req(#httpd{ path_parts=[_, _, _, _, ShowName, DocId] }=Req, Db, DDoc) -> + % open the doc - Doc = couch_httpd_db:couch_doc_open(Db, DocId, nil, [conflicts]), + Doc = maybe_open_doc(Db, DocId), + % we don't handle revs here b/c they are an internal api % returns 404 if there is no doc with DocId - handle_doc_show(Req, Db, DDoc, ShowName, Doc); + handle_doc_show(Req, Db, DDoc, ShowName, Doc, DocId); handle_doc_show_req(#httpd{ path_parts=[_, _, _, _, ShowName, DocId|Rest] }=Req, Db, DDoc) -> DocParts = [DocId|Rest], - DocId1 = string:join([?b2l(P)|| P <- DocParts], "/"), - + DocId1 = ?l2b(string:join([?b2l(P)|| P <- DocParts], "/")), + % open the doc - Doc = couch_httpd_db:couch_doc_open(Db, ?l2b(DocId1), nil, [conflicts]), + Doc = maybe_open_doc(Db, DocId1), + % we don't handle revs here b/c they are an internal api - % returns 404 if there is no doc with DocId - handle_doc_show(Req, Db, DDoc, ShowName, Doc); + % pass 404 docs to the show function + handle_doc_show(Req, Db, DDoc, ShowName, Doc, DocId1); handle_doc_show_req(#httpd{ path_parts=[_, _, _, _, ShowName] @@ -59,10 +68,13 @@ handle_doc_show_req(Req, _Db, _DDoc) -> send_error(Req, 404, <<"show_error">>, <<"Invalid path.">>). handle_doc_show(Req, Db, DDoc, ShowName, Doc) -> + handle_doc_show(Req, Db, DDoc, ShowName, Doc, null). + +handle_doc_show(Req, Db, DDoc, ShowName, Doc, DocId) -> % get responder for ddoc/showname CurrentEtag = show_etag(Req, Doc, DDoc, []), couch_httpd:etag_respond(Req, CurrentEtag, fun() -> - JsonReq = couch_httpd_external:json_req_obj(Req, Db), + JsonReq = couch_httpd_external:json_req_obj(Req, Db, DocId), JsonDoc = couch_query_servers:json_doc(Doc), [<<"resp">>, ExternalResp] = couch_query_servers:ddoc_prompt(DDoc, [<<"shows">>, ShowName], [JsonDoc, JsonReq]), -- cgit v1.2.3