Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Generate a uniqueish id for each request, send to client on server er…

…ror and make available to users for correlation.
  • Loading branch information...
commit 3a2220a33fe396246c2c9260c0fbeb36510c68a7 1 parent b0be967
@knutin authored
View
3  include/elli.hrl
@@ -36,7 +36,8 @@
headers :: headers(),
body :: body(),
pid :: pid(),
- socket :: inet:socket()
+ socket :: inet:socket(),
+ id :: reference()
}).
-define(EXAMPLE_CONF, [{callback, elli_example_callback},
View
34 src/elli_http.erl
@@ -122,16 +122,19 @@ handle_request(S, PrevB, Opts, {Mod, Args} = Callback) ->
{close_or_keepalive(Req, UserHeaders), B2}
end.
--spec mk_req(Method::http_method(), {PathType::atom(), RawPath::binary()}, RequestHeaders::headers(),
- RequestBody::body(), V::version(), Socket::inet:socket() | undefined,
+-spec mk_req(Method::http_method(), {PathType::atom(), RawPath::binary()},
+ RequestHeaders::headers(), RequestBody::body(),
+ V::version(), Socket::inet:socket() | undefined,
Callback::callback()) -> record(req).
mk_req(Method, RawPath, RequestHeaders, RequestBody, V, Socket, Callback) ->
{Mod, Args} = Callback,
case parse_path(RawPath) of
{ok, {Path, URL, URLArgs}} ->
+ <<Id:80/integer>> = <<(now_to_ms()):64/integer, (crypto:rand_bytes(2))/binary>>,
#req{method = Method, path = URL, args = URLArgs, version = V,
raw_path = Path, headers = RequestHeaders,
- body = RequestBody, pid = self(), socket = Socket};
+ body = RequestBody, pid = self(), socket = Socket,
+ id = Id};
{error, Reason} ->
handle_event(Mod, request_parse_error,
[{Reason, {Method, RawPath}}], Args),
@@ -223,15 +226,28 @@ execute_callback(Req, {Mod, Args}) ->
{response, ResponseCode, Headers, Body};
throw:Exc ->
handle_event(Mod, request_throw, [Req, Exc, erlang:get_stacktrace()], Args),
- {response, 500, [], <<"Internal server error">>};
+ internal_error_response(Req);
error:Error ->
handle_event(Mod, request_error, [Req, Error, erlang:get_stacktrace()], Args),
- {response, 500, [], <<"Internal server error">>};
+ internal_error_response(Req);
exit:Exit ->
handle_event(Mod, request_exit, [Req, Exit, erlang:get_stacktrace()], Args),
- {response, 500, [], <<"Internal server error">>}
+ internal_error_response(Req)
end.
+internal_error_response(Req) ->
+ Body = <<"<html>"
+ "<head><title>Internal server error</title></head>"
+ "<body>"
+ "<h1>Internal server error</h1>"
+ "<p>Request id: #", (list_to_binary(
+ integer_to_list(
+ elli_request:id(Req))))/binary, "</p>"
+ "</body>"
+ "</html>">>,
+
+ {response, 500, [], Body}.
+
handle_event(Mod, Name, EventArgs, ElliArgs) ->
try
Mod:handle_event(Name, EventArgs, ElliArgs)
@@ -563,6 +579,12 @@ get_timings() ->
[]
end, get()).
+now_to_ms() ->
+ now_to_ms(os:timestamp()).
+
+now_to_ms({MegaSecs,Secs,MicroSecs}) ->
+ (MegaSecs * 1000000 + Secs) * 1000 + MicroSecs div 1000.
+
%%
%% OPTIONS
View
2  src/elli_request.erl
@@ -19,6 +19,7 @@
, peer/1
, method/1
, body/1
+ , id/1
, get_range/1
, get_header/3
, to_proplist/1
@@ -35,6 +36,7 @@ raw_path(#req{raw_path = Path}) -> Path.
headers(#req{headers = Headers}) -> Headers.
method(#req{method = Method}) -> Method.
body(#req{body = Body}) -> Body.
+id(#req{id = Id}) -> Id.
peer(#req{socket = Socket} = Req) ->
case get_header(<<"X-Forwarded-For">>, Req, undefined) of
View
13 test/elli_tests.erl
@@ -76,8 +76,11 @@ crash() ->
{ok, Response} = httpc:request("http://localhost:3001/crash"),
?assertEqual(500, status(Response)),
?assertEqual([{"connection", "Keep-Alive"},
- {"content-length", "21"}], headers(Response)),
- ?assertEqual("Internal server error", body(Response)).
+ {"content-length", "142"}], headers(Response)),
+ ?assertNotEqual(nomatch, binary:match(list_to_binary(body(Response)),
+ <<"Internal server error">>)),
+ ?assertNotEqual(nomatch, binary:match(list_to_binary(body(Response)),
+ <<"Request id">>)).
no_compress() ->
@@ -371,7 +374,8 @@ to_proplist_test() ->
headers = [{<<"Host">>,<<"localhost:3001">>}],
body = <<>>,
pid = self(),
- socket = socket},
+ socket = socket,
+ id = 123},
Prop = [{method,'GET'},
{path,[<<"crash">>]},
@@ -381,7 +385,8 @@ to_proplist_test() ->
{headers,[{<<"Host">>,<<"localhost:3001">>}]},
{body,<<>>},
{pid,self()},
- {socket,socket}],
+ {socket,socket},
+ {id, 123}],
?assertEqual(Prop, elli_request:to_proplist(Req)).
Please sign in to comment.
Something went wrong with that request. Please try again.