Commits

Anonymous committed 918e3d8

only fetch body off socket when requested, not when initializing

Comments (0)

Files changed (5)

include/wm_reqdata.hrl

--record(wm_reqdata, {method, version, peer,
+-record(wm_reqdata, {method, version, peer, wmreq,
                      disp_path, path, raw_path, path_info, path_tokens,
                      app_root,response_code,
                      req_cookie, req_qs, req_headers, req_body,

src/webmachine_mochiweb.erl

 	    spawn(LogModule, log_access, [LogData]),
 	    Req:stop();
         {Mod, ModOpts, PathTokens, Bindings, AppRoot, StringPath} ->
-	    Req:load_dispatch_data(Bindings, PathTokens, AppRoot, StringPath),
+            {ok, Pid} = webmachine_resource:start_link(Mod, ModOpts),
+	    Req:load_dispatch_data(Bindings,PathTokens,AppRoot,StringPath,Req),
 	    Req:set_metadata('resource_module', Mod),
-            {ok, Pid} = webmachine_resource:start_link(Mod, ModOpts),
             webmachine_decision_core:handle_request(Req, Pid)
     end.
 

src/webmachine_request.erl

 	 path/0,
 	 raw_path/0,
 	 req_headers/0,
+	 req_body/0,
 	 headers/0,
 	 resp_headers/0,
 	 out_headers/0,
 	 get_metadata/1,
 	 get_path_info/0,
 	 get_path_info/1,
-	 load_dispatch_data/4,
+	 load_dispatch_data/5,
 	 get_path_tokens/0,
 	 get_app_root/0,
 	 parse_cookie/0,
 req_headers() -> call(req_headers).
 headers() -> req_headers().
 
+req_body() -> call(req_body).
+
 resp_headers() -> call(resp_headers).
 out_headers() -> resp_headers().
 
 app_root() -> call(app_root).
 get_app_root() -> app_root().
 
-load_dispatch_data(Bindings, PathTokens, AppRoot, DispPath) ->
-    call({load_dispatch_data, Bindings, PathTokens, AppRoot, DispPath}).
+load_dispatch_data(Bindings, PathTokens, AppRoot, DispPath, Req) ->
+    call({load_dispatch_data, Bindings, PathTokens, AppRoot, DispPath, Req}).
 
 log_data() -> call(log_data).

src/webmachine_request_srv.erl

     %% client IP address but it will do for now.
     {Peer, State} = get_peer(#state{socket=Socket,
          reqdata=wrq:create(Method,Version,RawPath,Headers)}),
-    BodyState = do_recv_body(State#state{
-                               reqdata=wrq:set_peer(Peer,State#state.reqdata)}),
+    PeerState = State#state{reqdata=wrq:set_peer(Peer,State#state.reqdata)},
     LogData = #wm_log_data{start_time=now(),
 			   method=Method,
 			   headers=Headers,
 			   version=Version,
 			   response_code=404,
 			   response_length=0},
-    {ok, BodyState#state{log_data=LogData}}.
+    {ok, PeerState#state{log_data=LogData}}.
 
 handle_call(socket, _From, State) ->
     Reply = State#state.socket,
     {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}) ->
+    {Body, FinalState} = case RD#wm_reqdata.req_body of
+        not_fetched_yet ->
+            NewState = do_recv_body(State),
+            NewRD = NewState#state.reqdata,
+            {NewRD#wm_reqdata.req_body, NewState};
+        X ->
+            {X, State}
+    end,
+    {reply, Body, FinalState};
 handle_call(resp_headers, _From, State) ->
     {reply, wrq:resp_headers(State#state.reqdata), State};
 handle_call(resp_redirect, _From, State) ->
     {reply, wrq:req_cookie(State#state.reqdata), State};
 handle_call(req_qs, _From, State) ->
     {reply, wrq:req_qs(State#state.reqdata), State};
-handle_call({load_dispatch_data, PathProps, PathTokens, AppRoot, DispPath},
+handle_call({load_dispatch_data, PathProps,PathTokens,AppRoot,DispPath,WMReq},
             _From, State) ->
     PathInfo = dict:from_list(PathProps),
     NewState = State#state{reqdata=wrq:load_dispatch_data(
-                 PathInfo, PathTokens, AppRoot, DispPath, State#state.reqdata)},
+               PathInfo,PathTokens,AppRoot,DispPath,WMReq,State#state.reqdata)},
     {reply, ok, NewState};
 handle_call(log_data, _From, State) -> {reply, State#state.log_data, State}.
 
             {unknown_transfer_encoding, Unknown}
     end.
 
-%% @spec do_recv_body(state()) -> binary()
+%% @spec do_recv_body(state()) -> state()
 %% @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=#state{reqdata=RD}) ->
     State#state{reqdata=wrq:set_req_body(
                              do_recv_body(State, ?MAX_RECV_BODY), RD)}.
 
-%% @spec do_recv_body(state(), integer()) -> {binary(), state()}
 %% @doc Receive the body of the HTTP request (defined by Content-Length).
 %%      Will receive up to MaxBody bytes. 
 do_recv_body(State = #state{reqdata=RD}, MaxBody) ->
 -module(wrq).
 -author('Justin Sheehy <justin@basho.com>').
 
--export([create/4,load_dispatch_data/5]).
+-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,
 create(Method,Version,RawPath,Headers) ->
     create(#wm_reqdata{method=Method,version=Version,
                        raw_path=RawPath,req_headers=Headers,
+      wmreq=defined_in_load_dispatch_data,
       path="defined_in_create",
       req_cookie=defined_in_create,
       req_qs=defined_in_create,
       peer="defined_in_wm_req_srv_init",
-      req_body=defined_in_wm_req_srv_init,
+      req_body=not_fetched_yet,
       app_root="defined_in_load_dispatch_data",
       path_info=dict:new(),
       path_tokens=defined_in_load_dispatch_data,
     {_, QueryString, _} = mochiweb_util:urlsplit_path(RawPath),
     ReqQS = mochiweb_util:parse_qs(QueryString),
     RD#wm_reqdata{path=Path,req_cookie=Cookie,req_qs=ReqQS}.
-load_dispatch_data(PathInfo, PathTokens, AppRoot, DispPath, RD) ->
+load_dispatch_data(PathInfo, PathTokens, AppRoot, DispPath, WMReq, RD) ->
     RD#wm_reqdata{path_info=PathInfo,path_tokens=PathTokens,
-                 app_root=AppRoot,disp_path=DispPath}.
+                 app_root=AppRoot,disp_path=DispPath,wmreq=WMReq}.
 
 method(_RD = #wm_reqdata{method=Method}) -> Method.
 
 
 req_headers(_RD = #wm_reqdata{req_headers=ReqH}) -> ReqH. % mochiheaders
 
-req_body(_RD = #wm_reqdata{req_body=undefined}) -> undefined;
-req_body(_RD = #wm_reqdata{req_body=ReqB}) when is_binary(ReqB) -> ReqB.
+req_body(_RD = #wm_reqdata{wmreq=WMReq}) -> WMReq:req_body().
 
 resp_redirect(_RD = #wm_reqdata{resp_redirect=true}) -> true;
 resp_redirect(_RD = #wm_reqdata{resp_redirect=false}) -> false.
 get_qs_value(Key, Default, RD) when is_list(Key) ->
     proplists:get_value(Key, req_qs(RD), Default).
 
-% --
+
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.