Question

I want to log all requests along with responses to db. I'm using hooks for that. But it looks like I can't get request body in 'onresponse' hook, it's always <<>>. In 'onrequest' hook I can get request body.

My hooks defined as:

request_hook(Req) ->
   %% All is OK: ReqBody contains what I sent:
   {ok, ReqBody, Req2} = cowboy_req:body(Req),
   io:format("request_hook: body = ~p", [ReqBody]),
   Req2.

response_hook(_Status, _Headers, _Body, Req) ->
   %% ReqBody is always <<>> at this point. Why?
   {ok, ReqBody, Req2} = cowboy_req:body(Req),
   io:format("response_hook: body = ~p", [ReqBody]),
   Req2.

Is this a bug in cowboy or normal behaviour?

I'm using the latest cowboy available at the time of writing this post (commit: aab63d605c595d8d0cd33646d13942d6cb372b60).

Was it helpful?

Solution

The latest version of Cowboy (as I know from v0.8.2) use following approach to increase performance - cowboy_req:body(Req) return Body and NewReq structure without request body. In other word it is a normal behaviour and you able to retrieve request body only once. Cowboy does not receive request body as it can be huge, body placed in socket until it became necessary (until cowboy_req:body/1 call). Also after you retrieve body, it become not available in handler. So if you want to implement logging and make body available in handler, you can save body on request to shared location and explicitly remove it on response.

request_hook(Req) ->
        %% limit max body length for security reasons
        %% here we expects that body less than 80000 bytes
        {ok, Body, Req2} = cowboy_req:body(80000, Req),
        put(req_body, Body), %% put body to process dict 
        Req2.

response_hook(RespCode, RespHeaders, RespBody, Req) ->
        ReqBody = get(req_body),
        Req2.

%% Need to cleanup body record in proc dict
%% since cowboy uses one process per several
%% requests in keepalive mode
terminate(_Reason, _Req, _St) ->
        put(req_body, undefined),                
        ok.                                        
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top