summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Christopher Anderson <jchris@apache.org>2009-04-17 00:47:50 +0000
committerJohn Christopher Anderson <jchris@apache.org>2009-04-17 00:47:50 +0000
commitc0171495ea1cd8b552ae39a23ad584eec5190860 (patch)
tree4ee79f4744bd1edda0215521977ce9151d8f2ec7
parent47edd9d102446e0b0b661d7cc4a7b46eae6a9a5e (diff)
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
-rw-r--r--share/server/main.js2
-rw-r--r--src/couchdb/couch_httpd.erl22
-rw-r--r--src/couchdb/couch_httpd_view.erl27
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,
+ "<html><body><h2>Error: ", ErrorStr, "</h2>",
+ "<pre>Reason: ", ReasonStr, "</pre>", $\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).