Loïc Hoguin 7 лет назад
Родитель
Сommit
34473bc247
5 измененных файлов с 22 добавлено и 16 удалено
  1. 3 2
      src/cowboy_http.erl
  2. 15 9
      src/cowboy_http2.erl
  3. 3 1
      src/cowboy_stream.erl
  4. 1 0
      src/cowboy_tracer_h.erl
  5. 0 4
      src/cowboy_websocket.erl

+ 3 - 2
src/cowboy_http.erl

@@ -981,8 +981,9 @@ commands(State0=#state{socket=Socket, transport=Transport}, StreamID,
 		[{sendfile, IsFin, Offset, Bytes, Path}|Tail]) ->
 	Transport:sendfile(Socket, Path, Offset, Bytes),
 	State = case IsFin of
-		fin -> State0#state{out_state=done};
-		nofin -> State0
+		fin -> State0#state{out_state=done}
+%% @todo Add the sendfile command.
+%		nofin -> State0
 	end,
 	commands(State, StreamID, Tail);
 %% Protocol takeover.

+ 15 - 9
src/cowboy_http2.erl

@@ -572,10 +572,11 @@ commands(State0, Stream0=#stream{local=nofin, te=TE0}, [{trailers, Trailers}|Tai
 	end,
 	commands(State, Stream, Tail);
 %% Send a file.
-commands(State0, Stream0=#stream{local=nofin},
-		[{sendfile, IsFin, Offset, Bytes, Path}|Tail]) ->
-	{State, Stream} = send_data(State0, Stream0, IsFin, {sendfile, Offset, Bytes, Path}),
-	commands(State, Stream, Tail);
+%% @todo Add the sendfile command.
+%commands(State0, Stream0=#stream{local=nofin},
+%		[{sendfile, IsFin, Offset, Bytes, Path}|Tail]) ->
+%	{State, Stream} = send_data(State0, Stream0, IsFin, {sendfile, Offset, Bytes, Path}),
+%	commands(State, Stream, Tail);
 %% @todo sendfile when local!=nofin
 %% Send a push promise.
 %%
@@ -843,10 +844,10 @@ stream_pseudo_headers_init(State, StreamID, IsFin, Headers0) ->
 	case pseudo_headers(Headers0, #{}) of
 		%% @todo Add clause for CONNECT requests (no scheme/path).
 		{ok, PseudoHeaders=#{method := <<"CONNECT">>}, _} ->
-			stream_early_error(State, StreamID, 501, PseudoHeaders,
+			stream_early_error(State, StreamID, IsFin, 501, PseudoHeaders,
 				'The CONNECT method is currently not implemented. (RFC7231 4.3.6)');
 		{ok, PseudoHeaders=#{method := <<"TRACE">>}, _} ->
-			stream_early_error(State, StreamID, 501, PseudoHeaders,
+			stream_early_error(State, StreamID, IsFin, 501, PseudoHeaders,
 				'The TRACE method is currently not implemented. (RFC7231 4.3.8)');
 		{ok, PseudoHeaders=#{method := _, scheme := _, authority := _, path := _}, Headers} ->
 			stream_regular_headers_init(State, StreamID, IsFin, Headers, PseudoHeaders);
@@ -983,8 +984,11 @@ stream_malformed(State=#state{socket=Socket, transport=Transport}, StreamID, _)
 	Transport:send(Socket, cow_http2:rst_stream(StreamID, protocol_error)),
 	State.
 
-stream_early_error(State0=#state{ref=Ref, opts=Opts, peer=Peer, streams=Streams},
-		StreamID, StatusCode0, #{method := Method}, HumanReadable) ->
+stream_early_error(State0=#state{ref=Ref, opts=Opts, peer=Peer,
+		local_settings=#{initial_window_size := RemoteWindow},
+		remote_settings=#{initial_window_size := LocalWindow},
+		streams=Streams}, StreamID, IsFin, StatusCode0,
+		#{method := Method}, HumanReadable) ->
 	%% We automatically terminate the stream but it is not an error
 	%% per se (at least not in the first implementation).
 	Reason = {stream_error, no_error, HumanReadable},
@@ -997,7 +1001,9 @@ stream_early_error(State0=#state{ref=Ref, opts=Opts, peer=Peer, streams=Streams}
 	},
 	Resp = {response, StatusCode0, RespHeaders0=#{<<"content-length">> => <<"0">>}, <<>>},
 	%% We need a stream to talk to the send_* functions.
-	Stream0 = #stream{id=StreamID, method=Method},
+	Stream0 = #stream{id=StreamID, state=flush, method=Method,
+		remote=IsFin, local=idle,
+		local_window=LocalWindow, remote_window=RemoteWindow},
 	try cowboy_stream:early_error(StreamID, Reason, PartialReq, Resp, Opts) of
 		{response, StatusCode, RespHeaders, RespBody} ->
 			case send_response(State0, Stream0, StatusCode, RespHeaders, RespBody) of

+ 3 - 1
src/cowboy_stream.erl

@@ -29,9 +29,11 @@
 	:: {response, cowboy:http_status(), cowboy:http_headers(), cowboy_req:resp_body()}.
 -export_type([resp_command/0]).
 
--type commands() :: [resp_command()
+-type commands() :: [{inform, cowboy:http_status(), cowboy:http_headers()}
+	| resp_command()
 	| {headers, cowboy:http_status(), cowboy:http_headers()}
 	| {data, fin(), iodata()}
+	| {trailers, cowboy:http_headers()}
 	| {push, binary(), binary(), binary(), inet:port_number(),
 		binary(), binary(), cowboy:http_headers()}
 	| {flow, pos_integer()}

+ 1 - 0
src/cowboy_tracer_h.erl

@@ -169,6 +169,7 @@ tracer_loop(Parent, Fun, State0) ->
 			tracer_loop(Parent, Fun, State0)
 	end.
 
+-spec tracer_terminate(_, _, _) -> no_return().
 tracer_terminate(Reason, Fun, State) ->
 	_ = Fun(terminate, State),
 	exit(Reason).

+ 0 - 4
src/cowboy_websocket.erl

@@ -110,8 +110,6 @@ upgrade(Req0, Env, Handler, HandlerState, Opts) ->
 		{ok, cowboy_req:reply(400, Req0), Env}
 	end.
 
--spec websocket_upgrade(#state{}, Req)
-	-> {ok, #state{}, Req} when Req::cowboy_req:req().
 websocket_upgrade(State, Req) ->
 	ConnTokens = cowboy_req:parse_header(<<"connection">>, Req, []),
 	case lists:member(<<"upgrade">>, ConnTokens) of
@@ -133,8 +131,6 @@ websocket_upgrade(State, Req) ->
 			end
 	end.
 
--spec websocket_extensions(#state{}, Req)
-	-> {ok, #state{}, Req} when Req::cowboy_req:req().
 websocket_extensions(State=#state{compress=Compress}, Req) ->
 	%% @todo We want different options for this. For example
 	%% * compress everything auto