Browse Source

Don't send transfer-encoding when streaming 204 responses

Loïc Hoguin 7 years ago
parent
commit
5229d790fb
3 changed files with 23 additions and 16 deletions
  1. 8 6
      src/cowboy_http.erl
  2. 1 3
      src/cowboy_stream_h.erl
  3. 14 7
      test/handlers/resp_h.erl

+ 8 - 6
src/cowboy_http.erl

@@ -929,17 +929,19 @@ commands(State0=#state{socket=Socket, transport=Transport, streams=Streams}, Str
 		[{headers, StatusCode, Headers0}|Tail]) ->
 		[{headers, StatusCode, Headers0}|Tail]) ->
 	%% @todo Same as above.
 	%% @todo Same as above.
 	#stream{version=Version} = lists:keyfind(StreamID, #stream.id, Streams),
 	#stream{version=Version} = lists:keyfind(StreamID, #stream.id, Streams),
-	{State1, Headers1} = case Version of
-		'HTTP/1.1' ->
-			{State0, Headers0#{<<"transfer-encoding">> => <<"chunked">>}};
+	{State1, Headers1} = case {cow_http:status_to_integer(StatusCode), Version} of
+		{204, 'HTTP/1.1'} ->
+			{State0#state{out_state=done}, Headers0};
+		{_, 'HTTP/1.1'} ->
+			{State0#state{out_state=chunked}, Headers0#{<<"transfer-encoding">> => <<"chunked">>}};
 		%% Close the connection after streaming the data to HTTP/1.0 client.
 		%% Close the connection after streaming the data to HTTP/1.0 client.
 		%% @todo I'm guessing we need to differentiate responses with a content-length and others.
 		%% @todo I'm guessing we need to differentiate responses with a content-length and others.
-		'HTTP/1.0' ->
-			{State0#state{last_streamid=StreamID}, Headers0}
+		{_, 'HTTP/1.0'} ->
+			{State0#state{out_state=chunked, last_streamid=StreamID}, Headers0}
 	end,
 	end,
 	{State, Headers} = connection(State1, Headers1, StreamID, Version),
 	{State, Headers} = connection(State1, Headers1, StreamID, Version),
 	Transport:send(Socket, cow_http:response(StatusCode, 'HTTP/1.1', headers_to_list(Headers))),
 	Transport:send(Socket, cow_http:response(StatusCode, 'HTTP/1.1', headers_to_list(Headers))),
-	commands(State#state{out_state=chunked}, StreamID, Tail);
+	commands(State, StreamID, Tail);
 %% Send a response body chunk.
 %% Send a response body chunk.
 %%
 %%
 %% @todo WINDOW_UPDATE stuff require us to buffer some data.
 %% @todo WINDOW_UPDATE stuff require us to buffer some data.

+ 1 - 3
src/cowboy_stream_h.erl

@@ -178,10 +178,8 @@ info(_StreamID, {read_body_timeout, _}, State) ->
 %% We reset the expect field when a 100 continue response
 %% We reset the expect field when a 100 continue response
 %% is sent or when any final response is sent.
 %% is sent or when any final response is sent.
 info(_StreamID, Inform = {inform, Status, _}, State0) ->
 info(_StreamID, Inform = {inform, Status, _}, State0) ->
-	State = case Status of
+	State = case cow_http:status_to_integer(Status) of
 		100 -> State0#state{expect=undefined};
 		100 -> State0#state{expect=undefined};
-		<<"100">> -> State0#state{expect=undefined};
-		<<"100 ", _/bits>> -> State0#state{expect=undefined};
 		_ -> State0
 		_ -> State0
 	end,
 	end,
 	{[Inform], State};
 	{[Inform], State};

+ 14 - 7
test/handlers/resp_h.erl

@@ -169,17 +169,24 @@ do(<<"reply4">>, Req0, Opts) ->
 	end,
 	end,
 	{ok, Req, Opts};
 	{ok, Req, Opts};
 do(<<"stream_reply2">>, Req0, Opts) ->
 do(<<"stream_reply2">>, Req0, Opts) ->
-	Req = case cowboy_req:binding(arg, Req0) of
+	case cowboy_req:binding(arg, Req0) of
 		<<"binary">> ->
 		<<"binary">> ->
-			cowboy_req:stream_reply(<<"200 GOOD">>, Req0);
+			Req = cowboy_req:stream_reply(<<"200 GOOD">>, Req0),
+			stream_body(Req),
+			{ok, Req, Opts};
 		<<"error">> ->
 		<<"error">> ->
 			ct_helper:ignore(cowboy_req, stream_reply, 3),
 			ct_helper:ignore(cowboy_req, stream_reply, 3),
-			cowboy_req:stream_reply(ok, Req0);
+			Req = cowboy_req:stream_reply(ok, Req0),
+			stream_body(Req),
+			{ok, Req, Opts};
+		<<"204">> ->
+			Req = cowboy_req:stream_reply(204, Req0),
+			{ok, Req, Opts};
 		Status ->
 		Status ->
-			cowboy_req:stream_reply(binary_to_integer(Status), Req0)
-	end,
-	stream_body(Req),
-	{ok, Req, Opts};
+			Req = cowboy_req:stream_reply(binary_to_integer(Status), Req0),
+			stream_body(Req),
+			{ok, Req, Opts}
+	end;
 do(<<"stream_reply3">>, Req0, Opts) ->
 do(<<"stream_reply3">>, Req0, Opts) ->
 	Req = case cowboy_req:binding(arg, Req0) of
 	Req = case cowboy_req:binding(arg, Req0) of
 		<<"error">> ->
 		<<"error">> ->