Anonymous avatar Anonymous committed ebd0496

streaming API for request body

Comments (0)

Files changed (3)

src/webmachine_request.erl

 	 raw_path/0,
 	 req_headers/0,
 	 req_body/0,
+	 stream_req_body/1,
 	 headers/0,
 	 resp_headers/0,
 	 out_headers/0,
 headers() -> req_headers().
 
 req_body() -> call(req_body).
+stream_req_body(MaxHunk) -> call({stream_req_body, MaxHunk}).
 
 resp_headers() -> call(resp_headers).
 out_headers() -> resp_headers().

src/webmachine_request_srv.erl

 		range=undefined,
 		peer=undefined,
                 reqdata=undefined,
+                bodyfetch=standard, % set to 'stream' if streaming body
 		log_data=#wm_log_data{}
 	       }).
 
     {reply, wrq:raw_path(State#state.reqdata), State};
 handle_call(req_headers, _From, State) ->
     {reply, wrq:req_headers(State#state.reqdata), State};
-handle_call(req_body, _From, State=#state{reqdata=RD}) ->
+handle_call(req_body, _From, State=#state{reqdata=RD,bodyfetch=standard}) ->
     {Body, FinalState} = case RD#wm_reqdata.req_body of
         not_fetched_yet ->
             NewState = do_recv_body(State),
             {X, State}
     end,
     {reply, Body, FinalState};
+handle_call(req_body, _From, State=#state{bodyfetch=stream}) ->
+    {reply, stream_conflict, State};
+handle_call({stream_req_body, MaxHunk}, _From, State=#state{reqdata=RD}) ->
+    {reply, do_stream_body(State, MaxHunk), State#state{bodyfetch=stream}};
 handle_call(resp_headers, _From, State) ->
     {reply, wrq:resp_headers(State#state.reqdata), State};
 handle_call(resp_redirect, _From, State) ->
         ChunkLength -> stream_chunked_body(Socket,MaxHunk,ChunkLength)
     end.
 stream_chunked_body(Socket, MaxHunk, LeftInChunk) ->
-    case MaxHunk > LeftInChunk of
+    case MaxHunk >= LeftInChunk of
         true ->
             {ok,Data1} = gen_tcp:recv(Socket,LeftInChunk,?IDLE_TIMEOUT),
             {Data1,
 -export([create/4,load_dispatch_data/6]).
 -export([method/1,version/1,peer/1,disp_path/1,path/1,raw_path/1,path_info/1,
          response_code/1,req_cookie/1,req_qs/1,req_headers/1,req_body/1,
-         resp_redirect/1,resp_headers/1,resp_body/1,
+         stream_req_body/2,resp_redirect/1,resp_headers/1,resp_body/1,
         app_root/1,path_tokens/1]).
 -export([path_info/2,get_req_header/2,do_redirect/2,fresh_resp_headers/2,
          get_resp_header/2,set_resp_header/3,set_resp_headers/2,
 
 req_headers(_RD = #wm_reqdata{req_headers=ReqH}) -> ReqH. % mochiheaders
 
-req_body(_RD = #wm_reqdata{wmreq=WMReq}) -> WMReq:req_body().
+req_body(_RD = #wm_reqdata{wmreq=WMReq}) ->
+    case WMReq:req_body() of
+        stream_conflict ->
+            erlang:error("wrq:req_body called after wrq:stream_req_body");
+        Body ->
+            Body
+    end.
+
+stream_req_body(_RD = #wm_reqdata{wmreq=WMReq}, MaxHunk) ->
+    WMReq:stream_req_body(MaxHunk).
 
 resp_redirect(_RD = #wm_reqdata{resp_redirect=true}) -> true;
 resp_redirect(_RD = #wm_reqdata{resp_redirect=false}) -> false.
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.