Skip to content

Instantly share code, notes, and snippets.

@jcomellas
Last active December 9, 2015 21:48
Show Gist options
  • Save jcomellas/adbad0b34c710f6ab642 to your computer and use it in GitHub Desktop.
Save jcomellas/adbad0b34c710f6ab642 to your computer and use it in GitHub Desktop.
Cowboy onresponse callback for common access log
%% Use the following function as onresponse callback when creating the
%% cowboy listener environment to log HTTP requests in common log format.
-define(HDR_X_FORWARDED_FOR, "x-forwarded-for").
-spec common_http_log(cowboy:status(), cowboy:headers(), iodata(), cowboy_req:req()) -> cowboy_req:req().
common_http_log(Status, _Headers, Body, Req0) ->
%% 127.0.0.1 - - [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326
[Method, Version, Path, Qs0] = cowboy_req:get([method, version, path, qs], Req0),
{{IpAddr, _Port}, Req1} = cowboy_req:peer(Req0),
Addr = inet:ntoa(IpAddr),
Datetime = calendar:now_to_universal_time(os:timestamp()),
Iso8601Date = datetime_to_iso8601(Datetime),
Qs = case Qs0 of
<<>> -> Qs0;
_ -> [$?, Qs0]
end,
Size = iolist_size(Body),
case cowboy_req:header(<<?HDR_X_FORWARDED_FOR>>, Req1) of
{undefined, Req} ->
lager:info("~s - - [~s] \"~s ~s~s ~s\" ~b ~b",
[Addr, Iso8601Date, Method, Path, Qs, Version, Status, Size]),
Req;
{ForwardedAddrs0, Req} ->
%% The X-Forwarded-For header value looks like this: "client, proxy1, proxy2".
ForwardedAddrs = [[bstr:lstrip(ForwardedAddr, $\s), <<"->">>] ||
ForwardedAddr <- binary:split(ForwardedAddrs0, <<",">>, [global, trim])],
lager:info("~s~s - - [~s] \"~s ~s~s ~s\" ~b ~b",
[iolist_to_binary(ForwardedAddrs), Addr, Iso8601Date,
Method, Path, Qs, Version, Status, Size]),
Req
end.
-spec datetime_to_iso8601(calendar:datetime()) -> binary().
datetime_to_iso8601({{_, _, _}, {_, _, _}} = Datetime) ->
datetime_to_iso8601(Datetime, <<$Z>>).
-spec datetime_to_iso8601(calendar:datetime(), Suffix :: binary()) -> binary().
datetime_to_iso8601({{Year, Month, Day}, {Hour, Min, Sec}}, Suffix) ->
ToBin = fun (I, Width) -> bstr:lpad(integer_to_binary(I), Width, $0) end,
YYYY = ToBin(Year, 4),
MM = ToBin(Month, 2),
DD = ToBin(Day, 2),
Hh = ToBin(Hour, 2),
Mm = ToBin(Min, 2),
Ss = ToBin(Sec, 2),
<<YYYY/binary, $-, MM/binary, $-, DD/binary, $T,
Hh/binary, $:, Mm/binary, $:, Ss/binary, Suffix/binary>>.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment