From 85e0b6da8073faa7c825e6b4c4d2ded6800c6c2b Mon Sep 17 00:00:00 2001 From: Giovanni Cappellotto Date: Wed, 3 Apr 2013 01:18:36 +0200 Subject: [PATCH] Add middleware to show better 4xx, 5xx responses Closes #46 --- src/elli_middleware.erl | 14 ++++++++++-- src/elli_middleware_error_responses.erl | 29 +++++++++++++++++++++++++ test/elli_middleware_tests.erl | 19 +++++++++++++++- 3 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 src/elli_middleware_error_responses.erl diff --git a/src/elli_middleware.erl b/src/elli_middleware.erl index fec2398..3dc69d1 100644 --- a/src/elli_middleware.erl +++ b/src/elli_middleware.erl @@ -39,8 +39,18 @@ handle(CleanReq, Config) -> Mods = mods(Config), PreReq = preprocess(CleanReq, Mods), - Res = process(PreReq, Mods), - postprocess(PreReq, Res, lists:reverse(Mods)). + try process(PreReq, Mods) of + Res -> postprocess(PreReq, Res, lists:reverse(Mods)) + catch + throw:{ResponseCode, Headers, Body} when is_integer(ResponseCode) -> + postprocess(PreReq, {ResponseCode, Headers, Body}, lists:reverse(Mods)); + throw:Exc -> + postprocess(PreReq, {500, [], <<"Internal server error">>}, lists:reverse(Mods)); + error:Error -> + postprocess(PreReq, {500, [], <<"Internal server error">>}, lists:reverse(Mods)); + exit:Exit -> + postprocess(PreReq, {500, [], <<"Internal server error">>}, lists:reverse(Mods)) + end. handle_event(elli_startup, Args, Config) -> diff --git a/src/elli_middleware_error_responses.erl b/src/elli_middleware_error_responses.erl new file mode 100644 index 0000000..368f413 --- /dev/null +++ b/src/elli_middleware_error_responses.erl @@ -0,0 +1,29 @@ +%% @doc: Add request reference to error response body as Elli middleware. +%% Postprocesses all requests and add request's unique reference to response +%% body. + +-module(elli_middleware_error_responses). +-export([postprocess/3]). + +%% +%% Postprocess handler +%% + +postprocess(Req, {ResponseCode, Headers, Body} = Res, _Args) + when is_integer(ResponseCode) -> + case is_error(ResponseCode) of + false -> + Res; + true -> + Msg = io_lib:format("~nRequest: ~p", [elli_request:to_proplist(Req)]), + {ResponseCode, Headers, [Body, Msg]} + end; +postprocess(_, Res, _) -> + Res. + +%% +%% INTERNALS +%% + +is_error(ResponseCode) -> + ResponseCode >= 400 andalso ResponseCode < 600. \ No newline at end of file diff --git a/test/elli_middleware_tests.erl b/test/elli_middleware_tests.erl index 19337c9..ccdfa9b 100644 --- a/test/elli_middleware_tests.erl +++ b/test/elli_middleware_tests.erl @@ -9,7 +9,8 @@ elli_test_() -> [ ?_test(hello_world()), ?_test(short_circuit()), - ?_test(compress()) + ?_test(compress()), + ?_test(error_responses()) ]}. %% @@ -58,6 +59,21 @@ compress() -> ?assertEqual(lists:flatten(lists:duplicate(86, "Hello World!")), body(Response3)). +error_responses() -> + {ok, Response} = httpc:request("http://localhost:3002/foobarbaz"), + ?assertEqual(404, status(Response)), + ?assertMatch({match, _Captured}, re:run(body(Response), "Not Found")), + ?assertMatch({match, _Captured}, re:run(body(Response), "Request: ")), + + {ok, Response1} = httpc:request("http://localhost:3002/crash"), + ?assertEqual(500, status(Response1)), + ?assertMatch({match, _Captured}, re:run(body(Response1), "Internal server error")), + ?assertMatch({match, _Captured}, re:run(body(Response1), "Request: ")), + + {ok, Response2} = httpc:request("http://localhost:3002/403"), + ?assertEqual(403, status(Response2)), + ?assertMatch({match, _Captured}, re:run(body(Response2), "Forbidden")), + ?assertMatch({match, _Captured}, re:run(body(Response2), "Request: ")). @@ -88,6 +104,7 @@ setup() -> {port, 514}]}, {elli_example_middleware, []}, {elli_middleware_compress, []}, + {elli_middleware_error_responses, []}, {elli_example_callback, []} ]} ],