From c0171495ea1cd8b552ae39a23ad584eec5190860 Mon Sep 17 00:00:00 2001 From: John Christopher Anderson Date: Fri, 17 Apr 2009 00:47:50 +0000 Subject: output errors differently during chunked responses (view and list) git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@765819 13f79535-47bb-0310-9956-ffa450edef68 --- share/server/main.js | 2 +- src/couchdb/couch_httpd.erl | 22 +++++++++++++++++++++- src/couchdb/couch_httpd_view.erl | 27 ++++++++++++++++++++++++--- 3 files changed, 46 insertions(+), 5 deletions(-) diff --git a/share/server/main.js b/share/server/main.js index b8612d41..3c59892b 100644 --- a/share/server/main.js +++ b/share/server/main.js @@ -414,7 +414,7 @@ function runRenderFunction(renderFun, args) { } catch(e) { log("function raised error: "+e.toString()); log("stacktrace: "+e.stack); - var errorMessage = "function raised error: "+e.toString()+"\nstacktrace: "+e.stack; + var errorMessage = "JavaScript function raised error: "+e.toString()+"\nSee CouchDB logfile for stacktrace."; respond({error:"render_error",reason:errorMessage}); } }; diff --git a/src/couchdb/couch_httpd.erl b/src/couchdb/couch_httpd.erl index 1e0bd9d4..a16f5fdd 100644 --- a/src/couchdb/couch_httpd.erl +++ b/src/couchdb/couch_httpd.erl @@ -21,7 +21,7 @@ -export([primary_header_value/2,partition/1,serve_file/3]). -export([start_chunked_response/3,send_chunk/2]). -export([start_json_response/2, start_json_response/3, end_json_response/1]). --export([send_response/4,send_method_not_allowed/2,send_error/4, send_redirect/2]). +-export([send_response/4,send_method_not_allowed/2,send_error/4, send_redirect/2,send_chunked_error/2]). -export([send_json/2,send_json/3,send_json/4]). -export([default_authentication_handler/1,special_test_authentication_handler/1]). -export([null_authentication_handler/1]). @@ -422,6 +422,9 @@ error_info({Error, Reason}) -> error_info(Error) -> {500, <<"unknown_error">>, couch_util:to_binary(Error)}. +send_error(_Req, {already_sent, _Error}) -> + ok; + send_error(Req, Error) -> {Code, ErrorStr, ReasonStr} = error_info(Error), if Code == 401 -> @@ -444,6 +447,23 @@ send_error(Req, Code, Headers, ErrorStr, ReasonStr) -> {[{<<"error">>, ErrorStr}, {<<"reason">>, ReasonStr}]}). +send_chunked_error(Resp, Error) -> + {Code, ErrorStr, ReasonStr} = error_info(Error), + CType = Resp:get_header_value("Content-Type"), + case CType of + "text/html" -> + HtmlError = ?l2b([$\n, + "

Error: ", ErrorStr, "

", + "
Reason: ", ReasonStr, "
", $\n]), + send_chunk(Resp, HtmlError); + _Else -> + JsonError = {[{<<"code">>, Code}, + {<<"error">>, ErrorStr}, + {<<"reason">>, ReasonStr}]}, + send_chunk(Resp, ?l2b([$\n,?JSON_ENCODE(JsonError),$\n])) + end, + send_chunk(Resp, []). + send_redirect(Req, Path) -> Headers = [{"Location", couch_httpd:absolute_uri(Req, Path)}], send_response(Req, 301, Headers, <<>>). diff --git a/src/couchdb/couch_httpd_view.erl b/src/couchdb/couch_httpd_view.erl index f5f0f5f4..e0c3f631 100644 --- a/src/couchdb/couch_httpd_view.erl +++ b/src/couchdb/couch_httpd_view.erl @@ -20,7 +20,8 @@ -import(couch_httpd, [send_json/2,send_json/3,send_json/4,send_method_not_allowed/2,send_chunk/2, - start_json_response/2, start_json_response/3, end_json_response/1]). + start_json_response/2, start_json_response/3, end_json_response/1, + send_chunked_error/2]). design_doc_view(Req, Db, Id, ViewName, Keys) -> #view_query_args{ @@ -500,7 +501,7 @@ apply_default_helper_funs(#view_fold_helper_funs{ Helpers#view_fold_helper_funs{ passed_end = PassedEnd2, start_response = StartResp2, - send_row = SendRow2 + send_row = wrap_for_chunked_errors(SendRow2) }. apply_default_helper_funs(#reduce_fold_helper_funs{ @@ -519,7 +520,7 @@ apply_default_helper_funs(#reduce_fold_helper_funs{ Helpers#reduce_fold_helper_funs{ start_response = StartResp2, - send_row = SendRow2 + send_row = wrap_for_chunked_errors(SendRow2) }. make_passed_end_fun(fwd, EndKey, EndDocId, InclusiveEnd) -> @@ -578,6 +579,26 @@ send_json_reduce_row(Resp, {Key, Value}, RowFront) -> end, send_chunk(Resp, RowFront2 ++ ?JSON_ENCODE({[{key, Key}, {value, Value}]})). +wrap_for_chunked_errors(Fun) when is_function(Fun, 3)-> + fun(Resp, B, C) -> + try Fun(Resp, B, C) + catch + throw:Error -> + send_chunked_error(Resp, Error), + throw({already_sent, Error}) + end + end; + +wrap_for_chunked_errors(Fun) when is_function(Fun, 5)-> + fun(Resp, B, C, D, E) -> + try Fun(Resp, B, C, D, E) + catch + throw:Error -> + send_chunked_error(Resp, Error), + throw({already_sent, Error}) + end + end. + view_group_etag(Group) -> view_group_etag(Group, nil). -- cgit v1.2.3