diff options
author | Kirilll Zaborsky <[email protected]> | 2015-09-23 16:51:33 +0300 |
---|---|---|
committer | Henrik Nord <[email protected]> | 2015-10-27 15:06:11 +0100 |
commit | 45251cd60ebad4ef08ffc7cb0797d1fd7a603eea (patch) | |
tree | 547b961e6ed224f4e9baa1d5438d2be9671658e5 | |
parent | f4b02cf574552f40ff354261b4c7cf02cb568212 (diff) | |
download | otp-45251cd60ebad4ef08ffc7cb0797d1fd7a603eea.tar.gz otp-45251cd60ebad4ef08ffc7cb0797d1fd7a603eea.tar.bz2 otp-45251cd60ebad4ef08ffc7cb0797d1fd7a603eea.zip |
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.
-rw-r--r-- | lib/inets/src/http_client/httpc_handler.erl | 31 | ||||
-rw-r--r-- | lib/inets/test/httpc_SUITE.erl | 43 |
2 files changed, 50 insertions, 24 deletions
diff --git a/lib/inets/src/http_client/httpc_handler.erl b/lib/inets/src/http_client/httpc_handler.erl index 0300a80b03..1044cffe6f 100644 --- a/lib/inets/src/http_client/httpc_handler.erl +++ b/lib/inets/src/http_client/httpc_handler.erl @@ -26,6 +26,7 @@ -include_lib("inets/src/http_lib/http_internal.hrl"). -include("httpc_internal.hrl"). +-define(IS_STREAMED(Code), ((Code =:= 200) orelse (Code =:= 206))). %%-------------------------------------------------------------------- %% Internal Application API @@ -167,7 +168,7 @@ stream(BodyPart, #request{stream = none} = Request, _) -> %% Stream to caller stream(BodyPart, #request{stream = Self} = Request, Code) - when ((Code =:= 200) orelse (Code =:= 206)) andalso + when ?IS_STREAMED(Code) andalso ((Self =:= self) orelse (Self =:= {self, once})) -> ?hcrt("stream - self", [{stream, Self}, {code, Code}]), httpc_response:send(Request#request.from, @@ -178,7 +179,7 @@ stream(BodyPart, #request{stream = Self} = Request, Code) %% This has been moved to start_stream/3 %% We keep this for backward compatibillity... stream(BodyPart, #request{stream = Filename} = Request, Code) - when ((Code =:= 200) orelse (Code =:= 206)) andalso is_list(Filename) -> + when ?IS_STREAMED(Code) andalso is_list(Filename) -> ?hcrt("stream - filename", [{stream, Filename}, {code, Code}]), case file:open(Filename, [write, raw, append, delayed_write]) of {ok, Fd} -> @@ -190,7 +191,7 @@ stream(BodyPart, #request{stream = Filename} = Request, Code) %% Stream to file stream(BodyPart, #request{stream = Fd} = Request, Code) - when ((Code =:= 200) orelse (Code =:= 206)) -> + when ?IS_STREAMED(Code) -> ?hcrt("stream to file", [{stream, Fd}, {code, Code}]), case file:write(Fd, BodyPart) of ok -> @@ -485,7 +486,7 @@ handle_info({Proto, _Socket, Data}, Length - size(Body) end, - NewState = next_body_chunk(State), + NewState = next_body_chunk(State, Code), NewMFA = {Module, whole_body, [NewBody, NewLength]}, {noreply, NewState#state{mfa = NewMFA, request = NewRequest}}; @@ -498,7 +499,7 @@ handle_info({Proto, _Socket, Data}, %% chunks as much as possible to stream. {_, Code, _} = StatusLine, {_, NewBody, NewRequest} = stream(BodySoFar, Request, Code), - NewState = next_body_chunk(State), + NewState = next_body_chunk(State, Code), NewMFA = {Module, decode_size, [TotalChunk, HexList, {MaxBodySize, NewBody, AccLength, MaxHeaderSize}]}, @@ -518,7 +519,7 @@ handle_info({Proto, _Socket, Data}, {_, Code, _} = StatusLine, {_, NewBody, NewRequest} = stream(StolenBody, Request, Code), - NewState = next_body_chunk(State), + NewState = next_body_chunk(State, Code), NewMFA = {Module, decode_data, [NewChunkSize, NewTotalChunk, {MaxBodySize, NewBody, AccLength, MaxHeaderSize}]}, @@ -1119,7 +1120,7 @@ handle_http_body(Body, #state{headers = Headers, [{module, Module}, {function, Function}, {args, Args}]), - NewState = next_body_chunk(State), + NewState = next_body_chunk(State, Code), {noreply, NewState#state{mfa = {Module, Function, Args}}}; {ok, {ChunkedHeaders, NewBody}} -> @@ -1152,7 +1153,7 @@ handle_http_body(Body, #state{headers = Headers, handle_response(State#state{body = NewBody, request = NewRequest}); MFA -> - NewState = next_body_chunk(State), + NewState = next_body_chunk(State, Code), {noreply, NewState#state{mfa = MFA}} end; false -> @@ -1646,21 +1647,21 @@ start_stream({_Version, _Code, _ReasonPhrase}, _Headers, {ok, Request}; start_stream({_Version, Code, _ReasonPhrase}, Headers, #request{stream = self} = Request) - when (Code =:= 200) orelse (Code =:= 206) -> + when ?IS_STREAMED(Code) -> ?hcrt("start stream - self", [{code, Code}]), Msg = httpc_response:stream_start(Headers, Request, ignore), httpc_response:send(Request#request.from, Msg), {ok, Request}; start_stream({_Version, Code, _ReasonPhrase}, Headers, #request{stream = {self, once}} = Request) - when (Code =:= 200) orelse (Code =:= 206) -> + when ?IS_STREAMED(Code) -> ?hcrt("start stream - self:once", [{code, Code}]), Msg = httpc_response:stream_start(Headers, Request, self()), httpc_response:send(Request#request.from, Msg), {ok, Request}; start_stream({_Version, Code, _ReasonPhrase}, _Headers, #request{stream = Filename} = Request) - when ((Code =:= 200) orelse (Code =:= 206)) andalso is_list(Filename) -> + when ?IS_STREAMED(Code) andalso is_list(Filename) -> ?hcrt("start stream", [{code, Code}, {filename, Filename}]), case file:open(Filename, [write, raw, append, delayed_write]) of {ok, Fd} -> @@ -1712,13 +1713,15 @@ end_stream(SL, R) -> next_body_chunk(#state{request = #request{stream = {self, once}}, once = once, - session = Session} = State) -> + session = Session} = State, + Code) when ?IS_STREAMED(Code) -> activate_once(Session), State#state{once = inactive}; next_body_chunk(#state{request = #request{stream = {self, once}}, - once = inactive} = State) -> + once = inactive} = State, + Code) when ?IS_STREAMED(Code) -> State; %% Wait for user to call stream_next -next_body_chunk(#state{session = Session} = State) -> +next_body_chunk(#state{session = Session} = State, _) -> activate_once(Session), State. 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</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" ++ |