Skip to content

Commit

Permalink
provide and honor wrq:set_max_recv_body/2
Browse files Browse the repository at this point in the history
  • Loading branch information
justin@basho.com committed Jun 1, 2009
1 parent 10406dc commit 818c993
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 22 deletions.
2 changes: 1 addition & 1 deletion include/wm_reqdata.hrl
@@ -1,6 +1,6 @@
-record(wm_reqdata, {method, version, peer, wmreq,
disp_path, path, raw_path, path_info, path_tokens,
app_root,response_code,
app_root,response_code,max_recv_body,
req_cookie, req_qs, req_headers, req_body,
resp_redirect, resp_headers, resp_body
}).
Expand Down
4 changes: 2 additions & 2 deletions src/webmachine_request.erl
Expand Up @@ -31,7 +31,7 @@
path/0,
raw_path/0,
req_headers/0,
req_body/0,
req_body/1,
stream_req_body/1,
headers/0,
resp_headers/0,
Expand Down Expand Up @@ -94,7 +94,7 @@ raw_path() -> call(raw_path).
req_headers() -> call(req_headers).
headers() -> req_headers().

req_body() -> call(req_body).
req_body(MaxRevBody) -> call({req_body,MaxRevBody}).
stream_req_body(MaxHunk) -> call({stream_req_body, MaxHunk}).

resp_headers() -> call(resp_headers).
Expand Down
35 changes: 18 additions & 17 deletions src/webmachine_request_srv.erl
Expand Up @@ -28,9 +28,6 @@
-define(WMVSN, "1.3").
-define(QUIP, "scale automagically into the cloud").

% Maximum recv_body() length of 50MB
-define(MAX_RECV_BODY, (50*(1024*1024))).

