summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien F. Katz <damien@apache.org>2009-10-27 21:40:25 +0000
committerDamien F. Katz <damien@apache.org>2009-10-27 21:40:25 +0000
commitcbd893d573e2b37baa50528f2d4a639f885ebefa (patch)
tree684c60c516e3a91d3e0da949c2d1496eadb7921b
parent8fbe7fa7b6ad515c456e21ba41d55dccd52ac3c6 (diff)
Make it harder to accidently terminate chunked resposnes by requiring callers to explicity call last_chunk(Req) and ignoring send_chunk calls with no data.
git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@830353 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--src/couchdb/couch_httpd.erl18
-rw-r--r--src/couchdb/couch_httpd_misc_handlers.erl4
-rw-r--r--src/couchdb/couch_httpd_show.erl4
3 files changed, 16 insertions, 10 deletions
diff --git a/src/couchdb/couch_httpd.erl b/src/couchdb/couch_httpd.erl
index b28486fa..9ad39e2d 100644
--- a/src/couchdb/couch_httpd.erl
+++ b/src/couchdb/couch_httpd.erl
@@ -23,7 +23,7 @@
-export([start_response_length/4, send/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,send_chunked_error/2]).
--export([send_json/2,send_json/3,send_json/4]).
+-export([send_json/2,send_json/3,send_json/4,last_chunk/1]).
start_link() ->
% read config and register for configuration changes
@@ -422,7 +422,14 @@ start_chunked_response(#httpd{mochi_req=MochiReq}=Req, Code, Headers) ->
{ok, Resp}.
send_chunk(Resp, Data) ->
- Resp:write_chunk(Data),
+ case iolist_size(Data) of
+ 0 -> ok; % do nothing
+ _ -> Resp:write_chunk(Data)
+ end,
+ {ok, Resp}.
+
+last_chunk(Resp) ->
+ Resp:write_chunk([]),
{ok, Resp}.
send_response(#httpd{mochi_req=MochiReq}=Req, Code, Headers, Body) ->
@@ -473,8 +480,7 @@ start_json_response(Req, Code, Headers) ->
end_json_response(Resp) ->
send_chunk(Resp, end_jsonp() ++ [$\n]),
- %send_chunk(Resp, [$\n]),
- send_chunk(Resp, []).
+ last_chunk(Resp).
start_jsonp(Req) ->
case get(jsonp) of
@@ -586,7 +592,7 @@ send_error(Req, Code, Headers, ErrorStr, ReasonStr) ->
% give the option for list functions to output html or other raw errors
send_chunked_error(Resp, {_Error, {[{<<"body">>, Reason}]}}) ->
send_chunk(Resp, Reason),
- send_chunk(Resp, []);
+ last_chunk(Resp);
send_chunked_error(Resp, Error) ->
{Code, ErrorStr, ReasonStr} = error_info(Error),
@@ -594,7 +600,7 @@ send_chunked_error(Resp, Error) ->
{<<"error">>, ErrorStr},
{<<"reason">>, ReasonStr}]},
send_chunk(Resp, ?l2b([$\n,?JSON_ENCODE(JsonError),$\n])),
- send_chunk(Resp, []).
+ last_chunk(Resp).
send_redirect(Req, Path) ->
Headers = [{"Location", couch_httpd:absolute_uri(Req, Path)}],
diff --git a/src/couchdb/couch_httpd_misc_handlers.erl b/src/couchdb/couch_httpd_misc_handlers.erl
index 7e2d9ea2..fb761f5b 100644
--- a/src/couchdb/couch_httpd_misc_handlers.erl
+++ b/src/couchdb/couch_httpd_misc_handlers.erl
@@ -24,7 +24,7 @@
-import(couch_httpd,
[send_json/2,send_json/3,send_json/4,send_method_not_allowed/2,
- start_json_response/2,send_chunk/2,end_json_response/1,
+ start_json_response/2,send_chunk/2,last_chunk/1,end_json_response/1,
start_chunked_response/3, send_error/4]).
% httpd global handlers
@@ -203,7 +203,7 @@ handle_log_req(#httpd{method='GET'}=Req) ->
{"Content-Length", integer_to_list(length(Chunk))}
]),
send_chunk(Resp, Chunk),
- send_chunk(Resp, "");
+ last_chunk(Resp);
handle_log_req(Req) ->
send_method_not_allowed(Req, "GET").
diff --git a/src/couchdb/couch_httpd_show.erl b/src/couchdb/couch_httpd_show.erl
index 896c833e..fe8e2002 100644
--- a/src/couchdb/couch_httpd_show.erl
+++ b/src/couchdb/couch_httpd_show.erl
@@ -19,7 +19,7 @@
-import(couch_httpd,
[send_json/2,send_json/3,send_json/4,send_method_not_allowed/2,
- start_json_response/2,send_chunk/2,send_chunked_error/2,
+ start_json_response/2,send_chunk/2,last_chunk/1,send_chunked_error/2,
start_chunked_response/3, send_error/4]).
handle_doc_show_req(#httpd{
@@ -365,7 +365,7 @@ finish_list(Req, QueryServer, Etag, FoldResult, StartFun, TotalRows) ->
[<<"end">>, Chunks] = couch_query_servers:render_list_tail(QueryServer),
send_non_empty_chunk(Resp, ?b2l(?l2b(Chunks)))
end,
- send_chunk(Resp, []).
+ last_chunk(Resp).
render_head_for_empty_list(StartListRespFun, Req, Etag, null) ->