From 9e852b4dd2bf8dc8e31359fe9a1f4601168fd6fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Hoguin?= Date: Tue, 20 Nov 2018 23:10:51 +0100 Subject: Move HTTP/1.0 tests from the old test suite to rfc7230 --- test/old_http_SUITE.erl | 63 ------------------------------------------------- test/rfc7230_SUITE.erl | 63 ++++++++++++++++++++++++++++++++++++------------- 2 files changed, 47 insertions(+), 79 deletions(-) (limited to 'test') diff --git a/test/old_http_SUITE.erl b/test/old_http_SUITE.erl index 767f65d..0448407 100644 --- a/test/old_http_SUITE.erl +++ b/test/old_http_SUITE.erl @@ -166,69 +166,6 @@ headers_dupe(Config) -> [<<"close">>] = [V || {Name, V} <- Headers, Name =:= <<"connection">>], 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) -> ConnPid = gun_open(Config), Refs = [begin diff --git a/test/rfc7230_SUITE.erl b/test/rfc7230_SUITE.erl index 17ff452..0ef1690 100644 --- a/test/rfc7230_SUITE.erl +++ b/test/rfc7230_SUITE.erl @@ -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"), {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. limit_request_line_8000(Config) -> @@ -703,7 +698,8 @@ reject_invalid_version_http2(Config) -> reject_empty_version(Config) -> 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, "GET / \r\n" "Host: localhost\r\n" @@ -1390,28 +1386,51 @@ remove_transfer_encoding_chunked_after_body_read(Config) -> %HTTP version. (RFC7230 6.3) no_connection_header_keepalive(Config) -> - doc("HTTP/1.1 requests with no \"close\" option and HTTP/1.0 with the " - "\"keep-alive\" option indicate the connection will persist. (RFC7230 6.1, RFC7230 6.3)"), - #{code := 200, client := Client} = do_raw(Config, [ + doc("HTTP/1.1 requests with no \"close\" option " + "indicate the connection will persist. (RFC7230 6.1, RFC7230 6.3)"), + #{code := 200, headers := RespHeaders, client := Client} = do_raw(Config, [ "GET / HTTP/1.1\r\n" "Host: localhost\r\n" "\r\n"]), + false = lists:keyfind(<<"connection">>, 1, RespHeaders), {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) -> doc("HTTP/1.1 requests with the \"close\" option and 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)"), - #{code := 200, client := Client} = do_raw(Config, [ + #{code := 200, headers := RespHeaders, client := Client} = do_raw(Config, [ "GET / HTTP/1.1\r\n" "Host: localhost\r\n" "Connection: close\r\n" "\r\n"]), + {_, <<"close">>} = lists:keyfind(<<"connection">>, 1, RespHeaders), {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) -> doc("The maximum number of requests sent using a persistent connection " @@ -1549,9 +1568,20 @@ reject_missing_host(Config) -> "\r\n"]), {error, closed} = raw_recv(Client, 0, 1000). -%% @todo http/1.0 missing_host(Config) -> -%An HTTP/1.0 request that lack a host header is valid. Behavior -%for these requests is configuration dependent. (RFC7230 5.5) +http10_allow_missing_host(Config0) -> + doc("An HTTP/1.0 request that lacks a host header may be accepted. " + "(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) -> 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) -> 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. " - "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), ok = raw_send(Client, [ "GET /resp/stream_reply2/200 HTTP/1.0\r\n" -- cgit v1.2.3