From 75045637fc6026054900f2dbea75805ad7c8e682 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Hoguin?= Date: Fri, 16 Nov 2018 13:09:01 +0100 Subject: Ensure unknown options are ignored in set_options command --- src/cowboy_compress_h.erl | 6 ++++-- src/cowboy_http2.erl | 3 +++ test/handlers/stream_handler_h.erl | 6 ++++++ test/stream_handler_SUITE.erl | 18 ++++++++++++++++++ 4 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/cowboy_compress_h.erl b/src/cowboy_compress_h.erl index 95c49d3..f4ee7b9 100644 --- a/src/cowboy_compress_h.erl +++ b/src/cowboy_compress_h.erl @@ -141,7 +141,8 @@ fold([Trailers={trailers, _}|Tail], State0=#state{compress=gzip}, Acc) -> {{data, fin, Data}, State} = gzip_data({data, fin, <<>>}, State0), fold(Tail, State, [Trailers, {data, nofin, Data}|Acc]); %% All the options from this handler can be updated for the current stream. -fold([{set_options, Opts}|Tail], State=#state{ +%% The set_options command must be propagated as-is regardless. +fold([SetOptions={set_options, Opts}|Tail], State=#state{ threshold=CompressThreshold0, deflate_flush=DeflateFlush0}, Acc) -> CompressThreshold = maps:get(compress_threshold, Opts, CompressThreshold0), DeflateFlush = case Opts of @@ -150,7 +151,8 @@ fold([{set_options, Opts}|Tail], State=#state{ _ -> DeflateFlush0 end, - fold(Tail, State#state{threshold=CompressThreshold, deflate_flush=DeflateFlush}, Acc); + fold(Tail, State#state{threshold=CompressThreshold, deflate_flush=DeflateFlush}, + [SetOptions|Acc]); %% Otherwise, we have an unrelated command or compression is disabled. fold([Command|Tail], State, Acc) -> fold(Tail, State, [Command|Acc]). diff --git a/src/cowboy_http2.erl b/src/cowboy_http2.erl index 3397241..b83c021 100644 --- a/src/cowboy_http2.erl +++ b/src/cowboy_http2.erl @@ -576,6 +576,9 @@ commands(State=#state{socket=Socket, transport=Transport, http2_init=upgrade}, commands(State0, StreamID, [{switch_protocol, Headers, _Mod, _ModState}|Tail]) -> State = info(State0, StreamID, {headers, 200, Headers}), commands(State, StreamID, Tail); +%% Set options dynamically. +commands(State, StreamID, [{set_options, _Opts}|Tail]) -> + commands(State, StreamID, Tail); commands(State, StreamID, [stop|_Tail]) -> %% @todo Do we want to run the commands after a stop? %% @todo Do we even allow commands after? diff --git a/test/handlers/stream_handler_h.erl b/test/handlers/stream_handler_h.erl index 2196be3..3761e11 100644 --- a/test/handlers/stream_handler_h.erl +++ b/test/handlers/stream_handler_h.erl @@ -34,6 +34,12 @@ init_commands(_, _, #state{test=crash_in_terminate}) -> [{response, 200, #{<<"content-length">> => <<"12">>}, <<"Hello world!">>}, stop]; init_commands(_, _, #state{test=crash_in_early_error}) -> error(crash); +init_commands(_, _, #state{test=set_options_ignore_unknown}) -> + [ + {set_options, #{unknown_options => true}}, + {response, 200, #{<<"content-length">> => <<"12">>}, <<"Hello world!">>}, + stop + ]; init_commands(_, _, State=#state{test=shutdown_on_stream_stop}) -> Spawn = init_process(false, State), [{headers, 200, #{}}, {spawn, Spawn, 5000}, stop]; diff --git a/test/stream_handler_SUITE.erl b/test/stream_handler_SUITE.erl index 738a4a2..0021ab9 100644 --- a/test/stream_handler_SUITE.erl +++ b/test/stream_handler_SUITE.erl @@ -224,6 +224,24 @@ do_crash_in_early_error_fatal(Config) -> %% Confirm the connection gets closed. gun_down(ConnPid). +set_options_ignore_unknown(Config) -> + doc("Confirm that unknown options are ignored when using the set_options commands."), + Self = self(), + ConnPid = gun_open(Config), + Ref = gun:get(ConnPid, "/long_polling", [ + {<<"accept-encoding">>, <<"gzip">>}, + {<<"x-test-case">>, <<"set_options_ignore_unknown">>}, + {<<"x-test-pid">>, pid_to_list(Self)} + ]), + %% Confirm init/3 is called. + Pid = receive {Self, P, init, _, _, _} -> P after 1000 -> error(timeout) end, + %% Confirm terminate/3 is called, indicating the stream ended. + receive {Self, Pid, terminate, _, _, _} -> ok after 1000 -> error(timeout) end, + %% Confirm the response is sent. + {response, nofin, 200, _} = gun:await(ConnPid, Ref), + {ok, _} = gun:await_body(ConnPid, Ref), + ok. + shutdown_on_stream_stop(Config) -> doc("Confirm supervised processes are shutdown when stopping the stream."), Self = self(), -- cgit v1.2.3