diff options
Diffstat (limited to 'lib/inets/test')
-rw-r--r-- | lib/inets/test/http_format_SUITE.erl | 238 | ||||
-rw-r--r-- | lib/inets/test/httpc_SUITE.erl | 91 | ||||
-rw-r--r-- | lib/inets/test/httpd_1_1.erl | 11 | ||||
-rw-r--r-- | lib/inets/test/httpd_SUITE.erl | 71 | ||||
-rw-r--r-- | lib/inets/test/httpd_test_lib.erl | 20 | ||||
-rw-r--r-- | lib/inets/test/uri_SUITE.erl | 23 |
6 files changed, 311 insertions, 143 deletions
diff --git a/lib/inets/test/http_format_SUITE.erl b/lib/inets/test/http_format_SUITE.erl index a97b51601f..e977bd1b9b 100644 --- a/lib/inets/test/http_format_SUITE.erl +++ b/lib/inets/test/http_format_SUITE.erl @@ -20,26 +20,12 @@ %% -module(http_format_SUITE). --author('[email protected]'). -include_lib("common_test/include/ct.hrl"). --include("test_server_line.hrl"). -include("http_internal.hrl"). -%% Test server specific exports --export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, init_per_testcase/2, end_per_testcase/2]). - -%% Test cases must be exported. --export([ chunk_decode/1, chunk_encode/1, - chunk_extensions_otp_6005/1, chunk_decode_otp_6264/1, - chunk_decode_empty_chunk_otp_6511/1, - chunk_decode_trailer/1, - http_response/1, http_request/1, validate_request_line/1, - esi_parse_headers/1, cgi_parse_headers/1, - is_absolut_uri/1, convert_netscapecookie_date/1, - check_content_length_encoding/1]). - -suite() -> [{ct_hooks,[ts_install_cth]}]. +%% Note: This directive should only be used in test suites. +-compile(export_all). all() -> [{group, chunk}, http_response, http_request, @@ -52,7 +38,8 @@ groups() -> [chunk_decode, chunk_encode, chunk_extensions_otp_6005, chunk_decode_otp_6264, chunk_decode_empty_chunk_otp_6511, - chunk_decode_trailer]}]. + chunk_whitespace_suffix, + chunk_decode_trailer, chunk_max_headersize, chunk_max_bodysize, chunk_not_hex]}]. init_per_suite(Config) -> Config. @@ -81,12 +68,8 @@ end_per_testcase(_, Config) -> %% Test cases starts here. %%------------------------------------------------------------------------- - -%%------------------------------------------------------------------------- -chunk_decode(doc) -> - ["Test http_chunk:decode/3"]; -chunk_decode(suite) -> - []; +chunk_decode() -> + [{doc, "Test http_chunk:decode/3"}]. chunk_decode(Config) when is_list(Config) -> ReqHeaders = #http_request_h{'transfer-encoding' = "chunked"}, ChunkedBody = "A" ++ ?CRLF ++ "1234567890" ++ ?CRLF ++ "4" ++ @@ -109,15 +92,11 @@ chunk_decode(Config) when is_list(Config) -> ?HTTP_MAX_BODY_SIZE, ?HTTP_MAX_HEADER_SIZE), {_, Body} = parse(Module, Function, Args, tl(NewChunkedBody)), - "1234567890HEJ!" = binary_to_list(Body), - - ok. + "1234567890HEJ!" = binary_to_list(Body). %%------------------------------------------------------------------------- -chunk_extensions_otp_6005(doc) -> - ["Make sure so called extensions are ignored"]; -chunk_extensions_otp_6005(suite) -> - []; +chunk_extensions_otp_6005() -> + [{doc, "Make sure so called extensions are ignored"}]. chunk_extensions_otp_6005(Config) when is_list(Config)-> ChunkedBody = "A;ignore this" ++ ?CRLF ++ "1234567890" ++ ?CRLF ++ "4" ++ ?CRLF ++ "HEJ!"++ ?CRLF ++ "0" ++ @@ -136,14 +115,11 @@ chunk_extensions_otp_6005(Config) when is_list(Config)-> ?HTTP_MAX_BODY_SIZE, ?HTTP_MAX_HEADER_SIZE), {_, NewBody} = parse(Module1, Function1, Args1, tl(ChunkedBody1)), - "1234567890HEJ!" = binary_to_list(NewBody), - ok. + "1234567890HEJ!" = binary_to_list(NewBody). %%------------------------------------------------------------------------- -chunk_decode_otp_6264(doc) -> - ["Check that 0 in the body does not count as the last chunk"]; -chunk_decode_otp_6264(suite) -> - []; +chunk_decode_otp_6264() -> + [{doc, "Check that 0 in the body does not count as the last chunk"}]. chunk_decode_otp_6264(Config) when is_list(Config)-> ChunkedBody = "A;ignore this" ++ ?CRLF ++ "1234567890" ++ ?CRLF ++ "4" ++ ?CRLF ++ "0123"++ ?CRLF ++ "0" ++ @@ -173,27 +149,33 @@ chunk_decode_otp_6264(Config) when is_list(Config)-> ?HTTP_MAX_BODY_SIZE, ?HTTP_MAX_HEADER_SIZE), {_, NewBody} = parse(Module1, Function1, Args1, tl(NewChunkedBody1)), - "12345678900" = binary_to_list(NewBody), - - ok. + "12345678900" = binary_to_list(NewBody). %%------------------------------------------------------------------------- -chunk_decode_empty_chunk_otp_6511(doc) -> - [""]; -chunk_decode_empty_chunk_otp_6511(suite) -> - []; chunk_decode_empty_chunk_otp_6511(Config) when is_list(Config) -> ChunkedBody = "0" ++ ?CRLF ++ ?CRLF, {ok,{["content-length:0"],<<>>}} = http_chunk:decode(list_to_binary(ChunkedBody), - ?HTTP_MAX_BODY_SIZE, ?HTTP_MAX_HEADER_SIZE), - ok. + ?HTTP_MAX_BODY_SIZE, ?HTTP_MAX_HEADER_SIZE). %%------------------------------------------------------------------------- -chunk_decode_trailer(doc) -> - ["Make sure trailers are handled correctly. Trailers should" - "become new headers"]; -chunk_decode_trailer(suite) -> - []; +chunk_whitespace_suffix() -> + [{doc, "Test whitespace after chunked length header"}]. +chunk_whitespace_suffix(Config) when is_list(Config) -> + ChunkedBody = "1a ; ignore-stuff-here" ++ ?CRLF ++ + "abcdefghijklmnopqrstuvwxyz" ++ ?CRLF ++ "10 " ++ ?CRLF + ++ "1234567890abcdef" ++ ?CRLF ++ "0 " ++ ?CRLF + ++ "some-footer:some-value" ++ ?CRLF + ++ "another-footer:another-value" ++ ?CRLF ++ ?CRLF, + {ok, {["content-length:42", "another-footer:another-value", + "some-footer:some-value", ""], + <<"abcdefghijklmnopqrstuvwxyz1234567890abcdef">>}} = + http_chunk:decode(list_to_binary(ChunkedBody), + ?HTTP_MAX_BODY_SIZE, ?HTTP_MAX_HEADER_SIZE). + +%%------------------------------------------------------------------------- +chunk_decode_trailer() -> + [{doc,"Make sure trailers are handled correctly. Trailers should" + "become new headers"}]. chunk_decode_trailer(Config) when is_list(Config)-> ChunkedBody = "1a; ignore-stuff-here" ++ ?CRLF ++ "abcdefghijklmnopqrstuvwxyz" ++ ?CRLF ++ "10" ++ ?CRLF @@ -249,30 +231,79 @@ chunk_decode_trailer(Config) when is_list(Config)-> ?HTTP_MAX_BODY_SIZE, ?HTTP_MAX_HEADER_SIZE), {_, NewBody} = parse(Module1, Function1, Args1, tl(ChunkedBody3)), - "abcdefghijklmnopqrstuvwxyz1234567890abcdef" = binary_to_list(NewBody), - - ok. + "abcdefghijklmnopqrstuvwxyz1234567890abcdef" = binary_to_list(NewBody). %%------------------------------------------------------------------------- -chunk_encode(doc) -> - ["Test http_chunk:encode/1 & http_chunk:encode_last/0"]; -chunk_encode(suite) -> - []; +chunk_encode() -> + [{doc, "Test http_chunk:encode/1 & http_chunk:encode_last/0"}]. chunk_encode(Config) when is_list(Config) -> <<54, ?CR, ?LF, 102,111,111,98,97,114, ?CR, ?LF>> = http_chunk:encode(list_to_binary("foobar")), ["6", ?CR, ?LF,"foobar", ?CR, ?LF] = http_chunk:encode("foobar"), - <<$0, ?CR, ?LF, ?CR, ?LF >> = http_chunk:encode_last(), - ok. - + <<$0, ?CR, ?LF, ?CR, ?LF >> = http_chunk:encode_last(). +%%------------------------------------------------------------------------- +chunk_max_headersize() -> + [{doc, "Test max header limit"}]. +chunk_max_headersize(Config) when is_list(Config) -> + ChunkedBody = "1a; ignore-stuff-here" ++ ?CRLF ++ + "abcdefghijklmnopqrstuvwxyz" ++ ?CRLF ++ "10" ++ ?CRLF + ++ "1234567890abcdef" ++ ?CRLF ++ "0" ++ ?CRLF + ++ "some-footer:some-value" ++ ?CRLF + ++ "another-footer:another-value" ++ ?CRLF ++ ?CRLF, + + {ok, {_, _}} = + http_chunk:decode(list_to_binary(ChunkedBody), + ?HTTP_MAX_BODY_SIZE, ?HTTP_MAX_HEADER_SIZE), + + %% Too long in length header + {error,{header_too_long, {max, 1}}} = + (catch http_chunk:decode(list_to_binary(ChunkedBody), + ?HTTP_MAX_BODY_SIZE, 1)), + + %% Too long in extension field + {error,{header_too_long, {max, 10}}} = + (catch http_chunk:decode(list_to_binary(ChunkedBody), + ?HTTP_MAX_BODY_SIZE, 10)), + + %% Too long in trailer + {error,{header_too_long, {max, 30}}} = + (catch http_chunk:decode(list_to_binary(ChunkedBody), + ?HTTP_MAX_BODY_SIZE, 30)). +%%------------------------------------------------------------------------- +chunk_not_hex() -> + [{doc, "Test bad chunked length header"}]. +chunk_not_hex(Config) when is_list(Config) -> + ChunkedBody = "åäö; ignore-stuff-here" ++ ?CRLF ++ + "abcdefghijklmnopqrstuvwxyz" ++ ?CRLF ++ "10" ++ ?CRLF + ++ "1234567890abcdef" ++ ?CRLF ++ "0" ++ ?CRLF + ++ "some-footer:some-value" ++ ?CRLF + ++ "another-footer:another-value" ++ ?CRLF ++ ?CRLF, + {error,{chunk_size, "åäö"}} = + (catch http_chunk:decode(list_to_binary(ChunkedBody), + ?HTTP_MAX_BODY_SIZE, ?HTTP_MAX_HEADER_SIZE)). +%%------------------------------------------------------------------------- +chunk_max_bodysize() -> + [{doc, "Test max body limit"}]. +chunk_max_bodysize(Config) when is_list(Config) -> + ChunkedBody = "1a; ignore-stuff-here" ++ ?CRLF ++ + "abcdefghijklmnopqrstuvwxyz" ++ ?CRLF ++ "10" ++ ?CRLF + ++ "1234567890abcdef" ++ ?CRLF ++ "0" ++ ?CRLF + ++ "some-footer:some-value" ++ ?CRLF + ++ "another-footer:another-value" ++ ?CRLF ++ ?CRLF, + {ok, {_, _}} = + http_chunk:decode(list_to_binary(ChunkedBody), + ?HTTP_MAX_BODY_SIZE, ?HTTP_MAX_HEADER_SIZE), + + %% Too long body + {error,{body_too_big, {max, 10}}} = + (catch http_chunk:decode(list_to_binary(ChunkedBody), + 10, ?HTTP_MAX_HEADER_SIZE)). %%------------------------------------------------------------------------- -http_response(doc) -> - ["Test httpc_response:parse*. This test case will simulate that the " +http_response() -> + [{doc, "Test httpc_response:parse*. This test case will simulate that the " "message will be recived a little at the time on a socket and the " - "package may be broken up into smaller parts at arbitrary point."]; -http_response(suite) -> - []; + "package may be broken up into smaller parts at arbitrary point."}]. http_response(Config) when is_list(Config) -> HttpHead1 = ["HTTP", "/1.1 ", "20", "0 ", "ok", [?CR, ?LF], @@ -340,12 +371,10 @@ http_response(Config) when is_list(Config) -> [<<>>,Length1], HttpBody1)), ok. %%------------------------------------------------------------------------- -http_request(doc) -> - ["Test httpd_request:parse* This test case will simulate that the " +http_request() -> + [{doc, "Test httpd_request:parse* This test case will simulate that the " "message will be recived a little at the time on a socket and the " - "package may be broken up into smaller parts at arbitrary point."]; -http_request(suite) -> - []; + "package may be broken up into smaller parts at arbitrary point."}]. http_request(Config) when is_list(Config) -> HttpHead = ["GE", "T ", "http://www.erlang", ".org ", "HTTP", @@ -407,15 +436,12 @@ http_request(Config) when is_list(Config) -> NewBody1 = binary_to_list(parse (httpd_request, whole_body, - [<<>>, Length1], HttpBody1)), - ok. + [<<>>, Length1], HttpBody1)). %%------------------------------------------------------------------------- -validate_request_line(doc) -> - ["Test httpd_request:validate/3. Makes sure you can not get past" +validate_request_line() -> + [{doc, "Test httpd_request:validate/3. Makes sure you can not get past" " the server_root and that the request is recognized by the server" - " and protcol version." ]; -validate_request_line(suite) -> - []; + " and protcol version."}]. validate_request_line(Config) when is_list(Config) -> %% HTTP/0.9 only has GET requests @@ -468,16 +494,12 @@ validate_request_line(Config) when is_list(Config) -> NewForbiddenUri1 = "http://127.0.0.1:8888/../home/ingela/test.html", {error, {bad_request, {forbidden, NewForbiddenUri1}}} = - httpd_request:validate("GET", NewForbiddenUri1, "HTTP/1.1"), - - ok. + httpd_request:validate("GET", NewForbiddenUri1, "HTTP/1.1"). %%------------------------------------------------------------------------- -check_content_length_encoding(doc) -> - ["Test http_request:headers/2. Check that the content-length is" - " encoded even when it is zero." ]; -check_content_length_encoding(suite) -> - []; +check_content_length_encoding() -> + [{doc, "Test http_request:headers/2. Check that the content-length is" + " encoded even when it is zero."}]. check_content_length_encoding(Config) when is_list(Config) -> %% Check that the content-length is preserved. @@ -486,16 +508,12 @@ check_content_length_encoding(Config) when is_list(Config) -> true = (string:str(Header1, "content-length: 123\r\n") > 0), %% Check that content-length=0 is handled correctly. Header2 = http_request:http_headers(#http_request_h{'content-length'="0"}), - true = (string:str(Header2, "content-length: 0\r\n") > 0), - - ok. + true = (string:str(Header2, "content-length: 0\r\n") > 0). %%------------------------------------------------------------------------- -esi_parse_headers(doc) -> - ["Test httpd_esi:*. All header values are received in the same" - " erlang message."]; -esi_parse_headers(suite) -> - []; +esi_parse_headers() -> + [{doc, "Test httpd_esi:*. All header values are received in the same" + " erlang message."}]. esi_parse_headers(Config) when is_list(Config) -> ESIResult = "content-type:text/html\r\ndate:Thu, 28 Oct 2004 07:57:43 " @@ -522,16 +540,14 @@ esi_parse_headers(Config) when is_list(Config) -> httpd_esi:handle_headers(Headers2), {proceed,"/foo/bar.html"} = - httpd_esi:handle_headers("location:/foo/bar.html\r\n"), - ok. + httpd_esi:handle_headers("location:/foo/bar.html\r\n"). %%-------------------------------------------------------------------- -cgi_parse_headers(doc) -> - ["Test httpd_cgi:*. This test case will simulate that the " +cgi_parse_headers() -> + [{doc, "Test httpd_cgi:*. This test case will simulate that the " "message will be recived a little at the time on a socket and the " - "package may be broken up into smaller parts at arbitrary point."]; -cgi_parse_headers(suite) -> - []; + "package may be broken up into smaller parts at arbitrary point."}]. + cgi_parse_headers(Config) when is_list(Config) -> CGIResult = ["content-type:text", "/html\ndate:Thu, 28 Oct 2004 07:57:43 " @@ -567,26 +583,18 @@ cgi_parse_headers(Config) when is_list(Config) -> {ok,[{"content-type","text/html"}, {"connection","close"}, {"content-language","en"}, - {"age","4711"}], {200,"ok"}} = httpd_cgi:handle_headers(Headers3), - - ok. - + {"age","4711"}], {200,"ok"}} = httpd_cgi:handle_headers(Headers3). %%------------------------------------------------------------------------- -is_absolut_uri(doc) -> - ["Test http_request:is_absolut_uri/1."]; -is_absolut_uri(suite) -> - []; +is_absolut_uri() -> + [{doc, "Test http_request:is_absolut_uri/1."}]. is_absolut_uri(Config) when is_list(Config) -> true = http_request:is_absolut_uri("http://www.erlang.org"), true = http_request:is_absolut_uri("https://www.erlang.org"), false = http_request:is_absolut_uri("index.html"). - %%------------------------------------------------------------------------- -convert_netscapecookie_date(doc) -> - ["Test http_util:convert_netscapecookie_date/1."]; -convert_netscapecookie_date(suite) -> - []; +convert_netscapecookie_date() -> + [{doc, "Test http_util:convert_netscapecookie_date/1."}]. convert_netscapecookie_date(Config) when is_list(Config) -> {{2006,1,6},{8,59,38}} = http_util:convert_netscapecookie_date("Mon, 06-Jan-2006 08:59:38 GMT"), @@ -619,9 +627,7 @@ convert_netscapecookie_date(Config) when is_list(Config) -> {{2006,12,12},{8,59,38}} = http_util:convert_netscapecookie_date("Sun 12-Dec-06 08:59:38 GMT"), {{2036,1,1},{8,0,1}} = - http_util:convert_netscapecookie_date("Tue Jan 01 08:00:01 2036 GMT"), - ok. - + http_util:convert_netscapecookie_date("Tue Jan 01 08:00:01 2036 GMT"). %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl index 5b40d08859..c6c59ab1af 100644 --- a/lib/inets/test/httpc_SUITE.erl +++ b/lib/inets/test/httpc_SUITE.erl @@ -98,13 +98,17 @@ only_simulated() -> stream_once, stream_single_chunk, stream_no_length, + not_streamed_once, + stream_large_not_200_or_206, no_content_204, tolerate_missing_CR, userinfo, bad_response, internal_server_error, invalid_http, + invalid_chunk_size, headers_dummy, + headers_with_obs_fold, empty_response_header, remote_socket_close, remote_socket_close_async, @@ -407,6 +411,21 @@ stream_no_length(Config) when is_list(Config) -> stream_test(Request1, {stream, self}), Request2 = {url(group_name(Config), "/http_1_0_no_length_multiple.html", Config), []}, stream_test(Request2, {stream, self}). +%%------------------------------------------------------------------------- +stream_large_not_200_or_206() -> + [{doc, "Test the option stream for large responses with status codes " + "other than 200 or 206" }]. +stream_large_not_200_or_206(Config) when is_list(Config) -> + Request = {url(group_name(Config), "/large_404_response.html", Config), []}, + {404, _} = not_streamed_test(Request, {stream, self}). +%%------------------------------------------------------------------------- +not_streamed_once() -> + [{doc, "Test not streamed responses with once streaming"}]. +not_streamed_once(Config) when is_list(Config) -> + Request0 = {url(group_name(Config), "/404.html", Config), []}, + {404, _} = not_streamed_test(Request0, {stream, {self, once}}), + Request1 = {url(group_name(Config), "/404_chunked.html", Config), []}, + {404, _} = not_streamed_test(Request1, {stream, {self, once}}). %%------------------------------------------------------------------------- @@ -747,6 +766,22 @@ invalid_http(Config) when is_list(Config) -> ct:print("Parse error: ~p ~n", [Reason]). %%------------------------------------------------------------------------- + +invalid_chunk_size(doc) -> + ["Test parse error of HTTP chunk size"]; +invalid_chunk_size(suite) -> + []; +invalid_chunk_size(Config) when is_list(Config) -> + + URL = url(group_name(Config), "/invalid_chunk_size.html", Config), + + {error, {chunk_size, _} = Reason} = + httpc:request(get, {URL, []}, [], []), + + ct:print("Parse error: ~p ~n", [Reason]). + +%%------------------------------------------------------------------------- + emulate_lower_versions(doc) -> [{doc, "Perform request as 0.9 and 1.0 clients."}]; emulate_lower_versions(Config) when is_list(Config) -> @@ -893,6 +928,13 @@ headers_dummy(Config) when is_list(Config) -> %%------------------------------------------------------------------------- +headers_with_obs_fold(Config) when is_list(Config) -> + Request = {url(group_name(Config), "/obs_folded_headers.html", Config), []}, + {ok, {{_,200,_}, Headers, [_|_]}} = httpc:request(get, Request, [], []), + "a b" = proplists:get_value("folded", Headers). + +%%------------------------------------------------------------------------- + invalid_headers(Config) -> Request = {url(group_name(Config), "/dummy.html", Config), [{"cookie", undefined}]}, {error, _} = httpc:request(get, Request, [], []). @@ -1109,6 +1151,19 @@ stream_test(Request, To) -> Body = binary_to_list(StreamedBody). +not_streamed_test(Request, To) -> + {ok, {{_,Code,_}, [_ | _], Body}} = + httpc:request(get, Request, [], [{body_format, binary}]), + {ok, RequestId} = + httpc:request(get, Request, [], [{body_format, binary}, {sync, false}, To]), + + receive + {http, {RequestId, {{_, Code, _}, _Headers, Body}}} -> + {Code, binary_to_list(Body)}; + {http, Msg} -> + ct:fail(Msg) + end. + url(http, End, Config) -> Port = ?config(port, Config), {ok,Host} = inet:gethostname(), @@ -1640,6 +1695,11 @@ handle_uri(_,"/307.html",Port,_,Socket,_) -> "Content-Length:" ++ integer_to_list(length(Body)) ++ "\r\n\r\n" ++ Body; +handle_uri(_,"/404.html",_,_,_,_) -> + "HTTP/1.1 404 not found\r\n" ++ + "Content-Length:14\r\n\r\n" ++ + "Page not found"; + handle_uri(_,"/500.html",_,_,_,_) -> "HTTP/1.1 500 Internal Server Error\r\n" ++ "Content-Length:47\r\n\r\n" ++ @@ -1713,6 +1773,13 @@ handle_uri(_,"/dummy_headers.html",_,_,Socket,_) -> send(Socket, http_chunk:encode("obar</BODY></HTML>")), http_chunk:encode_last(); +handle_uri(_,"/obs_folded_headers.html",_,_,_,_) -> + "HTTP/1.1 200 ok\r\n" + "Content-Length:5\r\n" + "Folded: a\r\n" + " b\r\n\r\n" + "Hello"; + handle_uri(_,"/capital_transfer_encoding.html",_,_,Socket,_) -> Head = "HTTP/1.1 200 ok\r\n" ++ "Transfer-Encoding:Chunked\r\n\r\n", @@ -1768,6 +1835,15 @@ handle_uri(_,"/once_chunked.html",_,_,Socket,_) -> http_chunk:encode("obar</BODY></HTML>")), http_chunk:encode_last(); +handle_uri(_,"/404_chunked.html",_,_,Socket,_) -> + Head = "HTTP/1.1 404 not found\r\n" ++ + "Transfer-Encoding:Chunked\r\n\r\n", + send(Socket, Head), + send(Socket, http_chunk:encode("<HTML><BODY>Not ")), + send(Socket, + http_chunk:encode("found</BODY></HTML>")), + http_chunk:encode_last(); + handle_uri(_,"/single_chunk.html",_,_,Socket,_) -> Chunk = "HTTP/1.1 200 ok\r\n" ++ "Transfer-Encoding:Chunked\r\n\r\n" ++ @@ -1792,6 +1868,17 @@ handle_uri(_,"/http_1_0_no_length_multiple.html",_,_,Socket,_) -> send(Socket, string:copies("other multiple packets ", 200)), close(Socket); +handle_uri(_,"/large_404_response.html",_,_,Socket,_) -> + %% long body to make sure it will be sent in multiple tcp packets + Body = string:copies("other multiple packets ", 200), + Head = io_lib:format("HTTP/1.1 404 not found\r\n" + "Content-length: ~B\r\n" + "Content-type: text/plain\r\n\r\n", + [length(Body)]), + send(Socket, Head), + send(Socket, Body), + close(Socket); + handle_uri(_,"/once.html",_,_,Socket,_) -> Head = "HTTP/1.1 200 ok\r\n" ++ "Content-Length:32\r\n\r\n", @@ -1806,6 +1893,10 @@ handle_uri(_,"/invalid_http.html",_,_,_,_) -> "HTTP/1.1 301\r\nDate:Sun, 09 Dec 2007 13:04:18 GMT\r\n" ++ "Transfer-Encoding:chunked\r\n\r\n"; +handle_uri(_,"/invalid_chunk_size.html",_,_,_,_) -> + "HTTP/1.1 200 ok\r\n" ++ + "Transfer-Encoding:chunked\r\n\r\nåäö\r\n"; + handle_uri(_,"/missing_reason_phrase.html",_,_,_,_) -> "HTTP/1.1 200\r\n" ++ "Content-Length: 32\r\n\r\n" diff --git a/lib/inets/test/httpd_1_1.erl b/lib/inets/test/httpd_1_1.erl index dd9d21bbfc..db6def9d17 100644 --- a/lib/inets/test/httpd_1_1.erl +++ b/lib/inets/test/httpd_1_1.erl @@ -24,7 +24,7 @@ -include_lib("kernel/include/file.hrl"). -export([host/4, chunked/4, expect/4, range/4, if_test/5, trace/4, - head/4, mod_cgi_chunked_encoding_test/5]). + head/4, mod_cgi_chunked_encoding_test/5, mod_esi_chunk_timeout/4]). %% -define(all_keys_lower_case,true). -ifndef(all_keys_lower_case). @@ -274,6 +274,15 @@ mod_cgi_chunked_encoding_test(Type, Port, Host, Node, [Request| Rest])-> [{statuscode, 200}]), mod_cgi_chunked_encoding_test(Type, Port, Host, Node, Rest). + +mod_esi_chunk_timeout(Type, Port, Host, Node) -> + ok = httpd_test_lib:verify_request(Type, Host, Port, Node, + "GET /cgi-bin/erl/httpd_example/chunk_timeout?input=20000 HTTP/1.1\r\n" + "Host:"++ Host ++"\r\n" + "\r\n", + [{statuscode, 200}, + {header, "warning"}]). + %%-------------------------------------------------------------------- %% Internal functions %%-------------------------------------------------------------------- diff --git a/lib/inets/test/httpd_SUITE.erl b/lib/inets/test/httpd_SUITE.erl index a6236f828a..1d8a603981 100644 --- a/lib/inets/test/httpd_SUITE.erl +++ b/lib/inets/test/httpd_SUITE.erl @@ -97,7 +97,7 @@ groups() -> {https_reload, [], [{group, reload}]}, {http_mime_types, [], [alias_1_1, alias_1_0, alias_0_9]}, {limit, [], [max_clients_1_1, max_clients_1_0, max_clients_0_9]}, - {custom, [], [customize]}, + {custom, [], [customize, add_default]}, {reload, [], [non_disturbing_reconfiger_dies, disturbing_reconfiger_dies, non_disturbing_1_1, @@ -117,7 +117,7 @@ groups() -> {htaccess, [], [htaccess_1_1, htaccess_1_0, htaccess_0_9]}, {security, [], [security_1_1, security_1_0]}, %% Skip 0.9 as causes timing issus in test code {http_1_1, [], [host, chunked, expect, cgi, cgi_chunked_encoding_test, - trace, range, if_modified_since] ++ http_head() ++ http_get() ++ load()}, + trace, range, if_modified_since, mod_esi_chunk_timeout] ++ http_head() ++ http_get() ++ load()}, {http_1_0, [], [host, cgi, trace] ++ http_head() ++ http_get() ++ load()}, {http_0_9, [], http_head() ++ http_get() ++ load()} ]. @@ -757,6 +757,13 @@ esi(Config) when is_list(Config) -> Config, [{statuscode, 200}, {no_header, "cache-control"}]). %%------------------------------------------------------------------------- +mod_esi_chunk_timeout(Config) when is_list(Config) -> + ok = httpd_1_1:mod_esi_chunk_timeout(?config(type, Config), + ?config(port, Config), + ?config(host, Config), + ?config(node, Config)). + +%%------------------------------------------------------------------------- cgi() -> [{doc, "Test mod_cgi"}]. @@ -1003,10 +1010,23 @@ customize(Config) when is_list(Config) -> {no_header, "Server"}, {version, Version}]). -response_header({"server", _}) -> - false; -response_header(Header) -> - {true, Header}. +add_default() -> + [{doc, "Test adding default header with custom callback"}]. + +add_default(Config) when is_list(Config) -> + Version = "HTTP/1.1", + Host = ?config(host, Config), + Type = ?config(type, Config), + ok = httpd_test_lib:verify_request(?config(type, Config), Host, + ?config(port, Config), + transport_opts(Type, Config), + ?config(node, Config), + http_request("GET /index.html ", Version, Host), + [{statuscode, 200}, + {header, "Content-Type", "text/html"}, + {header, "Date", "Override-date"}, + {header, "X-Frame-Options"}, + {version, Version}]). %%------------------------------------------------------------------------- max_header() -> @@ -1421,13 +1441,15 @@ server_config(http_reload, Config) -> server_config(https_reload, Config) -> [{keep_alive_timeout, 2}] ++ server_config(https, Config); server_config(http_limit, Config) -> - [{max_clients, 1}, - %% Make sure option checking code is run - {max_content_length, 100000002}] ++ server_config(http, Config); + Conf = [{max_clients, 1}, + %% Make sure option checking code is run + {max_content_length, 100000002}] ++ server_config(http, Config), + ct:pal("Received message ~p~n", [Conf]), + Conf; server_config(http_custom, Config) -> - [{custom, ?MODULE}] ++ server_config(http, Config); + [{customize, ?MODULE}] ++ server_config(http, Config); server_config(https_custom, Config) -> - [{custom, ?MODULE}] ++ server_config(https, Config); + [{customize, ?MODULE}] ++ server_config(https, Config); server_config(https_limit, Config) -> [{max_clients, 1}] ++ server_config(https, Config); server_config(http_basic_auth, Config) -> @@ -1473,6 +1495,7 @@ server_config(http_mime_types, Config0) -> server_config(http, Config) -> ServerRoot = ?config(server_root, Config), [{port, 0}, + {socket_type, {ip_comm, [{nodelay, true}]}}, {server_name,"httpd_test"}, {server_root, ServerRoot}, {document_root, ?config(doc_root, Config)}, @@ -1494,13 +1517,14 @@ server_config(http, Config) -> server_config(https, Config) -> PrivDir = ?config(priv_dir, Config), [{socket_type, {essl, - [{cacertfile, - filename:join(PrivDir, "public_key_cacert.pem")}, - {certfile, - filename:join(PrivDir, "public_key_cert.pem")}, - {keyfile, - filename:join(PrivDir, "public_key_cert_key.pem")} - ]}}] ++ server_config(http, Config). + [{nodelay, true}, + {cacertfile, + filename:join(PrivDir, "public_key_cacert.pem")}, + {certfile, + filename:join(PrivDir, "public_key_cert.pem")}, + {keyfile, + filename:join(PrivDir, "public_key_cert_key.pem")} + ]}}] ++ proplists:delete(socket_type, server_config(http, Config)). init_httpd(Group, Config0) -> Config1 = proplists:delete(port, Config0), @@ -2030,3 +2054,14 @@ typestr(ip_comm) -> "tcp"; typestr(_) -> "ssl". + +response_header({"server", _}) -> + false; +response_header(Header) -> + {true, Header}. + +response_default_headers() -> + [%% Add new header + {"X-Frame-Options", "SAMEORIGIN"}, + %% Override built-in default + {"Date", "Override-date"}]. diff --git a/lib/inets/test/httpd_test_lib.erl b/lib/inets/test/httpd_test_lib.erl index cb2e86c81e..c58966ce10 100644 --- a/lib/inets/test/httpd_test_lib.erl +++ b/lib/inets/test/httpd_test_lib.erl @@ -235,11 +235,17 @@ validate(RequestStr, #state{status_line = {Version, StatusCode, _}, _ -> ok end, - do_validate(http_response:header_list(Headers), Options, N, P), - check_body(RequestStr, StatusCode, - Headers#http_response_h.'content-type', - list_to_integer(Headers#http_response_h.'content-length'), - Body). + HList = http_response:header_list(Headers), + do_validate(HList, Options, N, P), + case lists:keysearch("warning", 1, HList) of + {value, _} -> + ok; + _ -> + check_body(RequestStr, StatusCode, + Headers#http_response_h.'content-type', + list_to_integer(Headers#http_response_h.'content-length'), + Body) + end. %-------------------------------------------------------------------- %% Internal functions @@ -294,9 +300,9 @@ do_validate(Header, [{header, HeaderField, Value}|Rest],N,P) -> {value, {LowerHeaderField, Value}} -> ok; false -> - ct:fail({wrong_header_field_value, LowerHeaderField, Header}); + ct:fail({wrong_header_field_value, LowerHeaderField, Header, Value}); _ -> - ct:fail({wrong_header_field_value, LowerHeaderField, Header}) + ct:fail({wrong_header_field_value, LowerHeaderField, Header, Value}) end, do_validate(Header, Rest, N, P); do_validate(Header,[{no_header, HeaderField}|Rest],N,P) -> diff --git a/lib/inets/test/uri_SUITE.erl b/lib/inets/test/uri_SUITE.erl index bfcd7bd339..2642b8fd4e 100644 --- a/lib/inets/test/uri_SUITE.erl +++ b/lib/inets/test/uri_SUITE.erl @@ -49,7 +49,8 @@ all() -> queries, fragments, escaped, - hexed_query + hexed_query, + scheme_validation ]. %%-------------------------------------------------------------------- @@ -175,6 +176,26 @@ hexed_query(Config) when is_list(Config) -> verify_uri(URI2, Verify2), verify_uri(URI3, Verify3). +scheme_validation(Config) when is_list(Config) -> + {ok, {http,[],"localhost",80,"/",""}} = + http_uri:parse("http://localhost#fragment"), + + ValidationFun = + fun("http") -> valid; + (_) -> {error, bad_scheme} + end, + + {ok, {http,[],"localhost",80,"/",""}} = + http_uri:parse("http://localhost#fragment", + [{scheme_validation_fun, ValidationFun}]), + {error, bad_scheme} = + http_uri:parse("https://localhost#fragment", + [{scheme_validation_fun, ValidationFun}]), + %% non-fun scheme_validation_fun works as no option passed + {ok, {https,[],"localhost",443,"/",""}} = + http_uri:parse("https://localhost#fragment", + [{scheme_validation_fun, none}]). + %%-------------------------------------------------------------------- %% Internal Functions ------------------------------------------------ |