% 120 second default idle timeout
-define(IDLE_TIMEOUT, infinity).
-record(state, {socket=undefined,
Expand Down Expand Up @@ -88,7 +85,9 @@ handle_call(req_headers, _From, State) ->
{reply, wrq:req_headers(State#state.reqdata), State};
handle_call(req_body, _From, State=#state{bodyfetch=stream}) ->
{reply, stream_conflict, State};
handle_call(req_body, _From, State=#state{reqdata=RD}) ->
handle_call({req_body, MaxRecvBody}, _From, State0=#state{reqdata=RD0}) ->
RD=RD0#wm_reqdata{max_recv_body=MaxRecvBody},
State=State0#state{reqdata=RD},
{Body, FinalState} = case RD#wm_reqdata.req_body of
not_fetched_yet ->
NewBody = do_recv_body(State),
Expand Down Expand Up @@ -285,8 +284,7 @@ send_ok_response(200, InitState) ->
X when X =:= undefined; X =:= fail ->
send_response(200, State);
Ranges ->
{PartList, Size} = range_parts(
wrq:resp_body(RD0), Ranges),
{PartList, Size} = range_parts(RD0, Ranges),
case PartList of
[] -> %% no valid ranges
%% could be 416, for now we'll just return 200
Expand Down Expand Up @@ -343,21 +341,23 @@ body_length(State) ->
%% @spec do_recv_body(state()) -> binary()
%% @doc Receive the body of the HTTP request (defined by Content-Length).
%% Will only receive up to the default max-body length
do_recv_body(State) ->
read_whole_stream(recv_stream_body(State, ?MAX_RECV_BODY), [], 0).
do_recv_body(State=#state{reqdata=RD}) ->
MRB = RD#wm_reqdata.max_recv_body,
read_whole_stream(recv_stream_body(State, MRB), [], MRB, 0).

read_whole_stream({Hunk,_}, _, SizeAcc)
when SizeAcc + byte_size(Hunk) > ?MAX_RECV_BODY ->
read_whole_stream({Hunk,_}, _, MaxRecvBody, SizeAcc)
when SizeAcc + byte_size(Hunk) > MaxRecvBody ->
{error, req_body_too_large};
read_whole_stream({Hunk,Next}, Acc0, SizeAcc) ->
read_whole_stream({Hunk,Next}, Acc0, MaxRecvBody, SizeAcc) ->
HunkSize = byte_size(Hunk),
if SizeAcc + HunkSize > ?MAX_RECV_BODY ->
if SizeAcc + HunkSize > MaxRecvBody ->
{error, req_body_too_large};
true ->
Acc = [Hunk|Acc0],
case Next of
done -> iolist_to_binary(lists:reverse(Acc));
_ -> read_whole_stream(Next(), Acc, SizeAcc + HunkSize)
_ -> read_whole_stream(Next(), Acc,
MaxRecvBody, SizeAcc + HunkSize)
end
end.

Expand Down Expand Up @@ -436,7 +436,7 @@ get_range(State) ->
{Range, State#state{range=Range}}
end.

range_parts({file, IoDevice}, Ranges) ->
range_parts(_RD=#wm_reqdata{resp_body={file, IoDevice}}, Ranges) ->
Size = iodevice_size(IoDevice),
F = fun (Spec, Acc) ->
case range_skip_length(Spec, Size) of
Expand All @@ -454,11 +454,12 @@ range_parts({file, IoDevice}, Ranges) ->
LocNums, Data),
{Bodies, Size};

range_parts({stream, {Hunk,Next}}, Ranges) ->
range_parts(RD=#wm_reqdata{resp_body={stream, {Hunk,Next}}}, Ranges) ->
% for now, streamed bodies are read in full for range requests
range_parts(read_whole_stream({Hunk,Next}, [], 0), Ranges);
MRB = RD#wm_reqdata.max_recv_body,
range_parts(read_whole_stream({Hunk,Next}, [], MRB, 0), Ranges);

range_parts(Body0, Ranges) ->
range_parts(_RD=#wm_reqdata{resp_body=Body0}, Ranges) ->
Body = iolist_to_binary(Body0),
Size = size(Body),
F = fun(Spec, Acc) ->
Expand Down
10 changes: 8 additions & 2 deletions src/wrq.erl
Expand Up @@ -26,6 +26,7 @@
set_disp_path/2,set_req_body/2,set_resp_body/2,set_response_code/2,
merge_resp_headers/2,remove_resp_header/2,
append_to_resp_body/2,append_to_response_body/2,
max_recv_body/1,set_max_recv_body/2,
get_cookie_value/2,get_qs_value/2,get_qs_value/3,set_peer/2]).

-include_lib("include/wm_reqdata.hrl").
Expand All @@ -39,6 +40,7 @@ create(Method,Version,RawPath,Headers) ->
req_qs=defined_in_create,
peer="defined_in_wm_req_srv_init",
req_body=not_fetched_yet,
max_recv_body=(50*(1024*1024)),
app_root="defined_in_load_dispatch_data",
path_info=dict:new(),
path_tokens=defined_in_load_dispatch_data,
Expand Down Expand Up @@ -87,12 +89,16 @@ req_qs(_RD = #wm_reqdata{req_qs=QS}) when is_list(QS) -> QS. % string

req_headers(_RD = #wm_reqdata{req_headers=ReqH}) -> ReqH. % mochiheaders

req_body(_RD = #wm_reqdata{wmreq=WMReq}) ->
maybe_conflict_body(WMReq:req_body()).
req_body(_RD = #wm_reqdata{wmreq=WMReq,max_recv_body=MRB}) ->
maybe_conflict_body(WMReq:req_body(MRB)).

stream_req_body(_RD = #wm_reqdata{wmreq=WMReq}, MaxHunk) ->
maybe_conflict_body(WMReq:stream_req_body(MaxHunk)).

max_recv_body(_RD = #wm_reqdata{max_recv_body=X}) when is_integer(X) -> X.

set_max_recv_body(X, RD) when is_integer(X) -> RD#wm_reqdata{max_recv_body=X}.

maybe_conflict_body(BodyResponse) ->
case BodyResponse of
stream_conflict ->
Expand Down

0 comments on commit 818c993

Please sign in to comment.