Anonymous avatar Anonymous committed 6159f73

provide and honor wrq:set_max_recv_body/2

Comments (0)

Files changed (4)

include/wm_reqdata.hrl

 -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
                     }).

src/webmachine_request.erl

 	 path/0,
 	 raw_path/0,
 	 req_headers/0,
-	 req_body/0,
+	 req_body/1,
 	 stream_req_body/1,
 	 headers/0,
 	 resp_headers/0,
 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).

src/webmachine_request_srv.erl

 -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,
     {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),
 	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
 %% @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.
 
 	    {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
                            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) ->
          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").
       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,
 
 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 ->
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.