feat: add `retry-after` headers to unavailable response

This commit is contained in:
Thales Macedo Garitezi 2022-10-25 15:01:05 -03:00
parent 79f2d3e9c3
commit 0eca531e64
2 changed files with 45 additions and 21 deletions

View File

@ -50,7 +50,11 @@ running_status() ->
running -> 200; running -> 200;
not_running -> 503 not_running -> 503
end, end,
{StatusCode, #{<<"content-type">> => <<"text/plain">>}, list_to_binary(Body)}; Headers = #{
<<"content-type">> => <<"text/plain">>,
<<"retry-after">> => <<"15">>
},
{StatusCode, Headers, list_to_binary(Body)};
false -> false ->
{503, #{<<"retry-after">> => <<"15">>}, <<>>} {503, #{<<"retry-after">> => <<"15">>}, <<>>}
end. end.

View File

@ -54,28 +54,43 @@ end_per_testcase(_TestCase, _Config) ->
do_request(Opts) -> do_request(Opts) ->
#{ #{
path := Path, path := Path0,
method := Method, method := Method,
headers := Headers, headers := Headers,
body := Body0 body := Body0
} = Opts, } = Opts,
URL = ?HOST ++ filename:join(Path), URL = ?HOST ++ filename:join(Path0),
{ok, #{host := Host, port := Port, path := Path}} = emqx_http_lib:uri_parse(URL),
%% we must not use `httpc' here, because it keeps retrying when it
%% receives a 503 with `retry-after' header, and there's no option
%% to stop that behavior...
{ok, Gun} = gun:open(Host, Port, #{retry => 0}),
{ok, http} = gun:await_up(Gun),
Request = Request =
fun() ->
case Body0 of case Body0 of
no_body -> {URL, Headers}; no_body -> gun:Method(Gun, Path, Headers);
{Encoding, Body} -> {URL, Headers, Encoding, Body} {_Encoding, Body} -> gun:Method(Gun, Path, Headers, Body)
end
end, end,
ct:pal("Method: ~p, Request: ~p", [Method, Request]), Ref = Request(),
case httpc:request(Method, Request, [], []) of receive
{error, socket_closed_remotely} -> {gun_response, Gun, Ref, nofin, StatusCode, Headers1} ->
{error, socket_closed_remotely}; Data = data_loop(Gun, Ref, _Acc = <<>>),
{ok, {{_, StatusCode, _}, Headers1, Body1}} -> #{status_code => StatusCode, headers => maps:from_list(Headers1), body => Data}
Body2 = after 5_000 ->
case emqx_json:safe_decode(Body1, [return_maps]) of error({timeout, Opts, process_info(self(), messages)})
{ok, Json} -> Json; end.
{error, _} -> Body1
end, data_loop(Gun, Ref, Acc) ->
{ok, #{status_code => StatusCode, headers => Headers1, body => Body2}} receive
{gun_data, Gun, Ref, nofin, Data} ->
data_loop(Gun, Ref, <<Acc/binary, Data/binary>>);
{gun_data, Gun, Ref, fin, Data} ->
gun:shutdown(Gun),
<<Acc/binary, Data/binary>>
after 5000 ->
error(timeout)
end. end.
%%--------------------------------------------------------------------------------------- %%---------------------------------------------------------------------------------------
@ -83,10 +98,10 @@ do_request(Opts) ->
%%--------------------------------------------------------------------------------------- %%---------------------------------------------------------------------------------------
t_status_ok(_Config) -> t_status_ok(_Config) ->
{ok, #{ #{
body := Resp, body := Resp,
status_code := StatusCode status_code := StatusCode
}} = do_request(#{ } = do_request(#{
method => get, method => get,
path => ["status"], path => ["status"],
headers => [], headers => [],
@ -100,10 +115,11 @@ t_status_ok(_Config) ->
ok. ok.
t_status_not_ok(_Config) -> t_status_not_ok(_Config) ->
{ok, #{ #{
body := Resp, body := Resp,
headers := Headers,
status_code := StatusCode status_code := StatusCode
}} = do_request(#{ } = do_request(#{
method => get, method => get,
path => ["status"], path => ["status"],
headers => [], headers => [],
@ -114,4 +130,8 @@ t_status_not_ok(_Config) ->
{match, _}, {match, _},
re:run(Resp, <<"emqx is not_running$">>) re:run(Resp, <<"emqx is not_running$">>)
), ),
?assertMatch(
#{<<"retry-after">> := <<"15">>},
Headers
),
ok. ok.