diff options
author | Loïc Hoguin <[email protected]> | 2017-11-24 00:16:19 +0100 |
---|---|---|
committer | Loïc Hoguin <[email protected]> | 2017-11-24 00:16:19 +0100 |
commit | ce32e1985afd6c629ed904a7cf2b3c119782e914 (patch) | |
tree | a63812736e4c297e7af3f88936534008ba07cb55 | |
parent | 14173d592999bb0478d8e2a7d7334800ee26057c (diff) | |
download | cowboy-ce32e1985afd6c629ed904a7cf2b3c119782e914.tar.gz cowboy-ce32e1985afd6c629ed904a7cf2b3c119782e914.tar.bz2 cowboy-ce32e1985afd6c629ed904a7cf2b3c119782e914.zip |
Add more tests to the rfc7230 suite
Found more bugs! Unfortunately no fix for them in this commit.
-rw-r--r-- | test/handlers/send_message_h.erl | 9 | ||||
-rw-r--r-- | test/http_SUITE.erl | 2 | ||||
-rw-r--r-- | test/rfc7230_SUITE.erl | 155 |
3 files changed, 120 insertions, 46 deletions
diff --git a/test/handlers/send_message_h.erl b/test/handlers/send_message_h.erl new file mode 100644 index 0000000..02d2139 --- /dev/null +++ b/test/handlers/send_message_h.erl @@ -0,0 +1,9 @@ +%% This module sends a message to the pid passed in a header. + +-module(send_message_h). +-export([init/2]). + +init(Req, State) -> + Pid = list_to_pid(binary_to_list(cowboy_req:header(<<"x-test-pid">>, Req))), + Pid ! {Pid, self(), init, Req, State}, + {ok, cowboy_req:reply(200, Req), State}. diff --git a/test/http_SUITE.erl b/test/http_SUITE.erl index 4370ab2..b4c6cc7 100644 --- a/test/http_SUITE.erl +++ b/test/http_SUITE.erl @@ -91,7 +91,7 @@ end_per_group(Name, _) -> %% Dispatch configuration. -init_dispatch(Config) -> +init_dispatch(_) -> cowboy_router:compile([ {"localhost", [ {"/chunked_response", http_chunked, []}, diff --git a/test/rfc7230_SUITE.erl b/test/rfc7230_SUITE.erl index f6344c7..0f17133 100644 --- a/test/rfc7230_SUITE.erl +++ b/test/rfc7230_SUITE.erl @@ -24,7 +24,7 @@ all() -> [{group, http}]. -groups() -> [{http, [parallel], ct_helper:all(?MODULE)}]. %% @todo parallel +groups() -> [{http, [parallel], ct_helper:all(?MODULE)}]. init_per_group(Name = http, Config) -> cowboy_test:init_http(Name = http, #{ @@ -38,7 +38,8 @@ init_routes(_) -> [ {"localhost", [ {"/", hello_h, []}, {"/echo/:key[/:arg]", echo_h, []}, - {"/length/echo/:key", echo_h, []} + {"/length/echo/:key", echo_h, []}, + {"/send_message", send_message_h, []} %% @todo Something is clearly wrong about routing * right now. %% {"*", asterisk_h, []} ]}, @@ -1443,22 +1444,66 @@ pipeline(Config) -> %Abusive traffic can come from the form of too many requests in a %given amount of time, or too many concurrent connections. Limits %must be subject to configuration. (RFC7230 6.4) -% -%close_inactive_connections(Config) -> -%The server must close inactive connections. The timeout -%must be subject to configuration. (RFC7230 6.5) -% + +close_inactive_connections(Config) -> + doc("The server must close inactive connections. The timeout " + "must be subject to configuration. (RFC7230 6.5)"), + Client = raw_open(Config), + {error, closed} = raw_recv(Client, 0, 6000). + %@todo %The server must monitor connections for the close signal %and close the socket on its end accordingly. (RFC7230 6.5) % %@todo %A connection close may occur at any time. (RFC7230 6.5) -% -%ignore_requests_after_connection_close(Config) -> -%The server must not process any request after sending or -%receiving the "close" connection option. (RFC7230 6.6) -% + +ignore_requests_after_request_connection_close(Config) -> + doc("The server must not process any request after " + "receiving the \"close\" connection option. (RFC7230 6.6)"), + Self = self(), + #{code := 200, client := Client} = do_raw(Config, [ + "GET / HTTP/1.1\r\n" + "Host: localhost\r\n" + "Connection: close\r\n" + "\r\n" + "GET /send_message HTTP/1.1\r\n" + "Host: localhost\r\n" + "x-test-pid: ", pid_to_list(Self), "\r\n" + "\r\n"]), + {error, closed} = raw_recv(Client, 0, 1000), + %% We receive a message if the second request is wrongly processed. + receive + {Self, _, init, Req, Opts} -> + error({init, Req, Opts}) + after 1000 -> + ok + end. + +ignore_requests_after_response_connection_close(Config) -> + doc("The server must not process any request after " + "sending the \"close\" connection option. (RFC7230 6.6)"), + Self = self(), + #{code := 200} = do_raw(Config, [ + [ + "GET / HTTP/1.1\r\n" + "Host: localhost\r\n" + "\r\n" + || _ <- lists:seq(1, 100)], + "GET /send_message HTTP/1.1\r\n" + "Host: localhost\r\n" + "x-test-pid: ", pid_to_list(Self), "\r\n" + "\r\n"]), + %% We have a separate test for the connection close so we don't + %% double check the connection gets closed here. We only need to + %% know whether the 101st request was wrongly processed. + receive + {Self, _, init, Req, Opts} -> + error({init, Req, Opts}) + after 1000 -> + ok + end. + %@todo %The server must close the connection in stages to avoid the %TCP reset problem. The server starts by closing the write @@ -1467,53 +1512,73 @@ pipeline(Config) -> %last response has been received by the client, or until %a close or timeout occurs. The server then fully close the %connection. (6.6) -% -%%% Routing. -% + +%% Routing. + %``` %Host = authority ; same as authority-form %``` -% -%reject_missing_host(Config) -> -%An HTTP/1.1 request that lacks a host header must be rejected with -%a 400 status code and the closing of the connection. (RFC7230 5.4) -% -%%% @todo http/1.0 missing_host(Config) -> + +reject_missing_host(Config) -> + doc("An HTTP/1.1 request that lacks a host header must be rejected with " + "a 400 status code and the closing of the connection. (RFC7230 5.4)"), + #{code := 400, client := Client} = do_raw(Config, [ + "GET / HTTP/1.1\r\n" + "\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) -% -%reject_invalid_host(Config) -> -%A request with an invalid host header must be rejected with a -%400 status code and the closing of the connection. (RFC7230 5.4) -% -%reject_userinfo(Config) -> -%An authority component with a userinfo component (and its -%"@" delimiter) is invalid. The request must be rejected with -%a 400 status code and the closing of the connection. (RFC7230 2.7.1) -% -%reject_absolute_form_different_host(Config) -> -%When using absolute-form the URI authority component must be -%identical to the host header. Invalid requests must be rejected -%with a 400 status code and the closing of the connection. (RFC7230 5.4) -% + +reject_invalid_host(Config) -> + doc("A request with an invalid host header must be rejected with a " + "400 status code and the closing of the connection. (RFC7230 5.4)"), + #{code := 400, client := Client} = do_raw(Config, [ + "GET / HTTP/1.1\r\n" + "Host: localhost:port\r\n" + "\r\n"]), + {error, closed} = raw_recv(Client, 0, 1000). + +reject_userinfo(Config) -> + doc("An authority component with a userinfo component (and its " + "\"@\" delimiter) is invalid. The request must be rejected with " + "a 400 status code and the closing of the connection. (RFC7230 2.7.1)"), + #{code := 400, client := Client} = do_raw(Config, [ + "GET / HTTP/1.1\r\n" + "Host: user@localhost\r\n" + "\r\n"]), + {error, closed} = raw_recv(Client, 0, 1000). + +reject_absolute_form_different_host(Config) -> + doc("When using absolute-form the URI authority component must be " + "identical to the host header. Invalid requests must be rejected " + "with a 400 status code and the closing of the connection. (RFC7230 5.4)"), + #{code := 400, client := Client} = do_raw(Config, [ + "GET http://example.org/ HTTP/1.1\r\n" + "Host: localhost\r\n" + "\r\n"]), + {error, closed} = raw_recv(Client, 0, 1000). + %reject_authority_form_different_host(Config) -> %When using authority-form the URI authority component must be %identical to the host header. Invalid requests must be rejected %with a 400 status code and the closing of the connection. -% + %empty_host(Config) -> %The host header is empty when the authority component is undefined. (RFC7230 5.4) -% -%@todo -%The effective request URI can be rebuilt by concatenating scheme, -%"://", authority, path and query components. (RFC7230 5.5) -% + +%% The effective request URI can be rebuilt by concatenating scheme, +%% "://", authority, path and query components. (RFC7230 5.5) +%% +%% This is covered in req_SUITE in the tests for cowboy_req:uri/1,2. + %@todo %Resources with identical URI except for the scheme component %must be treated as different. (RFC7230 2.7.2) -% -%%% Response. -% + +%% Response. + %@todo %A server can send more than one response per request only when a %1xx response is sent preceding the final response. (RFC7230 5.6) |