mirror of
https://github.com/ninenines/cowboy.git
synced 2025-07-14 12:20:24 +00:00
Move HTTP/1.0 tests from the old test suite to rfc7230
This commit is contained in:
parent
18ba3c7cff
commit
9e852b4dd2
2 changed files with 47 additions and 79 deletions
|
@ -166,69 +166,6 @@ headers_dupe(Config) ->
|
||||||
[<<"close">>] = [V || {Name, V} <- Headers, Name =:= <<"connection">>],
|
[<<"close">>] = [V || {Name, V} <- Headers, Name =:= <<"connection">>],
|
||||||
gun_down(ConnPid).
|
gun_down(ConnPid).
|
||||||
|
|
||||||
http10_chunkless(Config) ->
|
|
||||||
ConnPid = gun_open(Config, #{http_opts => #{version => 'HTTP/1.0'}}),
|
|
||||||
Ref = gun:get(ConnPid, "/chunked_response"),
|
|
||||||
{response, nofin, 200, Headers} = gun:await(ConnPid, Ref),
|
|
||||||
false = lists:keyfind(<<"transfer-encoding">>, 1, Headers),
|
|
||||||
{ok, <<"chunked_handler\r\nworks fine!">>} = gun:await_body(ConnPid, Ref),
|
|
||||||
gun_down(ConnPid).
|
|
||||||
|
|
||||||
http10_hostless(Config) ->
|
|
||||||
Name = http10_hostless,
|
|
||||||
Port10 = config(port, Config) + 10,
|
|
||||||
{Transport, Protocol} = case config(type, Config) of
|
|
||||||
tcp -> {ranch_tcp, cowboy_clear};
|
|
||||||
ssl -> {ranch_ssl, cowboy_tls}
|
|
||||||
end,
|
|
||||||
{ok, _} = ranch:start_listener(Name, 5, Transport,
|
|
||||||
config(opts, Config) ++ [{port, Port10}],
|
|
||||||
Protocol, #{
|
|
||||||
env =>#{dispatch => cowboy_router:compile([
|
|
||||||
{'_', [{"/http1.0/hostless", http_handler, []}]}])},
|
|
||||||
max_keepalive => 50,
|
|
||||||
timeout => 500
|
|
||||||
}),
|
|
||||||
200 = do_raw("GET /http1.0/hostless HTTP/1.0\r\n\r\n",
|
|
||||||
[{port, Port10}|Config]),
|
|
||||||
cowboy:stop_listener(http10_hostless).
|
|
||||||
|
|
||||||
http10_keepalive_default(Config) ->
|
|
||||||
Normal = "GET / HTTP/1.0\r\nhost: localhost\r\n\r\n",
|
|
||||||
Client = raw_open(Config),
|
|
||||||
ok = raw_send(Client, Normal),
|
|
||||||
_ = case catch raw_recv_head(Client) of
|
|
||||||
{'EXIT', _} -> error(closed);
|
|
||||||
Data ->
|
|
||||||
%% Cowboy always advertises itself as HTTP/1.1.
|
|
||||||
{'HTTP/1.1', 200, _, Rest} = cow_http:parse_status_line(Data),
|
|
||||||
{Headers, _} = cow_http:parse_headers(Rest),
|
|
||||||
{_, <<"close">>} = lists:keyfind(<<"connection">>, 1, Headers)
|
|
||||||
end,
|
|
||||||
ok = raw_send(Client, Normal),
|
|
||||||
case catch raw_recv_head(Client) of
|
|
||||||
{'EXIT', _} -> closed;
|
|
||||||
_ -> error(not_closed)
|
|
||||||
end.
|
|
||||||
|
|
||||||
http10_keepalive_forced(Config) ->
|
|
||||||
Keepalive = "GET / HTTP/1.0\r\nhost: localhost\r\nConnection: keep-alive\r\n\r\n",
|
|
||||||
Client = raw_open(Config),
|
|
||||||
ok = raw_send(Client, Keepalive),
|
|
||||||
_ = case catch raw_recv_head(Client) of
|
|
||||||
{'EXIT', _} -> error(closed);
|
|
||||||
Data ->
|
|
||||||
%% Cowboy always advertises itself as HTTP/1.1.
|
|
||||||
{'HTTP/1.1', 200, _, Rest} = cow_http:parse_status_line(Data),
|
|
||||||
{Headers, _} = cow_http:parse_headers(Rest),
|
|
||||||
{_, <<"keep-alive">>} = lists:keyfind(<<"connection">>, 1, Headers)
|
|
||||||
end,
|
|
||||||
ok = raw_send(Client, Keepalive),
|
|
||||||
case catch raw_recv_head(Client) of
|
|
||||||
{'EXIT', Err} -> error({closed, Err});
|
|
||||||
_ -> ok
|
|
||||||
end.
|
|
||||||
|
|
||||||
keepalive_nl(Config) ->
|
keepalive_nl(Config) ->
|
||||||
ConnPid = gun_open(Config),
|
ConnPid = gun_open(Config),
|
||||||
Refs = [begin
|
Refs = [begin
|
||||||
|
|
|
@ -173,11 +173,6 @@ timeout_after_request_line_host_crlfcr(Config) ->
|
||||||
#{code := 408, client := Client4} = do_raw(Config, "GET / HTTP/1.1\r\nHost: localhost\r\n\r"),
|
#{code := 408, client := Client4} = do_raw(Config, "GET / HTTP/1.1\r\nHost: localhost\r\n\r"),
|
||||||
{error, closed} = raw_recv(Client4, 0, 6000).
|
{error, closed} = raw_recv(Client4, 0, 6000).
|
||||||
|
|
||||||
%% @todo Add an HTTP/1.0 test suite.
|
|
||||||
%An HTTP/1.1 server must understand any valid HTTP/1.0 request,
|
|
||||||
%and respond to those with an HTTP/1.1 message that only use
|
|
||||||
%features understood or safely ignored by HTTP/1.0 clients. (RFC7230 A)
|
|
||||||
|
|
||||||
%% Request line.
|
%% Request line.
|
||||||
|
|
||||||
limit_request_line_8000(Config) ->
|
limit_request_line_8000(Config) ->
|
||||||
|
@ -703,7 +698,8 @@ reject_invalid_version_http2(Config) ->
|
||||||
|
|
||||||
reject_empty_version(Config) ->
|
reject_empty_version(Config) ->
|
||||||
doc("Any version number other than HTTP/1.0 or HTTP/1.1 must be "
|
doc("Any version number other than HTTP/1.0 or HTTP/1.1 must be "
|
||||||
"rejected by a server or intermediary with a 505 status code. (RFC7230 2.6, RFC7230 A.2)"),
|
"rejected by a server or intermediary with a 505 status code. "
|
||||||
|
"(RFC7230 2.6, RFC7230 A, RFC7230 A.2)"),
|
||||||
#{code := 505} = do_raw(Config,
|
#{code := 505} = do_raw(Config,
|
||||||
"GET / \r\n"
|
"GET / \r\n"
|
||||||
"Host: localhost\r\n"
|
"Host: localhost\r\n"
|
||||||
|
@ -1390,28 +1386,51 @@ remove_transfer_encoding_chunked_after_body_read(Config) ->
|
||||||
%HTTP version. (RFC7230 6.3)
|
%HTTP version. (RFC7230 6.3)
|
||||||
|
|
||||||
no_connection_header_keepalive(Config) ->
|
no_connection_header_keepalive(Config) ->
|
||||||
doc("HTTP/1.1 requests with no \"close\" option and HTTP/1.0 with the "
|
doc("HTTP/1.1 requests with no \"close\" option "
|
||||||
"\"keep-alive\" option indicate the connection will persist. (RFC7230 6.1, RFC7230 6.3)"),
|
"indicate the connection will persist. (RFC7230 6.1, RFC7230 6.3)"),
|
||||||
#{code := 200, client := Client} = do_raw(Config, [
|
#{code := 200, headers := RespHeaders, client := Client} = do_raw(Config, [
|
||||||
"GET / HTTP/1.1\r\n"
|
"GET / HTTP/1.1\r\n"
|
||||||
"Host: localhost\r\n"
|
"Host: localhost\r\n"
|
||||||
"\r\n"]),
|
"\r\n"]),
|
||||||
|
false = lists:keyfind(<<"connection">>, 1, RespHeaders),
|
||||||
{error, timeout} = raw_recv(Client, 0, 1000).
|
{error, timeout} = raw_recv(Client, 0, 1000).
|
||||||
|
|
||||||
%% @todo http/1.0 suite? connection_keepalive(Config) ->
|
http10_connection_keepalive(Config) ->
|
||||||
|
doc("HTTP/1.0 requests with the \"keep-alive\" option "
|
||||||
|
"indicate the connection will persist. "
|
||||||
|
"(RFC7230 6.1, RFC7230 6.3, RFC7230 A.1.2)"),
|
||||||
|
#{code := 200, headers := RespHeaders, client := Client} = do_raw(Config, [
|
||||||
|
"GET / HTTP/1.0\r\n"
|
||||||
|
"Host: localhost\r\n"
|
||||||
|
"Connection: keep-alive\r\n"
|
||||||
|
"\r\n"]),
|
||||||
|
{_, <<"keep-alive">>} = lists:keyfind(<<"connection">>, 1, RespHeaders),
|
||||||
|
{error, timeout} = raw_recv(Client, 0, 1000).
|
||||||
|
|
||||||
connection_close(Config) ->
|
connection_close(Config) ->
|
||||||
doc("HTTP/1.1 requests with the \"close\" option and HTTP/1.0 with no "
|
doc("HTTP/1.1 requests with the \"close\" option and HTTP/1.0 with no "
|
||||||
"\"keep-alive\" option indicate the connection will be closed "
|
"\"keep-alive\" option indicate the connection will be closed "
|
||||||
"upon reception of the response by the client. (RFC7230 6.1, RFC7230 6.3)"),
|
"upon reception of the response by the client. (RFC7230 6.1, RFC7230 6.3)"),
|
||||||
#{code := 200, client := Client} = do_raw(Config, [
|
#{code := 200, headers := RespHeaders, client := Client} = do_raw(Config, [
|
||||||
"GET / HTTP/1.1\r\n"
|
"GET / HTTP/1.1\r\n"
|
||||||
"Host: localhost\r\n"
|
"Host: localhost\r\n"
|
||||||
"Connection: close\r\n"
|
"Connection: close\r\n"
|
||||||
"\r\n"]),
|
"\r\n"]),
|
||||||
|
{_, <<"close">>} = lists:keyfind(<<"connection">>, 1, RespHeaders),
|
||||||
{error, closed} = raw_recv(Client, 0, 1000).
|
{error, closed} = raw_recv(Client, 0, 1000).
|
||||||
|
|
||||||
%% @todo http/1.0 suite? no_connection_close(Config) ->
|
http10_no_connection_header_close(Config) ->
|
||||||
|
doc("HTTP/1.0 with no \"keep-alive\" option indicate "
|
||||||
|
"the connection will be closed upon reception of "
|
||||||
|
"the response by the client. (RFC7230 6.1, RFC7230 6.3, RFC7230 A.1.2)"),
|
||||||
|
#{code := 200, headers := RespHeaders, client := Client} = do_raw(Config, [
|
||||||
|
"GET / HTTP/1.0\r\n"
|
||||||
|
"Host: localhost\r\n"
|
||||||
|
"\r\n"]),
|
||||||
|
%% Cowboy always sends a close header back to HTTP/1.0 clients
|
||||||
|
%% that support keep-alive, even though it is not required.
|
||||||
|
{_, <<"close">>} = lists:keyfind(<<"connection">>, 1, RespHeaders),
|
||||||
|
{error, closed} = raw_recv(Client, 0, 1000).
|
||||||
|
|
||||||
limit_requests_keepalive(Config) ->
|
limit_requests_keepalive(Config) ->
|
||||||
doc("The maximum number of requests sent using a persistent connection "
|
doc("The maximum number of requests sent using a persistent connection "
|
||||||
|
@ -1549,9 +1568,20 @@ reject_missing_host(Config) ->
|
||||||
"\r\n"]),
|
"\r\n"]),
|
||||||
{error, closed} = raw_recv(Client, 0, 1000).
|
{error, closed} = raw_recv(Client, 0, 1000).
|
||||||
|
|
||||||
%% @todo http/1.0 missing_host(Config) ->
|
http10_allow_missing_host(Config0) ->
|
||||||
%An HTTP/1.0 request that lack a host header is valid. Behavior
|
doc("An HTTP/1.0 request that lacks a host header may be accepted. "
|
||||||
%for these requests is configuration dependent. (RFC7230 5.5)
|
"(RFC7230 5.4, RFC7230 5.5, RFC7230 A.1.1)"),
|
||||||
|
Routes = [{'_', [{"/echo/:key[/:arg]", echo_h, []}]}],
|
||||||
|
Config = cowboy_test:init_http(?FUNCTION_NAME, #{
|
||||||
|
env => #{dispatch => cowboy_router:compile(Routes)}
|
||||||
|
}, Config0),
|
||||||
|
try
|
||||||
|
#{code := 200, body := <<>>} = do_raw(Config, [
|
||||||
|
"GET /echo/host HTTP/1.0\r\n"
|
||||||
|
"\r\n"])
|
||||||
|
after
|
||||||
|
cowboy:stop_listener(?FUNCTION_NAME)
|
||||||
|
end.
|
||||||
|
|
||||||
reject_invalid_host(Config) ->
|
reject_invalid_host(Config) ->
|
||||||
doc("A request with an invalid host header must be rejected with a "
|
doc("A request with an invalid host header must be rejected with a "
|
||||||
|
@ -1953,7 +1983,8 @@ no_content_length_if_transfer_encoding(Config) ->
|
||||||
http10_request_no_transfer_encoding_in_response(Config) ->
|
http10_request_no_transfer_encoding_in_response(Config) ->
|
||||||
doc("The transfer-encoding header must not be sent in responses to "
|
doc("The transfer-encoding header must not be sent in responses to "
|
||||||
"HTTP/1.0 requests, or in responses that use the HTTP/1.0 version. "
|
"HTTP/1.0 requests, or in responses that use the HTTP/1.0 version. "
|
||||||
"No transfer codings must be applied in these cases. (RFC7230 3.3.1)"),
|
"No transfer codings must be applied in these cases. "
|
||||||
|
"(RFC7230 3.3.1, RFC7230 A.1.3)"),
|
||||||
Client = raw_open(Config),
|
Client = raw_open(Config),
|
||||||
ok = raw_send(Client, [
|
ok = raw_send(Client, [
|
||||||
"GET /resp/stream_reply2/200 HTTP/1.0\r\n"
|
"GET /resp/stream_reply2/200 HTTP/1.0\r\n"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue