Browse Source

Fix protocol breaking when user tries to send empty chunk

The {data, IsFin, Data} uses IsFin to indicate whether this
is the last chunk, while chunked transfer-encoding uses the
length of Data, and ends when it is 0. We must therefore not
send chunks with empty data.
Loïc Hoguin 8 years ago
parent
commit
353dc29d8f
1 changed files with 14 additions and 10 deletions
  1. 14 10
      src/cowboy_http.erl

+ 14 - 10
src/cowboy_http.erl

@@ -842,16 +842,20 @@ commands(State0=#state{socket=Socket, transport=Transport, streams=Streams}, Str
 %% @todo We probably want to allow Data to be the {sendfile, ...} tuple also.
 commands(State=#state{socket=Socket, transport=Transport, streams=Streams}, StreamID,
 		[{data, IsFin, Data}|Tail]) ->
-
-	%% @todo We need to kill the stream if it tries to send data before headers.
-
-	%% @todo Same as above.
-	case lists:keyfind(StreamID, #stream.id, Streams) of
-		#stream{version='HTTP/1.1'} ->
-			Size = iolist_size(Data),
-			Transport:send(Socket, [integer_to_binary(Size, 16), <<"\r\n">>, Data, <<"\r\n">>]);
-		#stream{version='HTTP/1.0'} ->
-			Transport:send(Socket, Data)
+	%% Do not send anything when the user asks to send an empty
+	%% data frame, as that would break the protocol.
+	Size = iolist_size(Data),
+	case Size of
+		0 -> ok;
+		_ ->
+			%% @todo We need to kill the stream if it tries to send data before headers.
+			%% @todo Same as above.
+			case lists:keyfind(StreamID, #stream.id, Streams) of
+				#stream{version='HTTP/1.1'} ->
+					Transport:send(Socket, [integer_to_binary(Size, 16), <<"\r\n">>, Data, <<"\r\n">>]);
+				#stream{version='HTTP/1.0'} ->
+					Transport:send(Socket, Data)
+			end
 	end,
 	maybe_terminate(State, StreamID, Tail, IsFin);
 %% Send a file.