From e924382a93907437f4d3631350d0f02137c1e030 Mon Sep 17 00:00:00 2001 From: Magnus Froberg Date: Tue, 14 Sep 2010 15:54:26 +0200 Subject: [PATCH 01/17] add a space after : separator According to HTTP spec, space is a MAY but preferred way to separate HTTP header name and field value. Not having a space there can cause problems. --- src/lhttpc_lib.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lhttpc_lib.erl b/src/lhttpc_lib.erl index 239e056a..2f6d47eb 100644 --- a/src/lhttpc_lib.erl +++ b/src/lhttpc_lib.erl @@ -179,7 +179,7 @@ format_hdrs(Headers) -> format_hdrs([{Hdr, Value} | T], Acc) -> NewAcc = [ - maybe_atom_to_list(Hdr), ":", maybe_atom_to_list(Value), "\r\n" | Acc + maybe_atom_to_list(Hdr), ": ", maybe_atom_to_list(Value), "\r\n" | Acc ], format_hdrs(T, NewAcc); format_hdrs([], Acc) -> From fe19bba37fc35f304db9d82054aa2930103475bb Mon Sep 17 00:00:00 2001 From: Fabian Linzberger Date: Tue, 31 Aug 2010 16:47:47 +0200 Subject: [PATCH 02/17] add .gitignore files for doc and ebin directories --- doc/.gitignore | 4 ++++ ebin/.gitignore | 2 ++ 2 files changed, 6 insertions(+) create mode 100644 doc/.gitignore create mode 100644 ebin/.gitignore diff --git a/doc/.gitignore b/doc/.gitignore new file mode 100644 index 00000000..e898d316 --- /dev/null +++ b/doc/.gitignore @@ -0,0 +1,4 @@ +edoc-info +erlang.png +stylesheet.css +*.html diff --git a/ebin/.gitignore b/ebin/.gitignore new file mode 100644 index 00000000..1d35c7cc --- /dev/null +++ b/ebin/.gitignore @@ -0,0 +1,2 @@ +lhttpc.app +*.beam From 679b5f1733396ab3b7866cc6fbd52675ff45d51c Mon Sep 17 00:00:00 2001 From: Richard Carlsson Date: Wed, 17 Aug 2011 18:49:36 +0200 Subject: [PATCH 03/17] fix some edoc-warnings --- src/lhttpc.erl | 3 --- src/lhttpc_client.erl | 3 --- src/lhttpc_lib.erl | 3 --- src/lhttpc_manager.erl | 2 -- src/lhttpc_sock.erl | 2 -- 5 files changed, 13 deletions(-) diff --git a/src/lhttpc.erl b/src/lhttpc.erl index b175ee2e..974e2714 100644 --- a/src/lhttpc.erl +++ b/src/lhttpc.erl @@ -27,9 +27,6 @@ %%% @author Oscar Hellström %%% @doc Main interface to the lightweight http client. %%% See {@link request/4}, {@link request/5} and {@link request/6} functions. -%%% @end -%%% @type boolean() = bool(). -%%% @type iolist() = [] | binary() | [char() | binary() | iolist()]. -module(lhttpc). -behaviour(application). diff --git a/src/lhttpc_client.erl b/src/lhttpc_client.erl index d93bfab3..5f5db174 100644 --- a/src/lhttpc_client.erl +++ b/src/lhttpc_client.erl @@ -29,9 +29,6 @@ %%% @doc %%% This module implements the HTTP request handling. This should normally %%% not be called directly since it should be spawned by the lhttpc module. -%%% @end -%%% @type boolean() = bool(). -%%% @type iolist() = [] | binary() | [char() | binary() | iolist()]. -module(lhttpc_client). -export([request/9]). diff --git a/src/lhttpc_lib.erl b/src/lhttpc_lib.erl index 2f6d47eb..07eb6cee 100644 --- a/src/lhttpc_lib.erl +++ b/src/lhttpc_lib.erl @@ -28,9 +28,6 @@ %%% @author Oscar Hellström %%% @doc %%% This module implements various library functions used in lhttpc. -%%% @end -%%% @type boolean() = boolean(). -%%% @type iolist() = [] | binary() | [char() | binary() | iolist()]. -module(lhttpc_lib). -export([ diff --git a/src/lhttpc_manager.erl b/src/lhttpc_manager.erl index d8bb111d..4ac4ec2b 100644 --- a/src/lhttpc_manager.erl +++ b/src/lhttpc_manager.erl @@ -31,8 +31,6 @@ %%% `connection_count/0' and `connection_count/1'. %%% The gen_server is supposed to be started by a supervisor, which is %%% normally {@link lhttpc_sup}. -%%% @end -%%% @type boolean() = bool(). -module(lhttpc_manager). -export([ diff --git a/src/lhttpc_sock.erl b/src/lhttpc_sock.erl index b742fafa..c8669b58 100644 --- a/src/lhttpc_sock.erl +++ b/src/lhttpc_sock.erl @@ -29,8 +29,6 @@ %%% @doc %%% This module implements wrappers for socket operations. %%% Makes it possible to have the same interface to ssl and tcp sockets. -%%% @end -%%% @type boolean() = bool(). -module(lhttpc_sock). -export([ From 6f7c563eded9504df5b2854260a83f04af17a9b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Hellstr=C3=B6m?= Date: Wed, 7 Sep 2011 09:10:14 +0100 Subject: [PATCH 04/17] Make lhttpc_client check the return value from lhttpc_sock:setopts, if setopts returns an error, we can't use the socket... --- src/lhttpc_client.erl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/lhttpc_client.erl b/src/lhttpc_client.erl index 5f5db174..ac0cb77e 100644 --- a/src/lhttpc_client.erl +++ b/src/lhttpc_client.erl @@ -244,7 +244,7 @@ check_send_result(#client_state{socket = Sock, ssl = Ssl}, {error, Reason}) -> throw(Reason). read_response(#client_state{socket = Socket, ssl = Ssl} = State) -> - lhttpc_sock:setopts(Socket, [{packet, http}], Ssl), + ok = lhttpc_sock:setopts(Socket, [{packet, http}], Ssl), read_response(State, nil, {nil, nil}, []). read_response(State, Vsn, {StatusCode, _} = Status, Hdrs) -> @@ -266,7 +266,7 @@ read_response(State, Vsn, {StatusCode, _} = Status, Hdrs) -> % status responses MAY be ignored by a user agent. read_response(State, nil, {nil, nil}, []); {ok, http_eoh} -> - lhttpc_sock:setopts(Socket, [{packet, raw}], Ssl), + ok = lhttpc_sock:setopts(Socket, [{packet, raw}], Ssl), Response = handle_response_body(State, Vsn, Status, Hdrs), NewHdrs = element(2, Response), ReqHdrs = State#client_state.request_headers, @@ -474,7 +474,7 @@ read_partial_chunked_body(State, Hdrs, Window, BufferSize, Buffer, RemSize) -> end. read_chunk_size(Socket, Ssl) -> - lhttpc_sock:setopts(Socket, [{packet, line}], Ssl), + ok = lhttpc_sock:setopts(Socket, [{packet, line}], Ssl), case lhttpc_sock:recv(Socket, Ssl) of {ok, ChunkSizeExt} -> chunk_size(ChunkSizeExt); @@ -527,7 +527,7 @@ chunk_size(<>, Chars) -> read_partial_chunk(Socket, Ssl, ChunkSize, ChunkSize) -> {read_chunk(Socket, Ssl, ChunkSize), 0}; read_partial_chunk(Socket, Ssl, Size, ChunkSize) -> - lhttpc_sock:setopts(Socket, [{packet, raw}], Ssl), + ok = lhttpc_sock:setopts(Socket, [{packet, raw}], Ssl), case lhttpc_sock:recv(Socket, Size, Ssl) of {ok, Chunk} -> {Chunk, ChunkSize - Size}; @@ -536,7 +536,7 @@ read_partial_chunk(Socket, Ssl, Size, ChunkSize) -> end. read_chunk(Socket, Ssl, Size) -> - lhttpc_sock:setopts(Socket, [{packet, raw}], Ssl), + ok = lhttpc_sock:setopts(Socket, [{packet, raw}], Ssl), case lhttpc_sock:recv(Socket, Size + 2, Ssl) of {ok, <>} -> Chunk; @@ -547,7 +547,7 @@ read_chunk(Socket, Ssl, Size) -> end. read_trailers(Socket, Ssl, Trailers, Hdrs) -> - lhttpc_sock:setopts(Socket, [{packet, httph}], Ssl), + ok = lhttpc_sock:setopts(Socket, [{packet, httph}], Ssl), case lhttpc_sock:recv(Socket, Ssl) of {ok, http_eoh} -> {Trailers, Hdrs}; From 0fd4a6e3601905debf89316440986bb8703f8c45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Hellstr=C3=B6m?= Date: Wed, 7 Sep 2011 09:48:48 +0100 Subject: [PATCH 05/17] Raise the timeout again, the test fails on slow machines... --- test/lhttpc_tests.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/lhttpc_tests.erl b/test/lhttpc_tests.erl index ad35e56b..397741b0 100644 --- a/test/lhttpc_tests.erl +++ b/test/lhttpc_tests.erl @@ -663,14 +663,14 @@ ssl_post() -> ssl_chunked() -> Port = start(ssl, [fun chunked_response/5, fun chunked_response_t/5]), URL = ssl_url(Port, "/ssl_chunked"), - FirstResult = lhttpc:request(URL, get, [], 100), + FirstResult = lhttpc:request(URL, get, [], 1000), ?assertMatch({ok, _}, FirstResult), {ok, FirstResponse} = FirstResult, ?assertEqual({200, "OK"}, status(FirstResponse)), ?assertEqual(<>, body(FirstResponse)), ?assertEqual("chunked", lhttpc_lib:header_value("transfer-encoding", headers(FirstResponse))), - SecondResult = lhttpc:request(URL, get, [], 100), + SecondResult = lhttpc:request(URL, get, [], 1000), {ok, SecondResponse} = SecondResult, ?assertEqual({200, "OK"}, status(SecondResponse)), ?assertEqual(<<"Again, great success!">>, body(SecondResponse)), From f5c0b3ac831c8ecc51f028c27bf6c239acfd9ab1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Hellstr=C3=B6m?= Date: Wed, 7 Sep 2011 21:56:39 +0100 Subject: [PATCH 06/17] Add a comment about the bool() / boolean() type thing. --- src/lhttpc_types.hrl | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/lhttpc_types.hrl b/src/lhttpc_types.hrl index fd67c6e6..65ad05c5 100644 --- a/src/lhttpc_types.hrl +++ b/src/lhttpc_types.hrl @@ -24,6 +24,12 @@ %%% ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. %%% ---------------------------------------------------------------------------- +%% In R13B bool() is now called boolean() +%% I get lots of questions for this, but it will be removed when R15 comes +%% out, before that I belive it's more useful than harmful, since it makes +%% lhttpc compile also with older erlang releases. +-type boolean() :: bool(). + -type header() :: {string() | atom(), string()}. -type headers() :: [header()]. @@ -42,6 +48,3 @@ -type socket_options() :: [{atom(), term()} | atom()]. -type window_size() :: non_neg_integer() | infinity. - -%% In R13B bool() is now called boolean() --type boolean() :: bool(). From 9387e28e4257fe2e42f3135429965e6e0dd65045 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Hellstr=C3=B6m?= Date: Wed, 7 Sep 2011 21:57:39 +0100 Subject: [PATCH 07/17] Update the default rebar.config --- rebar.config | 3 +++ 1 file changed, 3 insertions(+) diff --git a/rebar.config b/rebar.config index 4483aa93..51073ddb 100644 --- a/rebar.config +++ b/rebar.config @@ -1 +1,4 @@ +{edoc_opts, [{report_missing_types, true}]}. +{erl_opts, [debug_info]}. {cover_enabled, true}. +{dialyzer_opts, [{warnings, [unmatched_returns]}]}. From f7979dac53b823ba380310a1123fddd2fff908d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Hellstr=C3=B6m?= Date: Thu, 8 Sep 2011 00:17:53 +0100 Subject: [PATCH 08/17] ssl seem to have stopped supporting setopts(S, [{packet, httph}]). Therefore we use erlang:decode_packet/3 instead. This should make chunked ssl work with both old and new erlang versions. --- src/lhttpc_client.erl | 42 +++++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/src/lhttpc_client.erl b/src/lhttpc_client.erl index ac0cb77e..a82fc193 100644 --- a/src/lhttpc_client.erl +++ b/src/lhttpc_client.erl @@ -440,7 +440,7 @@ read_partial_chunked_body(State, Hdrs, Window, BufferSize, Buffer, 0) -> case read_chunk_size(Socket, Ssl) of 0 -> reply_chunked_part(State, Buffer, Window), - {Trailers, NewHdrs} = read_trailers(Socket, Ssl, [], Hdrs), + {Trailers, NewHdrs} = read_trailers(Socket, Ssl, [], Hdrs, <<>>), reply_end_of_body(State, Trailers, NewHdrs); ChunkSize when PartSize =:= infinity -> Chunk = read_chunk(Socket, Ssl, ChunkSize), @@ -504,7 +504,7 @@ read_chunked_body(Socket, Ssl, Hdrs, Chunks) -> case read_chunk_size(Socket, Ssl) of 0 -> Body = list_to_binary(lists:reverse(Chunks)), - {_, NewHdrs} = read_trailers(Socket, Ssl, [], Hdrs), + {_, NewHdrs} = read_trailers(Socket, Ssl, [], Hdrs, <<>>), {Body, NewHdrs}; Size -> Chunk = read_chunk(Socket, Ssl, Size), @@ -546,17 +546,33 @@ read_chunk(Socket, Ssl, Size) -> erlang:error(Reason) end. -read_trailers(Socket, Ssl, Trailers, Hdrs) -> - ok = lhttpc_sock:setopts(Socket, [{packet, httph}], Ssl), - case lhttpc_sock:recv(Socket, Ssl) of - {ok, http_eoh} -> - {Trailers, Hdrs}; - {ok, {http_header, _, Name, _, Value}} -> - Header = {lhttpc_lib:maybe_atom_to_list(Name), Value}, - read_trailers(Socket, Ssl, [Header | Trailers], [Header | Hdrs]); - {error, {http_error, Data}} -> - erlang:error({bad_trailer, Data}) - end. +read_trailers(Socket, Ssl, Trailers, Hdrs, <<>>) -> + case lhttpc_sock:recv(Socket, Ssl) of + {ok, Data} -> + read_trailers(Socket, Ssl, Trailers, Hdrs, Data); + {error, closed} -> + {Hdrs, Trailers} + end; +read_trailers(Socket, Ssl, Trailers, Hdrs, Buffer) -> + case erlang:decode_packet(httph, Buffer, []) of + {ok, {http_header, _, Name, _, Value}, NextBuffer} -> + Header = {Name, Value}, + NTrailers = [Header | Trailers], + NHeaders = [Header | Hdrs], + read_trailers(Socket, Ssl, NTrailers, NHeaders, NextBuffer); + {ok, http_eoh, _} -> + {Trailers, Hdrs}; + {more, _} -> + case lhttpc_sock:recv(Socket, Ssl) of + {ok, Data} -> + BufferAndData = list_to_binary([Buffer, Data]), + read_trailers(Socket, Ssl, Trailers, Hdrs, BufferAndData); + {error, closed} -> + {Hdrs, Trailers} + end; + {http_error, Data} -> + erlang:error({bad_trailer, Data}) + end. reply_end_of_body(#client_state{requester = Requester}, Trailers, Hdrs) -> Requester ! {http_eob, self(), Trailers}, From 8218b5e9c9575363d0c47659415347060c5a2866 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Hellstr=C3=B6m?= Date: Thu, 8 Sep 2011 00:20:19 +0100 Subject: [PATCH 09/17] Update ignore pattern --- .gitignore | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index af4dcc9f..ffc9d970 100644 --- a/.gitignore +++ b/.gitignore @@ -11,5 +11,4 @@ test/*.log .eunit -*.swp -*.swo +*.sw? From f851194ee3ae50eea263b5a404f514449af83792 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Hellstr=C3=B6m?= Date: Thu, 8 Sep 2011 00:31:44 +0100 Subject: [PATCH 10/17] Dialyzer made me do it. It didn' make dialyzer happy, but I'm not sure how to da that in a sain way... --- src/lhttpc_client.erl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lhttpc_client.erl b/src/lhttpc_client.erl index a82fc193..b5a8eb28 100644 --- a/src/lhttpc_client.erl +++ b/src/lhttpc_client.erl @@ -571,7 +571,9 @@ read_trailers(Socket, Ssl, Trailers, Hdrs, Buffer) -> {Hdrs, Trailers} end; {http_error, Data} -> - erlang:error({bad_trailer, Data}) + erlang:error({bad_trailer, Data}); + {error, Reason} -> + erlang:error({bad_trailer, Reason}) end. reply_end_of_body(#client_state{requester = Requester}, Trailers, Hdrs) -> From 5e9660afc86b8c0479443b9c2c50b39d7a51d1c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Hellstr=C3=B6m?= Date: Thu, 8 Sep 2011 08:30:18 +0100 Subject: [PATCH 11/17] Update changelog and prepare for releasing 1.3 --- CHANGELOG | 7 +++++-- src/lhttpc.app.src | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 21ce97d9..1c46b31b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,9 +1,9 @@ -Version ?: +Version 1.3: +* Add support for "streaming" of entities * Add support for connect_options * Enables the user to pass socket options, for instance ip and port, that will be used when connecting the socket * Allows the user to specify SSL options during the connect phase -* Add support for "streaming" of entities * Add start/0 and stop/0 * Fix for unexpected messages after request has been completed * When the client process is trapping exits (which some eunit versions seem @@ -11,6 +11,9 @@ Version ?: after completing requests which came from the lhttpc_client process. These are now avoided. * Add rebar support (thanks to Benoit Chesneau) +* Fix some Edoc warnings (thanks to Richard Carlsson) +* Follow http spec recomendation and add space after : separator (thanks to + Marcus Froberg) Version 1.2.5: * Fix for decoding chunked HTTP responses with extraneous whitespace diff --git a/src/lhttpc.app.src b/src/lhttpc.app.src index 43596373..9dfcc10c 100644 --- a/src/lhttpc.app.src +++ b/src/lhttpc.app.src @@ -29,7 +29,7 @@ %%% @end {application, lhttpc, [{description, "Lightweight HTTP Client"}, - {vsn, "1.2.5"}, + {vsn, "1.3"}, {modules, []}, {registered, [lhttpc_manager]}, {applications, [kernel, stdlib, ssl, crypto]}, From 0ec06aa0a4ae1aa31ab60538bd5d580b43af8355 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Hellstr=C3=B6m?= Date: Thu, 8 Sep 2011 16:17:16 +0100 Subject: [PATCH 12/17] Don't use tabs, use spaces... --- src/lhttpc_client.erl | 54 +++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/src/lhttpc_client.erl b/src/lhttpc_client.erl index b5a8eb28..ff218c82 100644 --- a/src/lhttpc_client.erl +++ b/src/lhttpc_client.erl @@ -547,34 +547,34 @@ read_chunk(Socket, Ssl, Size) -> end. read_trailers(Socket, Ssl, Trailers, Hdrs, <<>>) -> - case lhttpc_sock:recv(Socket, Ssl) of - {ok, Data} -> - read_trailers(Socket, Ssl, Trailers, Hdrs, Data); - {error, closed} -> - {Hdrs, Trailers} - end; + case lhttpc_sock:recv(Socket, Ssl) of + {ok, Data} -> + read_trailers(Socket, Ssl, Trailers, Hdrs, Data); + {error, closed} -> + {Hdrs, Trailers} + end; read_trailers(Socket, Ssl, Trailers, Hdrs, Buffer) -> - case erlang:decode_packet(httph, Buffer, []) of - {ok, {http_header, _, Name, _, Value}, NextBuffer} -> - Header = {Name, Value}, - NTrailers = [Header | Trailers], - NHeaders = [Header | Hdrs], - read_trailers(Socket, Ssl, NTrailers, NHeaders, NextBuffer); - {ok, http_eoh, _} -> - {Trailers, Hdrs}; - {more, _} -> - case lhttpc_sock:recv(Socket, Ssl) of - {ok, Data} -> - BufferAndData = list_to_binary([Buffer, Data]), - read_trailers(Socket, Ssl, Trailers, Hdrs, BufferAndData); - {error, closed} -> - {Hdrs, Trailers} - end; - {http_error, Data} -> - erlang:error({bad_trailer, Data}); - {error, Reason} -> - erlang:error({bad_trailer, Reason}) - end. + case erlang:decode_packet(httph, Buffer, []) of + {ok, {http_header, _, Name, _, Value}, NextBuffer} -> + Header = {Name, Value}, + NTrailers = [Header | Trailers], + NHeaders = [Header | Hdrs], + read_trailers(Socket, Ssl, NTrailers, NHeaders, NextBuffer); + {ok, http_eoh, _} -> + {Trailers, Hdrs}; + {more, _} -> + case lhttpc_sock:recv(Socket, Ssl) of + {ok, Data} -> + BufferAndData = list_to_binary([Buffer, Data]), + read_trailers(Socket, Ssl, Trailers, Hdrs, BufferAndData); + {error, closed} -> + {Hdrs, Trailers} + end; + {http_error, Data} -> + erlang:error({bad_trailer, Data}); + {error, Reason} -> + erlang:error({bad_trailer, Reason}) + end. reply_end_of_body(#client_state{requester = Requester}, Trailers, Hdrs) -> Requester ! {http_eob, self(), Trailers}, From def1e39bc54f2ca10f4d2e191c97a23cad1f4f0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Hellstr=C3=B6m?= Date: Thu, 8 Sep 2011 16:21:05 +0100 Subject: [PATCH 13/17] Also deal with Other errors when reading trailers. This will make the error report a bit nicer imho. --- src/lhttpc_client.erl | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/lhttpc_client.erl b/src/lhttpc_client.erl index ff218c82..efa9c391 100644 --- a/src/lhttpc_client.erl +++ b/src/lhttpc_client.erl @@ -551,7 +551,9 @@ read_trailers(Socket, Ssl, Trailers, Hdrs, <<>>) -> {ok, Data} -> read_trailers(Socket, Ssl, Trailers, Hdrs, Data); {error, closed} -> - {Hdrs, Trailers} + {Hdrs, Trailers}; + {error, Error} -> + erlang:error(Error) end; read_trailers(Socket, Ssl, Trailers, Hdrs, Buffer) -> case erlang:decode_packet(httph, Buffer, []) of @@ -568,7 +570,9 @@ read_trailers(Socket, Ssl, Trailers, Hdrs, Buffer) -> BufferAndData = list_to_binary([Buffer, Data]), read_trailers(Socket, Ssl, Trailers, Hdrs, BufferAndData); {error, closed} -> - {Hdrs, Trailers} + {Hdrs, Trailers}; + {error, Error} -> + erlang:error(Error) end; {http_error, Data} -> erlang:error({bad_trailer, Data}); From e243dcfaaab267c7e0e24c38a9ee378fa7f8cb59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Hellstr=C3=B6m?= Date: Mon, 12 Sep 2011 19:57:09 +0100 Subject: [PATCH 14/17] Make the version number 1.3.0, it's been like that before. --- src/lhttpc.app.src | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lhttpc.app.src b/src/lhttpc.app.src index 9dfcc10c..987cb784 100644 --- a/src/lhttpc.app.src +++ b/src/lhttpc.app.src @@ -29,7 +29,7 @@ %%% @end {application, lhttpc, [{description, "Lightweight HTTP Client"}, - {vsn, "1.3"}, + {vsn, "1.3.0"}, {modules, []}, {registered, [lhttpc_manager]}, {applications, [kernel, stdlib, ssl, crypto]}, From 5a906f6e2d6b60ae63787ce0cf532440236c0083 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Hellstr=C3=B6m?= Date: Tue, 13 Sep 2011 14:38:21 +0100 Subject: [PATCH 15/17] Handle the http_error return from decode packet. (thank you dialyzer) --- src/lhttpc_client.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lhttpc_client.erl b/src/lhttpc_client.erl index efa9c391..2b53ebe7 100644 --- a/src/lhttpc_client.erl +++ b/src/lhttpc_client.erl @@ -564,6 +564,8 @@ read_trailers(Socket, Ssl, Trailers, Hdrs, Buffer) -> read_trailers(Socket, Ssl, NTrailers, NHeaders, NextBuffer); {ok, http_eoh, _} -> {Trailers, Hdrs}; + {ok, {http_error, HttpString}, _} -> + erlang:error({bad_trailer, HttpString}); {more, _} -> case lhttpc_sock:recv(Socket, Ssl) of {ok, Data} -> @@ -574,8 +576,6 @@ read_trailers(Socket, Ssl, Trailers, Hdrs, Buffer) -> {error, Error} -> erlang:error(Error) end; - {http_error, Data} -> - erlang:error({bad_trailer, Data}); {error, Reason} -> erlang:error({bad_trailer, Reason}) end. From f07ca47ce698f3c3aadce6b89ff5a61b82efec59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Hellstr=C3=B6m?= Date: Tue, 13 Sep 2011 15:57:54 +0100 Subject: [PATCH 16/17] Again, spaces, not tabs. --- src/lhttpc_client.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lhttpc_client.erl b/src/lhttpc_client.erl index 2b53ebe7..68daa180 100644 --- a/src/lhttpc_client.erl +++ b/src/lhttpc_client.erl @@ -564,7 +564,7 @@ read_trailers(Socket, Ssl, Trailers, Hdrs, Buffer) -> read_trailers(Socket, Ssl, NTrailers, NHeaders, NextBuffer); {ok, http_eoh, _} -> {Trailers, Hdrs}; - {ok, {http_error, HttpString}, _} -> + {ok, {http_error, HttpString}, _} -> erlang:error({bad_trailer, HttpString}); {more, _} -> case lhttpc_sock:recv(Socket, Ssl) of From 6da14814dd1b91c214b85c352d3a313d1e66ecc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Hellstr=C3=B6m?= Date: Tue, 13 Sep 2011 16:15:49 +0100 Subject: [PATCH 17/17] Test for broken trailers. --- test/lhttpc_tests.erl | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/test/lhttpc_tests.erl b/test/lhttpc_tests.erl index 397741b0..3803fb9a 100644 --- a/test/lhttpc_tests.erl +++ b/test/lhttpc_tests.erl @@ -137,6 +137,7 @@ tcp_test_() -> ?_test(connection_timeout()), ?_test(suspended_manager()), ?_test(chunked_encoding()), + ?_test(bad_trailers()), ?_test(partial_upload_identity()), ?_test(partial_upload_identity_iolist()), ?_test(partial_upload_chunked()), @@ -425,6 +426,11 @@ chunked_encoding() -> ?assertEqual("2", lhttpc_lib:header_value("trailer-2", headers(SecondResponse))). +bad_trailers() -> + Port = start(gen_tcp, [fun chunked_response_bad_t/5]), + URL = url(Port, "/chunked"), + ?assertExit({{bad_trailer, "Broken-Trailer-1\r\n"}, _}, lhttpc:request(URL, get, [], 50)). + partial_upload_identity() -> Port = start(gen_tcp, [fun simple_response/5, fun simple_response/5]), URL = url(Port, "/partial_upload"), @@ -967,6 +973,21 @@ chunked_response_t(Module, Socket, _, _, _) -> "\r\n" ). +chunked_response_bad_t(Module, Socket, _, _, _) -> + Module:send( + Socket, + "HTTP/1.1 200 OK\r\n" + "Content-type: text/plain\r\nTransfer-Encoding: ChUnKeD\r\n\r\n" + "7\r\n" + "Again, \r\n" + "E\r\n" + "great success!\r\n" + "0\r\n" + "Broken-Trailer-1\r\n" + "Trailer-2: 2\r\n" + "\r\n" + ). + close_connection(Module, Socket, _, _, _) -> Module:send( Socket,