summaryrefslogtreecommitdiff
path: root/src/mochiweb
diff options
context:
space:
mode:
authorJohn Christopher Anderson <jchris@apache.org>2009-02-13 03:55:36 +0000
committerJohn Christopher Anderson <jchris@apache.org>2009-02-13 03:55:36 +0000
commit76508853716f2c0567bb08dfb586a6f326ee54e2 (patch)
tree3826927aa79d2cb2c7ea3e3405e4c9a2538c08d6 /src/mochiweb
parentda592618240eb9b8c165905f1d9ab4c4a3665b02 (diff)
Accept standalone attachment PUTs with Transfer-Encoding: chunked
Includes a patch to mochiweb_request that is under review for inclusion upstream. git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@743971 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/mochiweb')
-rw-r--r--src/mochiweb/mochiweb_request.erl36
1 files changed, 29 insertions, 7 deletions
diff --git a/src/mochiweb/mochiweb_request.erl b/src/mochiweb/mochiweb_request.erl
index 311ed507..7fc04f8b 100644
--- a/src/mochiweb/mochiweb_request.erl
+++ b/src/mochiweb/mochiweb_request.erl
@@ -12,7 +12,7 @@
-define(READ_SIZE, 8192).
-export([get_header_value/1, get_primary_header_value/1, get/1, dump/0]).
--export([send/1, recv/1, recv/2, recv_body/0, recv_body/1]).
+-export([send/1, recv/1, recv/2, recv_body/0, recv_body/1, recv_body/3]).
-export([start_response/1, start_response_length/1, start_raw_response/1]).
-export([respond/1, ok/1]).
-export([not_found/0, not_found/1]).
@@ -171,6 +171,9 @@ recv_body() ->
%% @doc Receive the body of the HTTP request (defined by Content-Length).
%% Will receive up to MaxBody bytes.
recv_body(MaxBody) ->
+ recv_body(MaxBody, nil, nil).
+
+recv_body(MaxBody, ChunkFun, ChunkAcc) ->
case get_header_value("expect") of
"100-continue" ->
start_raw_response({100, gb_trees:empty()});
@@ -183,7 +186,15 @@ recv_body(MaxBody) ->
{unknown_transfer_encoding, Unknown} ->
exit({unknown_transfer_encoding, Unknown});
chunked ->
- read_chunked_body(MaxBody, []);
+ case ChunkFun of
+ nil ->
+ read_chunked_body(MaxBody);
+ _StreamFun ->
+ % In this case the MaxBody is actually used to
+ % determine the maximum allowed size of a single
+ % chunk.
+ stream_chunked_body(MaxBody, ChunkFun, ChunkAcc)
+ end;
0 ->
<<>>;
Length when is_integer(Length), Length =< MaxBody ->
@@ -408,15 +419,26 @@ parse_post() ->
Cached
end.
-read_chunked_body(Max, Acc) ->
+read_chunked_body(MaxBufferSize) ->
+ stream_chunked_body(MaxBufferSize, fun
+ ({0, _}, Acc) ->
+ iolist_to_binary(lists:reverse(Acc));
+ ({_Length, Bin}, Acc) ->
+ [Bin | Acc]
+ end, []).
+
+%% @spec stream_chunked_body(integer(), fun(), term()) -> term()
+%% @doc The function is called for each chunk.
+%% Used internally by read_chunked_body.
+stream_chunked_body(MaxChunkSize, Fun, FunState) ->
case read_chunk_length() of
0 ->
- read_chunk(0),
- iolist_to_binary(lists:reverse(Acc));
- Length when Length > Max ->
+ Fun({0, read_chunk(0)}, FunState);
+ Length when Length > MaxChunkSize ->
exit({body_too_large, chunked});
Length ->
- read_chunked_body(Max - Length, [read_chunk(Length) | Acc])
+ NewState = Fun({Length, read_chunk(Length)}, FunState),
+ stream_chunked_body(MaxChunkSize, Fun, NewState)
end.
%% @spec read_chunk_length() -> integer()