From f8750f121176c6cedc7b3162b6656ce201c9fe97 Mon Sep 17 00:00:00 2001 From: Kirilll Zaborsky Date: Mon, 20 Jul 2015 16:38:33 +0300 Subject: inets: fix suppport of HTTP headers with obs-fold httpc should not fail when response contains (now deprecated) multiline HTTP headers constructed with obs-folds. And as RFC7230 specifies user agent should replace obs-folds with spaces. --- lib/inets/test/httpc_SUITE.erl | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'lib/inets/test/httpc_SUITE.erl') diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl index 5b40d08859..2ad00bdf76 100644 --- a/lib/inets/test/httpc_SUITE.erl +++ b/lib/inets/test/httpc_SUITE.erl @@ -105,6 +105,7 @@ only_simulated() -> internal_server_error, invalid_http, headers_dummy, + headers_with_obs_fold, empty_response_header, remote_socket_close, remote_socket_close_async, @@ -893,6 +894,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, [], []). @@ -1713,6 +1721,13 @@ handle_uri(_,"/dummy_headers.html",_,_,Socket,_) -> send(Socket, http_chunk:encode("obar")), 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", -- cgit v1.2.3 From f4b02cf574552f40ff354261b4c7cf02cb568212 Mon Sep 17 00:00:00 2001 From: Kirilll Zaborsky Date: Tue, 20 Jan 2015 21:06:13 +0300 Subject: inets: send correct nonstreamed response with streaming httpc_handler should respond with correct and complete responses seeing non-streamed status codes i.e. codes other than 200 or 206. --- lib/inets/test/httpc_SUITE.erl | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'lib/inets/test/httpc_SUITE.erl') diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl index 2ad00bdf76..cc0fa5d4d9 100644 --- a/lib/inets/test/httpc_SUITE.erl +++ b/lib/inets/test/httpc_SUITE.erl @@ -98,6 +98,7 @@ only_simulated() -> stream_once, stream_single_chunk, stream_no_length, + stream_large_not_200_or_206, no_content_204, tolerate_missing_CR, userinfo, @@ -408,6 +409,13 @@ 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,_}, _, _} = non_streamed_async_test(Request, {stream, self}). %%------------------------------------------------------------------------- @@ -1117,6 +1125,19 @@ stream_test(Request, To) -> Body = binary_to_list(StreamedBody). +non_streamed_async_test(Request, To) -> + {ok, Response} = + httpc:request(get, Request, [], [{body_format, binary}]), + {ok, RequestId} = + httpc:request(get, Request, [], [{sync, false}, To]), + + receive + {http, {RequestId, Response}} -> + Response; + {http, Msg} -> + ct:fail(Msg) + end. + url(http, End, Config) -> Port = ?config(port, Config), {ok,Host} = inet:gethostname(), @@ -1807,6 +1828,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", -- cgit v1.2.3 From 45251cd60ebad4ef08ffc7cb0797d1fd7a603eea Mon Sep 17 00:00:00 2001 From: Kirilll Zaborsky Date: Wed, 23 Sep 2015 16:51:33 +0300 Subject: inets: fix {self, once} for not streamed request httpc should work properly if streaming option {self, once} is chosen and the corresponding response does not get streamed. --- lib/inets/test/httpc_SUITE.erl | 43 ++++++++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 10 deletions(-) (limited to 'lib/inets/test/httpc_SUITE.erl') diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl index cc0fa5d4d9..989563cdbc 100644 --- a/lib/inets/test/httpc_SUITE.erl +++ b/lib/inets/test/httpc_SUITE.erl @@ -98,6 +98,7 @@ 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, @@ -415,7 +416,15 @@ stream_large_not_200_or_206() -> "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,_}, _, _} = non_streamed_async_test(Request, {stream, self}). + {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}}). %%------------------------------------------------------------------------- @@ -1125,18 +1134,18 @@ stream_test(Request, To) -> Body = binary_to_list(StreamedBody). -non_streamed_async_test(Request, To) -> - {ok, Response} = +not_streamed_test(Request, To) -> + {ok, {{_,Code,_}, [_ | _], Body}} = httpc:request(get, Request, [], [{body_format, binary}]), {ok, RequestId} = - httpc:request(get, Request, [], [{sync, false}, To]), + httpc:request(get, Request, [], [{body_format, binary}, {sync, false}, To]), - receive - {http, {RequestId, Response}} -> - Response; - {http, Msg} -> - ct:fail(Msg) - end. + 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), @@ -1669,6 +1678,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" ++ @@ -1804,6 +1818,15 @@ handle_uri(_,"/once_chunked.html",_,_,Socket,_) -> http_chunk:encode("obar")), 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("Not ")), + send(Socket, + http_chunk:encode("found")), + 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" ++ -- cgit v1.2.3 From 25c9d0c38d659cc00db461d760f66369e9024c54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20Wei=C3=9Fl?= Date: Sat, 14 Nov 2015 16:29:13 +0100 Subject: inets: Terminate really gracefully on bad chunk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Without this fix, httpc:request/1 crashes the httpc_handler when an invalid chunked length header is encountered (since 77acb47): =ERROR REPORT==== 14-Nov-2015::17:19:30 === ** Generic server <0.651.0> terminating ** Last message in was {tcp,#Port<0.5714>, <<"HTTP/1.1 200 ok\r\nTransfer-Encoding:chunked\r\n\r\nåäö\r\n">>} ** When Server state == {state, [...] ** Reason for termination == ** {bad_return_value,{error,{chunk_size,"åäö"}}} --- lib/inets/test/httpc_SUITE.erl | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'lib/inets/test/httpc_SUITE.erl') diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl index 989563cdbc..c6c59ab1af 100644 --- a/lib/inets/test/httpc_SUITE.erl +++ b/lib/inets/test/httpc_SUITE.erl @@ -106,6 +106,7 @@ only_simulated() -> bad_response, internal_server_error, invalid_http, + invalid_chunk_size, headers_dummy, headers_with_obs_fold, empty_response_header, @@ -765,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) -> @@ -1876,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" -- cgit v1.2.3