diff --git a/CHANGELOG b/CHANGELOG index 9e39760..3aff4ac 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,9 @@ CONTRIBUTIONS & CHANGE HISTORY ============================== +06-04-2012 - v3.0.4 + * Fix for the following issue + https://github.com/cmullaparthi/ibrowse/issues/67 + 13-03-2012 - v3.0.3 * Fixes the following issues https://github.com/cmullaparthi/ibrowse/issues/64 diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 5216930..d84318e 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -29,6 +29,7 @@ Paul J. Davis Peter Kristensen Ram Krishnan Richard Cameron +Ryan Flynn Ryan Zezeski Sean Hinde Sergey Samokhi diff --git a/README.md b/README.md index 428d561..206cd2b 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ ibrowse is a HTTP client written in erlang. **Comments to:** chandrashekhar.mullaparthi@gmail.com -**Current Version:** 3.0.3 +**Current Version:** 3.0.4 **Latest Version:** git://github.com/cmullaparthi/ibrowse.git diff --git a/src/ibrowse.app.src b/src/ibrowse.app.src index a696294..b793dd6 100644 --- a/src/ibrowse.app.src +++ b/src/ibrowse.app.src @@ -1,6 +1,6 @@ {application, ibrowse, - [{description, "HTTP client application"}, - {vsn, "3.0.3"}, + [{description, "Erlang HTTP client application"}, + {vsn, "3.0.4"}, {modules, [ ibrowse, ibrowse_http_client, ibrowse_app, diff --git a/src/ibrowse_http_client.erl b/src/ibrowse_http_client.erl index 4ad962f..2d2f577 100644 --- a/src/ibrowse_http_client.erl +++ b/src/ibrowse_http_client.erl @@ -1047,7 +1047,13 @@ parse_response(Data, #state{reply_buffer = Acc, reqs = Reqs, do_error_reply(State#state{reqs = Reqs_1}, {error, proxy_tunnel_failed}), {error, proxy_tunnel_failed}; - _ when Method == head -> + _ when Method == head, + TransferEncoding =/= "chunked" -> + %% This is not supposed to happen, but it does. An + %% Apache server was observed to send an "empty" + %% body, but in a Chunked-Transfer-Encoding way, + %% which meant there was still a body. + %% Issue #67 on Github {_, Reqs_1} = queue:out(Reqs), send_async_headers(ReqId, StreamTo, Give_raw_headers, State_1), State_1_1 = do_reply(State_1, From, StreamTo, ReqId, Resp_format, @@ -1091,7 +1097,7 @@ parse_response(Data, #state{reply_buffer = Acc, reqs = Reqs, State_2 end; undefined when HttpVsn =:= "HTTP/1.0"; - ConnClose =:= "close" -> + ConnClose =:= "close" -> send_async_headers(ReqId, StreamTo, Give_raw_headers, State_1), State_1#state{reply_buffer = Data_1}; undefined -> diff --git a/src/ibrowse_test.erl b/src/ibrowse_test.erl index 9b521b6..6353f1a 100644 --- a/src/ibrowse_test.erl +++ b/src/ibrowse_test.erl @@ -23,7 +23,9 @@ test_20122010/1, test_pipeline_head_timeout/0, test_pipeline_head_timeout/1, - do_test_pipeline_head_timeout/4 + do_test_pipeline_head_timeout/4, + test_head_transfer_encoding/0, + test_head_transfer_encoding/1 ]). test_stream_once(Url, Method, Options) -> @@ -227,7 +229,8 @@ dump_errors(Key, Iod) -> {"http://www.httpwatch.com/httpgallery/chunked/", get}, {"https://github.com", get, [{ssl_options, [{depth, 2}]}]}, {local_test_fun, test_20122010, []}, - {local_test_fun, test_pipeline_head_timeout, []} + {local_test_fun, test_pipeline_head_timeout, []}, + {local_test_fun, test_head_transfer_encoding, []} ]). unit_tests() -> @@ -436,7 +439,22 @@ log_msg(Fmt, Args) -> io:format("~s -- " ++ Fmt, [ibrowse_lib:printable_date() | Args]). +%%------------------------------------------------------------------------------ +%% Test what happens when the response to a HEAD request is a +%% Chunked-Encoding response with a non-empty body. Issue #67 on +%% Github +%% ------------------------------------------------------------------------------ +test_head_transfer_encoding() -> + clear_msg_q(), + test_head_transfer_encoding("http://localhost:8181/ibrowse_head_transfer_enc"). +test_head_transfer_encoding(Url) -> + case ibrowse:send_req(Url, [], head) of + {ok, "400", _, _} -> + success; + Res -> + {test_failed, Res} + end. %%------------------------------------------------------------------------------ %% Test what happens when the request at the head of a pipeline times out %%------------------------------------------------------------------------------ diff --git a/test/ibrowse_test_server.erl b/test/ibrowse_test_server.erl index a9d6e1e..562e908 100644 --- a/test/ibrowse_test_server.erl +++ b/test/ibrowse_test_server.erl @@ -35,7 +35,7 @@ start_server(Port, Sock_type) -> spawn_link(Fun). stop_server(Port) -> - catch exit(whereis(server_proc_name(Port)), kill), + server_proc_name(Port) ! stop, ok. server_proc_name(Port) -> @@ -99,6 +99,8 @@ server_loop(Sock, Sock_type, #request{headers = Headers} = Req) -> {tcp_closed, Sock} -> do_trace("Client closed connection~n", []), ok; + stop -> + ok; Other -> do_trace("Recvd unknown msg: ~p~n", [Other]), exit({unknown_msg, Other}) @@ -145,6 +147,12 @@ process_request(Sock, Sock_type, do_trace("...Sending response now.~n", []), Resp = <<"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n">>, do_send(Sock, Sock_type, Resp); +process_request(Sock, Sock_type, + #request{method='HEAD', + headers = _Headers, + uri = {abs_path, "/ibrowse_head_transfer_enc"}}) -> + Resp = <<"HTTP/1.1 400 Bad Request\r\nServer: Apache-Coyote/1.1\r\nTransfer-Encoding: chunked\r\nDate: Wed, 04 Apr 2012 16:53:49 GMT\r\nConnection: close\r\n\r\n0\r\n\r\n">>, + do_send(Sock, Sock_type, Resp); process_request(Sock, Sock_type, Req) -> do_trace("Recvd req: ~p~n", [Req]), Resp = <<"HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n">>,