From 446735bf7d60831b800275e3bb85251e4d6f8e38 Mon Sep 17 00:00:00 2001 From: Jan Lehnardt Date: Wed, 4 Mar 2009 00:15:07 +0000 Subject: allow for handling 404s in document show functions git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@749852 13f79535-47bb-0310-9956-ffa450edef68 --- src/couchdb/couch_httpd_db.erl | 17 ++++++++++++----- src/couchdb/couch_httpd_show.erl | 16 ++++++++-------- src/couchdb/couch_query_servers.erl | 18 ++++++++++++------ 3 files changed, 32 insertions(+), 19 deletions(-) (limited to 'src/couchdb') diff --git a/src/couchdb/couch_httpd_db.erl b/src/couchdb/couch_httpd_db.erl index 524b52b4..1bd853f3 100644 --- a/src/couchdb/couch_httpd_db.erl +++ b/src/couchdb/couch_httpd_db.erl @@ -13,7 +13,7 @@ -module(couch_httpd_db). -include("couch_db.hrl"). --export([handle_request/1, db_req/2, couch_doc_open/4]). +-export([handle_request/1, db_req/2, couch_doc_open/4, couch_doc_open/5]). -import(couch_httpd, [send_json/2,send_json/3,send_json/4,send_method_not_allowed/2, @@ -538,20 +538,27 @@ db_doc_req(Req, _Db, _DocId) -> % couch_doc_open(Db, DocId, [], []). couch_doc_open(Db, DocId, Rev, Options) -> + couch_doc_open(Db, DocId, Rev, Options, true). + +couch_doc_open(Db, DocId, Rev, Options, Throw) -> case Rev of "" -> % open most recent rev case couch_db:open_doc(Db, DocId, Options) of {ok, Doc} -> Doc; - Error -> - throw(Error) + Error when Throw -> + throw(Error); + _ -> + nil end; _ -> % open a specific rev (deletions come back as stubs) case couch_db:open_doc_revs(Db, DocId, [Rev], Options) of {ok, [{ok, Doc}]} -> Doc; - {ok, [Else]} -> - throw(Else) + {ok, [Else]} when Throw -> + throw(Else); + {ok, _} -> + nil end end. diff --git a/src/couchdb/couch_httpd_show.erl b/src/couchdb/couch_httpd_show.erl index 09484a3c..475f9ae2 100644 --- a/src/couchdb/couch_httpd_show.erl +++ b/src/couchdb/couch_httpd_show.erl @@ -24,14 +24,14 @@ handle_doc_show_req(#httpd{ method='GET', - path_parts=[_, _, DesignName, ShowName, Docid] + path_parts=[_, _, DesignName, ShowName, DocId] }=Req, Db) -> DesignId = <<"_design/", DesignName/binary>>, #doc{body={Props}} = couch_httpd_db:couch_doc_open(Db, DesignId, [], []), Lang = proplists:get_value(<<"language">>, Props, <<"javascript">>), ShowSrc = get_nested_json_value({Props}, [<<"shows">>, ShowName]), - Doc = couch_httpd_db:couch_doc_open(Db, Docid, [], []), - send_doc_show_response(Lang, ShowSrc, Doc, Req, Db); + Doc = couch_httpd_db:couch_doc_open(Db, DocId, [], [], false), + send_doc_show_response(Lang, ShowSrc, DocId, Doc, Req, Db); handle_doc_show_req(#httpd{ method='GET', @@ -41,7 +41,7 @@ handle_doc_show_req(#httpd{ #doc{body={Props}} = couch_httpd_db:couch_doc_open(Db, DesignId, [], []), Lang = proplists:get_value(<<"language">>, Props, <<"javascript">>), ShowSrc = get_nested_json_value({Props}, [<<"shows">>, ShowName]), - send_doc_show_response(Lang, ShowSrc, nil, Req, Db); + send_doc_show_response(Lang, ShowSrc, nil, nil, Req, Db); handle_doc_show_req(#httpd{method='GET'}=Req, _Db) -> send_error(Req, 404, <<"show_error">>, <<"Invalid path.">>); @@ -257,7 +257,7 @@ finish_list(Req, Db, QueryServer, Etag, FoldResult, StartListRespFun, TotalRows) throw(Error) end. -send_doc_show_response(Lang, ShowSrc, nil, #httpd{mochi_req=MReq}=Req, Db) -> +send_doc_show_response(Lang, ShowSrc, DocId, nil, #httpd{mochi_req=MReq}=Req, Db) -> % compute etag with no doc Headers = MReq:get(headers), Hlist = mochiweb_headers:to_list(Headers), @@ -265,12 +265,12 @@ send_doc_show_response(Lang, ShowSrc, nil, #httpd{mochi_req=MReq}=Req, Db) -> CurrentEtag = couch_httpd:make_etag({Lang, ShowSrc, nil, Accept}), couch_httpd:etag_respond(Req, CurrentEtag, fun() -> ExternalResp = couch_query_servers:render_doc_show(Lang, ShowSrc, - nil, Req, Db), + DocId, nil, Req, Db), JsonResp = apply_etag(ExternalResp, CurrentEtag), couch_httpd_external:send_external_response(Req, JsonResp) end); -send_doc_show_response(Lang, ShowSrc, #doc{revs=[DocRev|_]}=Doc, +send_doc_show_response(Lang, ShowSrc, DocId, #doc{revs=[DocRev|_]}=Doc, #httpd{mochi_req=MReq}=Req, Db) -> % calculate the etag Headers = MReq:get(headers), @@ -280,7 +280,7 @@ send_doc_show_response(Lang, ShowSrc, #doc{revs=[DocRev|_]}=Doc, % We know our etag now couch_httpd:etag_respond(Req, CurrentEtag, fun() -> ExternalResp = couch_query_servers:render_doc_show(Lang, ShowSrc, - Doc, Req, Db), + DocId, Doc, Req, Db), JsonResp = apply_etag(ExternalResp, CurrentEtag), couch_httpd_external:send_external_response(Req, JsonResp) end). diff --git a/src/couchdb/couch_query_servers.erl b/src/couchdb/couch_query_servers.erl index a33ffada..4ff69a2d 100644 --- a/src/couchdb/couch_query_servers.erl +++ b/src/couchdb/couch_query_servers.erl @@ -18,7 +18,9 @@ -export([init/1, terminate/2, handle_call/3, handle_cast/2, handle_info/2,code_change/3,stop/0]). -export([start_doc_map/2, map_docs/2, stop_doc_map/1]). -export([reduce/3, rereduce/3,validate_doc_update/5]). --export([render_doc_show/5,start_view_list/2,render_list_head/5, render_list_row/4, render_list_tail/3, render_reduce_head/3, render_reduce_row/4]). +-export([render_doc_show/6,start_view_list/2,render_list_head/5, + render_list_row/4, render_list_tail/3, render_reduce_head/3, + render_reduce_row/4]). % -export([test/0]). -include("couch_db.hrl"). @@ -122,14 +124,18 @@ validate_doc_update(Lang, FunSrc, EditDoc, DiskDoc, Ctx) -> after ok = ret_os_process(Lang, Pid) end. +append_docid(DocId, JsonReqIn) -> + [{<<"docId">>, DocId} | JsonReqIn]. -render_doc_show(Lang, ShowSrc, Doc, Req, Db) -> +render_doc_show(Lang, ShowSrc, DocId, Doc, Req, Db) -> Pid = get_os_process(Lang), - JsonDoc = case Doc of - nil -> null; - _ -> couch_doc:to_json_obj(Doc, [revs]) + {JsonReqIn} = couch_httpd_external:json_req_obj(Req, Db), + + {JsonReq, JsonDoc} = case {DocId, Doc} of + {nil, nil} -> {{JsonReqIn}, null}; + {DocId, nil} -> {{append_docid(DocId, JsonReqIn)}, null}; + _ -> {{append_docid(DocId, JsonReqIn)}, couch_doc:to_json_obj(Doc, [revs])} end, - JsonReq = couch_httpd_external:json_req_obj(Req, Db), try couch_os_process:prompt(Pid, [<<"show_doc">>, ShowSrc, JsonDoc, JsonReq]) of FormResp -> -- cgit v1.2.3