test(emqx_bridge_webhook_SUITE): fix flakyness in test web server

This commit is contained in:
Zaiming (Stone) Shi 2023-03-07 20:53:37 +01:00
parent 93ebd59fb2
commit 26b29185b2
1 changed files with 39 additions and 16 deletions

View File

@ -59,7 +59,7 @@ start_http_server(HTTPServerConfig) ->
ct:pal("Start server\n"), ct:pal("Start server\n"),
process_flag(trap_exit, true), process_flag(trap_exit, true),
Parent = self(), Parent = self(),
{Port, Sock} = listen_on_random_port(), {ok, {Port, Sock}} = listen_on_random_port(),
Acceptor = spawn(fun() -> Acceptor = spawn(fun() ->
accept_loop(Sock, Parent, HTTPServerConfig) accept_loop(Sock, Parent, HTTPServerConfig)
end), end),
@ -76,17 +76,22 @@ listen_on_random_port() ->
case gen_tcp:listen(0, SockOpts) of case gen_tcp:listen(0, SockOpts) of
{ok, Sock} -> {ok, Sock} ->
{ok, Port} = inet:port(Sock), {ok, Port} = inet:port(Sock),
{Port, Sock}; {ok, {Port, Sock}};
{error, Reason} when Reason /= eaddrinuse -> {error, Reason} when Reason =/= eaddrinuse ->
{error, Reason} {error, Reason}
end. end.
accept_loop(Sock, Parent, HTTPServerConfig) -> accept_loop(Sock, Parent, HTTPServerConfig) ->
process_flag(trap_exit, true), process_flag(trap_exit, true),
{ok, Conn} = gen_tcp:accept(Sock), case gen_tcp:accept(Sock) of
spawn(fun() -> handle_fun_200_ok(Conn, Parent, HTTPServerConfig) end), {ok, Conn} ->
spawn(fun() -> handle_fun_200_ok(Conn, Parent, HTTPServerConfig, <<>>) end),
%%gen_tcp:controlling_process(Conn, Handler), %%gen_tcp:controlling_process(Conn, Handler),
accept_loop(Sock, Parent, HTTPServerConfig). accept_loop(Sock, Parent, HTTPServerConfig);
{error, closed} ->
%% socket owner died
ok
end.
make_response(CodeStr, Str) -> make_response(CodeStr, Str) ->
B = iolist_to_binary(Str), B = iolist_to_binary(Str),
@ -97,17 +102,21 @@ make_response(CodeStr, Str) ->
) )
). ).
handle_fun_200_ok(Conn, Parent, HTTPServerConfig) -> handle_fun_200_ok(Conn, Parent, HTTPServerConfig, Acc) ->
ResponseDelayMS = maps:get(response_delay_ms, HTTPServerConfig, 0), ResponseDelayMS = maps:get(response_delay_ms, HTTPServerConfig, 0),
ct:pal("Waiting for request~n"), ct:pal("Waiting for request~n"),
case gen_tcp:recv(Conn, 0) of case gen_tcp:recv(Conn, 0) of
{ok, ReqStr} -> {ok, ReqStr} ->
ct:pal("The http handler got request: ~p", [ReqStr]), ct:pal("The http handler got request: ~p", [ReqStr]),
Req = parse_http_request(ReqStr), case parse_http_request(<<Acc/binary, ReqStr/binary>>) of
{ok, incomplete, NewAcc} ->
handle_fun_200_ok(Conn, Parent, HTTPServerConfig, NewAcc);
{ok, Req, NewAcc} ->
timer:sleep(ResponseDelayMS), timer:sleep(ResponseDelayMS),
Parent ! {http_server, received, Req}, Parent ! {http_server, received, Req},
gen_tcp:send(Conn, make_response("200 OK", "Request OK")), gen_tcp:send(Conn, make_response("200 OK", "Request OK")),
handle_fun_200_ok(Conn, Parent, HTTPServerConfig); handle_fun_200_ok(Conn, Parent, HTTPServerConfig, NewAcc)
end;
{error, closed} -> {error, closed} ->
ct:pal("http connection closed"); ct:pal("http connection closed");
{error, Reason} -> {error, Reason} ->
@ -116,12 +125,26 @@ handle_fun_200_ok(Conn, Parent, HTTPServerConfig) ->
gen_tcp:close(Conn) gen_tcp:close(Conn)
end. end.
parse_http_request(ReqStr0) -> parse_http_request(ReqStr) ->
try
parse_http_request_assertive(ReqStr)
catch
_:_ ->
{ok, incomplete, ReqStr}
end.
parse_http_request_assertive(ReqStr0) ->
%% find body length
[_, LengthStr0] = string:split(ReqStr0, "content-length:"),
[LengthStr, _] = string:split(LengthStr0, "\r\n"),
Length = binary_to_integer(string:trim(LengthStr, both)),
%% split between multiple requests
[Method, ReqStr1] = string:split(ReqStr0, " ", leading), [Method, ReqStr1] = string:split(ReqStr0, " ", leading),
[Path, ReqStr2] = string:split(ReqStr1, " ", leading), [Path, ReqStr2] = string:split(ReqStr1, " ", leading),
[_ProtoVsn, ReqStr3] = string:split(ReqStr2, "\r\n", leading), [_ProtoVsn, ReqStr3] = string:split(ReqStr2, "\r\n", leading),
[_HeaderStr, Body] = string:split(ReqStr3, "\r\n\r\n", leading), [_HeaderStr, Rest] = string:split(ReqStr3, "\r\n\r\n", leading),
#{method => Method, path => Path, body => Body}. <<Body:Length/binary, Remain/binary>> = Rest,
{ok, #{method => Method, path => Path, body => Body}, Remain}.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Helper functions %% Helper functions