mirror of
https://github.com/ninenines/cowboy.git
synced 2025-07-14 20:30:23 +00:00
Move some tests out of the old HTTP test suite
And additional minor tweaks.
This commit is contained in:
parent
9e852b4dd2
commit
dc240adc1e
4 changed files with 154 additions and 126 deletions
|
@ -152,6 +152,8 @@ raw_recv_head(Socket, Transport, Buffer) ->
|
||||||
raw_recv({raw_client, Socket, Transport}, Length, Timeout) ->
|
raw_recv({raw_client, Socket, Transport}, Length, Timeout) ->
|
||||||
Transport:recv(Socket, Length, Timeout).
|
Transport:recv(Socket, Length, Timeout).
|
||||||
|
|
||||||
|
raw_expect_recv({raw_client, _, _}, <<>>) ->
|
||||||
|
ok;
|
||||||
raw_expect_recv({raw_client, Socket, Transport}, Expect) ->
|
raw_expect_recv({raw_client, Socket, Transport}, Expect) ->
|
||||||
{ok, Expect} = Transport:recv(Socket, iolist_size(Expect), 10000),
|
{ok, Expect} = Transport:recv(Socket, iolist_size(Expect), 10000),
|
||||||
ok.
|
ok.
|
||||||
|
|
|
@ -25,13 +25,12 @@ all() -> [{group, clear}].
|
||||||
|
|
||||||
groups() -> [{clear, [parallel], ct_helper:all(?MODULE)}].
|
groups() -> [{clear, [parallel], ct_helper:all(?MODULE)}].
|
||||||
|
|
||||||
init_routes(_) -> [
|
init_dispatch(_) ->
|
||||||
{"localhost", [
|
cowboy_router:compile([{"localhost", [
|
||||||
{"/", hello_h, []},
|
{"/", hello_h, []},
|
||||||
{"/echo/:key", echo_h, []},
|
{"/echo/:key", echo_h, []},
|
||||||
{"/resp_iolist_body", resp_iolist_body_h, []}
|
{"/resp_iolist_body", resp_iolist_body_h, []}
|
||||||
]}
|
]}]).
|
||||||
].
|
|
||||||
|
|
||||||
%% Do a prior knowledge handshake (function originally copied from rfc7540_SUITE).
|
%% Do a prior knowledge handshake (function originally copied from rfc7540_SUITE).
|
||||||
do_handshake(Config) ->
|
do_handshake(Config) ->
|
||||||
|
@ -53,7 +52,7 @@ do_handshake(Settings, Config) ->
|
||||||
idle_timeout(Config) ->
|
idle_timeout(Config) ->
|
||||||
doc("Terminate when the idle timeout is reached."),
|
doc("Terminate when the idle timeout is reached."),
|
||||||
ProtoOpts = #{
|
ProtoOpts = #{
|
||||||
env => #{dispatch => cowboy_router:compile(init_routes(Config))},
|
env => #{dispatch => init_dispatch(Config)},
|
||||||
idle_timeout => 1000
|
idle_timeout => 1000
|
||||||
},
|
},
|
||||||
{ok, _} = cowboy:start_clear(?FUNCTION_NAME, [{port, 0}], ProtoOpts),
|
{ok, _} = cowboy:start_clear(?FUNCTION_NAME, [{port, 0}], ProtoOpts),
|
||||||
|
@ -70,7 +69,7 @@ idle_timeout(Config) ->
|
||||||
idle_timeout_infinity(Config) ->
|
idle_timeout_infinity(Config) ->
|
||||||
doc("Ensure the idle_timeout option accepts the infinity value."),
|
doc("Ensure the idle_timeout option accepts the infinity value."),
|
||||||
ProtoOpts = #{
|
ProtoOpts = #{
|
||||||
env => #{dispatch => cowboy_router:compile(init_routes(Config))},
|
env => #{dispatch => init_dispatch(Config)},
|
||||||
idle_timeout => infinity
|
idle_timeout => infinity
|
||||||
},
|
},
|
||||||
{ok, _} = cowboy:start_clear(?FUNCTION_NAME, [{port, 0}], ProtoOpts),
|
{ok, _} = cowboy:start_clear(?FUNCTION_NAME, [{port, 0}], ProtoOpts),
|
||||||
|
@ -87,7 +86,7 @@ idle_timeout_infinity(Config) ->
|
||||||
idle_timeout_reset_on_data(Config) ->
|
idle_timeout_reset_on_data(Config) ->
|
||||||
doc("Terminate when the idle timeout is reached."),
|
doc("Terminate when the idle timeout is reached."),
|
||||||
ProtoOpts = #{
|
ProtoOpts = #{
|
||||||
env => #{dispatch => cowboy_router:compile(init_routes(Config))},
|
env => #{dispatch => init_dispatch(Config)},
|
||||||
idle_timeout => 1000
|
idle_timeout => 1000
|
||||||
},
|
},
|
||||||
{ok, _} = cowboy:start_clear(?FUNCTION_NAME, [{port, 0}], ProtoOpts),
|
{ok, _} = cowboy:start_clear(?FUNCTION_NAME, [{port, 0}], ProtoOpts),
|
||||||
|
@ -116,7 +115,7 @@ idle_timeout_reset_on_data(Config) ->
|
||||||
inactivity_timeout(Config) ->
|
inactivity_timeout(Config) ->
|
||||||
doc("Terminate when the inactivity timeout is reached."),
|
doc("Terminate when the inactivity timeout is reached."),
|
||||||
ProtoOpts = #{
|
ProtoOpts = #{
|
||||||
env => #{dispatch => cowboy_router:compile(init_routes(Config))},
|
env => #{dispatch => init_dispatch(Config)},
|
||||||
inactivity_timeout => 1000
|
inactivity_timeout => 1000
|
||||||
},
|
},
|
||||||
{ok, _} = cowboy:start_clear(?FUNCTION_NAME, [{port, 0}], ProtoOpts),
|
{ok, _} = cowboy:start_clear(?FUNCTION_NAME, [{port, 0}], ProtoOpts),
|
||||||
|
@ -135,7 +134,7 @@ initial_connection_window_size(Config) ->
|
||||||
"connection window is larger than the default."),
|
"connection window is larger than the default."),
|
||||||
ConfiguredSize = 100000,
|
ConfiguredSize = 100000,
|
||||||
ProtoOpts = #{
|
ProtoOpts = #{
|
||||||
env => #{dispatch => cowboy_router:compile(init_routes(Config))},
|
env => #{dispatch => init_dispatch(Config)},
|
||||||
initial_connection_window_size => ConfiguredSize
|
initial_connection_window_size => ConfiguredSize
|
||||||
},
|
},
|
||||||
{ok, _} = cowboy:start_clear(?FUNCTION_NAME, [{port, 0}], ProtoOpts),
|
{ok, _} = cowboy:start_clear(?FUNCTION_NAME, [{port, 0}], ProtoOpts),
|
||||||
|
@ -159,7 +158,7 @@ max_frame_size_sent(Config) ->
|
||||||
"by the max_frame_size_sent configuration value."),
|
"by the max_frame_size_sent configuration value."),
|
||||||
MaxFrameSize = 20000,
|
MaxFrameSize = 20000,
|
||||||
ProtoOpts = #{
|
ProtoOpts = #{
|
||||||
env => #{dispatch => cowboy_router:compile(init_routes(Config))},
|
env => #{dispatch => init_dispatch(Config)},
|
||||||
max_frame_size_sent => MaxFrameSize
|
max_frame_size_sent => MaxFrameSize
|
||||||
},
|
},
|
||||||
{ok, _} = cowboy:start_clear(?FUNCTION_NAME, [{port, 0}], ProtoOpts),
|
{ok, _} = cowboy:start_clear(?FUNCTION_NAME, [{port, 0}], ProtoOpts),
|
||||||
|
@ -200,7 +199,7 @@ max_frame_size_sent(Config) ->
|
||||||
preface_timeout_infinity(Config) ->
|
preface_timeout_infinity(Config) ->
|
||||||
doc("Ensure infinity for preface_timeout is accepted."),
|
doc("Ensure infinity for preface_timeout is accepted."),
|
||||||
ProtoOpts = #{
|
ProtoOpts = #{
|
||||||
env => #{dispatch => cowboy_router:compile(init_routes(Config))},
|
env => #{dispatch => init_dispatch(Config)},
|
||||||
preface_timeout => infinity
|
preface_timeout => infinity
|
||||||
},
|
},
|
||||||
{ok, _} = cowboy:start_clear(?FUNCTION_NAME, [{port, 0}], ProtoOpts),
|
{ok, _} = cowboy:start_clear(?FUNCTION_NAME, [{port, 0}], ProtoOpts),
|
||||||
|
@ -224,7 +223,7 @@ resp_iolist_body(Config) ->
|
||||||
"include improper lists, empty lists and empty binaries. "
|
"include improper lists, empty lists and empty binaries. "
|
||||||
"The original issue failed to split the body into frames properly."),
|
"The original issue failed to split the body into frames properly."),
|
||||||
ProtoOpts = #{
|
ProtoOpts = #{
|
||||||
env => #{dispatch => cowboy_router:compile(init_routes(Config))}
|
env => #{dispatch => init_dispatch(Config)}
|
||||||
},
|
},
|
||||||
{ok, _} = cowboy:start_clear(?FUNCTION_NAME, [{port, 0}], ProtoOpts),
|
{ok, _} = cowboy:start_clear(?FUNCTION_NAME, [{port, 0}], ProtoOpts),
|
||||||
Port = ranch:get_port(?FUNCTION_NAME),
|
Port = ranch:get_port(?FUNCTION_NAME),
|
||||||
|
@ -244,7 +243,7 @@ resp_iolist_body(Config) ->
|
||||||
settings_timeout_infinity(Config) ->
|
settings_timeout_infinity(Config) ->
|
||||||
doc("Ensure infinity for settings_timeout is accepted."),
|
doc("Ensure infinity for settings_timeout is accepted."),
|
||||||
ProtoOpts = #{
|
ProtoOpts = #{
|
||||||
env => #{dispatch => cowboy_router:compile(init_routes(Config))},
|
env => #{dispatch => init_dispatch(Config)},
|
||||||
settings_timeout => infinity
|
settings_timeout => infinity
|
||||||
},
|
},
|
||||||
{ok, _} = cowboy:start_clear(?FUNCTION_NAME, [{port, 0}], ProtoOpts),
|
{ok, _} = cowboy:start_clear(?FUNCTION_NAME, [{port, 0}], ProtoOpts),
|
||||||
|
|
|
@ -30,20 +30,27 @@ all() -> [{group, clear}].
|
||||||
|
|
||||||
groups() -> [{clear, [parallel], ct_helper:all(?MODULE)}].
|
groups() -> [{clear, [parallel], ct_helper:all(?MODULE)}].
|
||||||
|
|
||||||
init_routes(_) -> [
|
init_per_group(Name, Config) ->
|
||||||
{"localhost", [
|
cowboy_test:init_http(Name, #{
|
||||||
|
env => #{dispatch => init_dispatch(Config)}
|
||||||
|
}, Config).
|
||||||
|
|
||||||
|
end_per_group(Name, _) ->
|
||||||
|
cowboy:stop_listener(Name).
|
||||||
|
|
||||||
|
init_dispatch(_) ->
|
||||||
|
cowboy_router:compile([{"localhost", [
|
||||||
{"/", hello_h, []},
|
{"/", hello_h, []},
|
||||||
{"/echo/:key", echo_h, []},
|
{"/echo/:key", echo_h, []},
|
||||||
{"/resp/:key[/:arg]", resp_h, []},
|
{"/resp/:key[/:arg]", resp_h, []},
|
||||||
{"/set_options/:key", set_options_h, []}
|
{"/set_options/:key", set_options_h, []}
|
||||||
]}
|
]}]).
|
||||||
].
|
|
||||||
|
|
||||||
chunked_false(Config) ->
|
chunked_false(Config) ->
|
||||||
doc("Confirm the option chunked => false disables chunked "
|
doc("Confirm the option chunked => false disables chunked "
|
||||||
"transfer-encoding for HTTP/1.1 connections."),
|
"transfer-encoding for HTTP/1.1 connections."),
|
||||||
{ok, _} = cowboy:start_clear(?FUNCTION_NAME, [{port, 0}], #{
|
{ok, _} = cowboy:start_clear(?FUNCTION_NAME, [{port, 0}], #{
|
||||||
env => #{dispatch => cowboy_router:compile(init_routes(Config))},
|
env => #{dispatch => init_dispatch(Config)},
|
||||||
chunked => false
|
chunked => false
|
||||||
}),
|
}),
|
||||||
Port = ranch:get_port(?FUNCTION_NAME),
|
Port = ranch:get_port(?FUNCTION_NAME),
|
||||||
|
@ -68,11 +75,131 @@ chunked_false(Config) ->
|
||||||
cowboy:stop_listener(?FUNCTION_NAME)
|
cowboy:stop_listener(?FUNCTION_NAME)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
chunked_one_byte_at_a_time(Config) ->
|
||||||
|
doc("Confirm that chunked transfer-encoding works when "
|
||||||
|
"the body is received one byte at a time."),
|
||||||
|
Body = list_to_binary(io_lib:format("~p", [lists:seq(1, 100)])),
|
||||||
|
ChunkedBody = iolist_to_binary(do_chunked_body(50, Body, [])),
|
||||||
|
Client = raw_open(Config),
|
||||||
|
ok = raw_send(Client,
|
||||||
|
"POST /echo/read_body HTTP/1.1\r\n"
|
||||||
|
"Host: localhost\r\n"
|
||||||
|
"Transfer-encoding: chunked\r\n\r\n"),
|
||||||
|
_ = [begin
|
||||||
|
raw_send(Client, <<C>>),
|
||||||
|
timer:sleep(10)
|
||||||
|
end || <<C>> <= ChunkedBody],
|
||||||
|
Rest = case catch raw_recv_head(Client) of
|
||||||
|
{'EXIT', _} -> error(closed);
|
||||||
|
Data ->
|
||||||
|
{'HTTP/1.1', 200, _, Rest0} = cow_http:parse_status_line(Data),
|
||||||
|
{_, Rest1} = cow_http:parse_headers(Rest0),
|
||||||
|
Rest1
|
||||||
|
end,
|
||||||
|
RestSize = byte_size(Rest),
|
||||||
|
<<Rest:RestSize/binary, Expect/bits>> = Body,
|
||||||
|
raw_expect_recv(Client, Expect).
|
||||||
|
|
||||||
|
chunked_one_chunk_at_a_time(Config) ->
|
||||||
|
doc("Confirm that chunked transfer-encoding works when "
|
||||||
|
"the body is received one chunk at a time."),
|
||||||
|
Body = list_to_binary(io_lib:format("~p", [lists:seq(1, 100)])),
|
||||||
|
Chunks = do_chunked_body(50, Body, []),
|
||||||
|
Client = raw_open(Config),
|
||||||
|
ok = raw_send(Client,
|
||||||
|
"POST /echo/read_body HTTP/1.1\r\n"
|
||||||
|
"Host: localhost\r\n"
|
||||||
|
"Transfer-encoding: chunked\r\n\r\n"),
|
||||||
|
_ = [begin
|
||||||
|
raw_send(Client, Chunk),
|
||||||
|
timer:sleep(10)
|
||||||
|
end || Chunk <- Chunks],
|
||||||
|
Rest = case catch raw_recv_head(Client) of
|
||||||
|
{'EXIT', _} -> error(closed);
|
||||||
|
Data ->
|
||||||
|
{'HTTP/1.1', 200, _, Rest0} = cow_http:parse_status_line(Data),
|
||||||
|
{_, Rest1} = cow_http:parse_headers(Rest0),
|
||||||
|
Rest1
|
||||||
|
end,
|
||||||
|
RestSize = byte_size(Rest),
|
||||||
|
<<Rest:RestSize/binary, Expect/bits>> = Body,
|
||||||
|
raw_expect_recv(Client, Expect).
|
||||||
|
|
||||||
|
chunked_split_delay_in_chunk_body(Config) ->
|
||||||
|
doc("Confirm that chunked transfer-encoding works when "
|
||||||
|
"the body is received with a delay inside the chunks."),
|
||||||
|
Body = list_to_binary(io_lib:format("~p", [lists:seq(1, 100)])),
|
||||||
|
Chunks = do_chunked_body(50, Body, []),
|
||||||
|
Client = raw_open(Config),
|
||||||
|
ok = raw_send(Client,
|
||||||
|
"POST /echo/read_body HTTP/1.1\r\n"
|
||||||
|
"Host: localhost\r\n"
|
||||||
|
"Transfer-encoding: chunked\r\n\r\n"),
|
||||||
|
_ = [begin
|
||||||
|
case Chunk of
|
||||||
|
<<"0\r\n\r\n">> ->
|
||||||
|
raw_send(Client, Chunk);
|
||||||
|
_ ->
|
||||||
|
[Size, ChunkBody, <<>>] = binary:split(Chunk, <<"\r\n">>, [global]),
|
||||||
|
PartASize = rand:uniform(byte_size(ChunkBody)),
|
||||||
|
<<PartA:PartASize/binary, PartB/binary>> = ChunkBody,
|
||||||
|
raw_send(Client, [Size, <<"\r\n">>, PartA]),
|
||||||
|
timer:sleep(10),
|
||||||
|
raw_send(Client, [PartB, <<"\r\n">>])
|
||||||
|
end
|
||||||
|
end || Chunk <- Chunks],
|
||||||
|
Rest = case catch raw_recv_head(Client) of
|
||||||
|
{'EXIT', _} -> error(closed);
|
||||||
|
Data ->
|
||||||
|
{'HTTP/1.1', 200, _, Rest0} = cow_http:parse_status_line(Data),
|
||||||
|
{_, Rest1} = cow_http:parse_headers(Rest0),
|
||||||
|
Rest1
|
||||||
|
end,
|
||||||
|
RestSize = byte_size(Rest),
|
||||||
|
<<Rest:RestSize/binary, Expect/bits>> = Body,
|
||||||
|
raw_expect_recv(Client, Expect).
|
||||||
|
|
||||||
|
chunked_split_delay_in_chunk_crlf(Config) ->
|
||||||
|
doc("Confirm that chunked transfer-encoding works when "
|
||||||
|
"the body is received with a delay inside the chunks end CRLF."),
|
||||||
|
Body = list_to_binary(io_lib:format("~p", [lists:seq(1, 100)])),
|
||||||
|
Chunks = do_chunked_body(50, Body, []),
|
||||||
|
Client = raw_open(Config),
|
||||||
|
ok = raw_send(Client,
|
||||||
|
"POST /echo/read_body HTTP/1.1\r\n"
|
||||||
|
"Host: localhost\r\n"
|
||||||
|
"Transfer-encoding: chunked\r\n\r\n"),
|
||||||
|
_ = [begin
|
||||||
|
Len = byte_size(Chunk) - (rand:uniform(2) - 1),
|
||||||
|
<<Begin:Len/binary, End/binary>> = Chunk,
|
||||||
|
raw_send(Client, Begin),
|
||||||
|
timer:sleep(10),
|
||||||
|
raw_send(Client, End)
|
||||||
|
end || Chunk <- Chunks],
|
||||||
|
Rest = case catch raw_recv_head(Client) of
|
||||||
|
{'EXIT', _} -> error(closed);
|
||||||
|
Data ->
|
||||||
|
{'HTTP/1.1', 200, _, Rest0} = cow_http:parse_status_line(Data),
|
||||||
|
{_, Rest1} = cow_http:parse_headers(Rest0),
|
||||||
|
Rest1
|
||||||
|
end,
|
||||||
|
RestSize = byte_size(Rest),
|
||||||
|
<<Rest:RestSize/binary, Expect/bits>> = Body,
|
||||||
|
raw_expect_recv(Client, Expect).
|
||||||
|
|
||||||
|
do_chunked_body(_, <<>>, Acc) ->
|
||||||
|
lists:reverse([cow_http_te:last_chunk()|Acc]);
|
||||||
|
do_chunked_body(ChunkSize0, Data, Acc) ->
|
||||||
|
ChunkSize = min(byte_size(Data), ChunkSize0),
|
||||||
|
<<Chunk:ChunkSize/binary, Rest/binary>> = Data,
|
||||||
|
do_chunked_body(ChunkSize, Rest,
|
||||||
|
[iolist_to_binary(cow_http_te:chunk(Chunk))|Acc]).
|
||||||
|
|
||||||
http10_keepalive_false(Config) ->
|
http10_keepalive_false(Config) ->
|
||||||
doc("Confirm the option http10_keepalive => false disables keep-alive "
|
doc("Confirm the option http10_keepalive => false disables keep-alive "
|
||||||
"completely for HTTP/1.0 connections."),
|
"completely for HTTP/1.0 connections."),
|
||||||
{ok, _} = cowboy:start_clear(?FUNCTION_NAME, [{port, 0}], #{
|
{ok, _} = cowboy:start_clear(?FUNCTION_NAME, [{port, 0}], #{
|
||||||
env => #{dispatch => cowboy_router:compile(init_routes(Config))},
|
env => #{dispatch => init_dispatch(Config)},
|
||||||
http10_keepalive => false
|
http10_keepalive => false
|
||||||
}),
|
}),
|
||||||
Port = ranch:get_port(?FUNCTION_NAME),
|
Port = ranch:get_port(?FUNCTION_NAME),
|
||||||
|
@ -100,7 +227,7 @@ http10_keepalive_false(Config) ->
|
||||||
idle_timeout_infinity(Config) ->
|
idle_timeout_infinity(Config) ->
|
||||||
doc("Ensure the idle_timeout option accepts the infinity value."),
|
doc("Ensure the idle_timeout option accepts the infinity value."),
|
||||||
{ok, _} = cowboy:start_clear(?FUNCTION_NAME, [{port, 0}], #{
|
{ok, _} = cowboy:start_clear(?FUNCTION_NAME, [{port, 0}], #{
|
||||||
env => #{dispatch => cowboy_router:compile(init_routes(Config))},
|
env => #{dispatch => init_dispatch(Config)},
|
||||||
request_timeout => 500,
|
request_timeout => 500,
|
||||||
idle_timeout => infinity
|
idle_timeout => infinity
|
||||||
}),
|
}),
|
||||||
|
@ -126,7 +253,7 @@ idle_timeout_infinity(Config) ->
|
||||||
request_timeout_infinity(Config) ->
|
request_timeout_infinity(Config) ->
|
||||||
doc("Ensure the request_timeout option accepts the infinity value."),
|
doc("Ensure the request_timeout option accepts the infinity value."),
|
||||||
{ok, _} = cowboy:start_clear(?FUNCTION_NAME, [{port, 0}], #{
|
{ok, _} = cowboy:start_clear(?FUNCTION_NAME, [{port, 0}], #{
|
||||||
env => #{dispatch => cowboy_router:compile(init_routes(Config))},
|
env => #{dispatch => init_dispatch(Config)},
|
||||||
request_timeout => infinity
|
request_timeout => infinity
|
||||||
}),
|
}),
|
||||||
Port = ranch:get_port(?FUNCTION_NAME),
|
Port = ranch:get_port(?FUNCTION_NAME),
|
||||||
|
@ -151,7 +278,7 @@ set_options_chunked_false(Config) ->
|
||||||
"chunked transfer-encoding. This results in the closing of the "
|
"chunked transfer-encoding. This results in the closing of the "
|
||||||
"connection after the current request."),
|
"connection after the current request."),
|
||||||
{ok, _} = cowboy:start_clear(?FUNCTION_NAME, [{port, 0}], #{
|
{ok, _} = cowboy:start_clear(?FUNCTION_NAME, [{port, 0}], #{
|
||||||
env => #{dispatch => cowboy_router:compile(init_routes(Config))},
|
env => #{dispatch => init_dispatch(Config)},
|
||||||
chunked => true
|
chunked => true
|
||||||
}),
|
}),
|
||||||
Port = ranch:get_port(?FUNCTION_NAME),
|
Port = ranch:get_port(?FUNCTION_NAME),
|
||||||
|
@ -181,7 +308,7 @@ set_options_chunked_false_ignored(Config) ->
|
||||||
"chunked transfer-encoding, and that it is ignored if the "
|
"chunked transfer-encoding, and that it is ignored if the "
|
||||||
"response is not streamed."),
|
"response is not streamed."),
|
||||||
{ok, _} = cowboy:start_clear(?FUNCTION_NAME, [{port, 0}], #{
|
{ok, _} = cowboy:start_clear(?FUNCTION_NAME, [{port, 0}], #{
|
||||||
env => #{dispatch => cowboy_router:compile(init_routes(Config))},
|
env => #{dispatch => init_dispatch(Config)},
|
||||||
chunked => true
|
chunked => true
|
||||||
}),
|
}),
|
||||||
Port = ranch:get_port(?FUNCTION_NAME),
|
Port = ranch:get_port(?FUNCTION_NAME),
|
||||||
|
@ -206,7 +333,7 @@ set_options_idle_timeout(Config) ->
|
||||||
"set to change how long Cowboy will wait before it closes the connection."),
|
"set to change how long Cowboy will wait before it closes the connection."),
|
||||||
%% We start with a long timeout and then cut it short.
|
%% We start with a long timeout and then cut it short.
|
||||||
{ok, _} = cowboy:start_clear(?FUNCTION_NAME, [{port, 0}], #{
|
{ok, _} = cowboy:start_clear(?FUNCTION_NAME, [{port, 0}], #{
|
||||||
env => #{dispatch => cowboy_router:compile(init_routes(Config))},
|
env => #{dispatch => init_dispatch(Config)},
|
||||||
idle_timeout => 60000
|
idle_timeout => 60000
|
||||||
}),
|
}),
|
||||||
Port = ranch:get_port(?FUNCTION_NAME),
|
Port = ranch:get_port(?FUNCTION_NAME),
|
||||||
|
@ -232,7 +359,7 @@ set_options_idle_timeout_only_applies_to_current_request(Config) ->
|
||||||
doc("Confirm that changes to the idle_timeout option only apply to the current stream."),
|
doc("Confirm that changes to the idle_timeout option only apply to the current stream."),
|
||||||
%% We start with a long timeout and then cut it short.
|
%% We start with a long timeout and then cut it short.
|
||||||
{ok, _} = cowboy:start_clear(?FUNCTION_NAME, [{port, 0}], #{
|
{ok, _} = cowboy:start_clear(?FUNCTION_NAME, [{port, 0}], #{
|
||||||
env => #{dispatch => cowboy_router:compile(init_routes(Config))},
|
env => #{dispatch => init_dispatch(Config)},
|
||||||
idle_timeout => 500
|
idle_timeout => 500
|
||||||
}),
|
}),
|
||||||
Port = ranch:get_port(?FUNCTION_NAME),
|
Port = ranch:get_port(?FUNCTION_NAME),
|
||||||
|
@ -270,7 +397,7 @@ set_options_idle_timeout_only_applies_to_current_request(Config) ->
|
||||||
switch_protocol_flush(Config) ->
|
switch_protocol_flush(Config) ->
|
||||||
doc("Confirm that switch_protocol does not flush unrelated messages."),
|
doc("Confirm that switch_protocol does not flush unrelated messages."),
|
||||||
ProtoOpts = #{
|
ProtoOpts = #{
|
||||||
env => #{dispatch => cowboy_router:compile(init_routes(Config))},
|
env => #{dispatch => init_dispatch(Config)},
|
||||||
stream_handlers => [switch_protocol_flush_h]
|
stream_handlers => [switch_protocol_flush_h]
|
||||||
},
|
},
|
||||||
{ok, _} = cowboy:start_clear(?FUNCTION_NAME, [{port, 0}], ProtoOpts),
|
{ok, _} = cowboy:start_clear(?FUNCTION_NAME, [{port, 0}], ProtoOpts),
|
||||||
|
|
|
@ -446,106 +446,6 @@ slowloris2(Config) ->
|
||||||
{_, 408, _, _} = cow_http:parse_status_line(Data),
|
{_, 408, _, _} = cow_http:parse_status_line(Data),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
te_chunked(Config) ->
|
|
||||||
Body = list_to_binary(io_lib:format("~p", [lists:seq(1, 100)])),
|
|
||||||
ConnPid = gun_open(Config),
|
|
||||||
Ref = gun:post(ConnPid, "/echo/body", [{<<"content-type">>, <<"text/plain">>}]),
|
|
||||||
gun:data(ConnPid, Ref, fin, Body),
|
|
||||||
{response, nofin, 200, _} = gun:await(ConnPid, Ref),
|
|
||||||
{ok, Body} = gun:await_body(ConnPid, Ref),
|
|
||||||
ok.
|
|
||||||
|
|
||||||
do_body_to_chunks(_, <<>>, Acc) ->
|
|
||||||
lists:reverse([<<"0\r\n\r\n">>|Acc]);
|
|
||||||
do_body_to_chunks(ChunkSize, Body, Acc) ->
|
|
||||||
BodySize = byte_size(Body),
|
|
||||||
ChunkSize2 = case BodySize < ChunkSize of
|
|
||||||
true -> BodySize;
|
|
||||||
false -> ChunkSize
|
|
||||||
end,
|
|
||||||
<< Chunk:ChunkSize2/binary, Rest/binary >> = Body,
|
|
||||||
ChunkSizeBin = integer_to_binary(ChunkSize2, 16),
|
|
||||||
do_body_to_chunks(ChunkSize, Rest,
|
|
||||||
[<< ChunkSizeBin/binary, "\r\n", Chunk/binary, "\r\n" >>|Acc]).
|
|
||||||
|
|
||||||
te_chunked_chopped(Config) ->
|
|
||||||
Body = list_to_binary(io_lib:format("~p", [lists:seq(1, 100)])),
|
|
||||||
Body2 = iolist_to_binary(do_body_to_chunks(50, Body, [])),
|
|
||||||
ConnPid = gun_open(Config),
|
|
||||||
Ref = gun:post(ConnPid, "/echo/body",
|
|
||||||
[{<<"content-type">>, <<"text/plain">>}]),
|
|
||||||
_ = [begin
|
|
||||||
ok = dbg_send_raw(ConnPid, << C >>),
|
|
||||||
receive after 10 -> ok end
|
|
||||||
end || << C >> <= Body2],
|
|
||||||
{response, nofin, 200, _} = gun:await(ConnPid, Ref),
|
|
||||||
{ok, Body} = gun:await_body(ConnPid, Ref),
|
|
||||||
ok.
|
|
||||||
|
|
||||||
te_chunked_delayed(Config) ->
|
|
||||||
Body = list_to_binary(io_lib:format("~p", [lists:seq(1, 100)])),
|
|
||||||
Chunks = do_body_to_chunks(50, Body, []),
|
|
||||||
ConnPid = gun_open(Config),
|
|
||||||
Ref = gun:post(ConnPid, "/echo/body",
|
|
||||||
[{<<"content-type">>, <<"text/plain">>}]),
|
|
||||||
_ = [begin
|
|
||||||
ok = dbg_send_raw(ConnPid, Chunk),
|
|
||||||
receive after 10 -> ok end
|
|
||||||
end || Chunk <- Chunks],
|
|
||||||
{response, nofin, 200, _} = gun:await(ConnPid, Ref),
|
|
||||||
{ok, Body} = gun:await_body(ConnPid, Ref),
|
|
||||||
ok.
|
|
||||||
|
|
||||||
te_chunked_split_body(Config) ->
|
|
||||||
Body = list_to_binary(io_lib:format("~p", [lists:seq(1, 100)])),
|
|
||||||
Chunks = do_body_to_chunks(50, Body, []),
|
|
||||||
ConnPid = gun_open(Config),
|
|
||||||
Ref = gun:post(ConnPid, "/echo/body",
|
|
||||||
[{<<"content-type">>, <<"text/plain">>}]),
|
|
||||||
_ = [begin
|
|
||||||
case Chunk of
|
|
||||||
<<"0\r\n\r\n">> ->
|
|
||||||
ok = dbg_send_raw(ConnPid, Chunk);
|
|
||||||
_ ->
|
|
||||||
[Size, ChunkBody, <<>>] =
|
|
||||||
binary:split(Chunk, [<<"\r\n">>], [global]),
|
|
||||||
PartASize = random:uniform(byte_size(ChunkBody)),
|
|
||||||
<<PartA:PartASize/binary, PartB/binary>> = ChunkBody,
|
|
||||||
ok = dbg_send_raw(ConnPid, [Size, <<"\r\n">>, PartA]),
|
|
||||||
receive after 10 -> ok end,
|
|
||||||
ok = dbg_send_raw(ConnPid, [PartB, <<"\r\n">>])
|
|
||||||
end
|
|
||||||
end || Chunk <- Chunks],
|
|
||||||
{response, nofin, 200, _} = gun:await(ConnPid, Ref),
|
|
||||||
{ok, Body} = gun:await_body(ConnPid, Ref),
|
|
||||||
ok.
|
|
||||||
|
|
||||||
te_chunked_split_crlf(Config) ->
|
|
||||||
Body = list_to_binary(io_lib:format("~p", [lists:seq(1, 100)])),
|
|
||||||
Chunks = do_body_to_chunks(50, Body, []),
|
|
||||||
ConnPid = gun_open(Config),
|
|
||||||
Ref = gun:post(ConnPid, "/echo/body",
|
|
||||||
[{<<"content-type">>, <<"text/plain">>}]),
|
|
||||||
_ = [begin
|
|
||||||
%% Split in the newline just before the end of the chunk.
|
|
||||||
Len = byte_size(Chunk) - (random:uniform(2) - 1),
|
|
||||||
<< Chunk2:Len/binary, End/binary >> = Chunk,
|
|
||||||
ok = dbg_send_raw(ConnPid, Chunk2),
|
|
||||||
receive after 10 -> ok end,
|
|
||||||
ok = dbg_send_raw(ConnPid, End)
|
|
||||||
end || Chunk <- Chunks],
|
|
||||||
{response, nofin, 200, _} = gun:await(ConnPid, Ref),
|
|
||||||
{ok, Body} = gun:await_body(ConnPid, Ref),
|
|
||||||
ok.
|
|
||||||
|
|
||||||
te_identity(Config) ->
|
|
||||||
Body = list_to_binary(io_lib:format("~p", [lists:seq(1, 100)])),
|
|
||||||
ConnPid = gun_open(Config),
|
|
||||||
Ref = gun:post(ConnPid, "/echo/body", [], Body),
|
|
||||||
{response, nofin, 200, _} = gun:await(ConnPid, Ref),
|
|
||||||
{ok, Body} = gun:await_body(ConnPid, Ref),
|
|
||||||
ok.
|
|
||||||
|
|
||||||
dbg_send_raw(ConnPid, Data) ->
|
dbg_send_raw(ConnPid, Data) ->
|
||||||
#{
|
#{
|
||||||
socket := Socket,
|
socket := Socket,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue