0
Fork 0
mirror of https://github.com/ninenines/cowboy.git synced 2025-07-14 12:20:24 +00:00

Honor the SETTINGS_ENABLE_PUSH from clients

This fixes curl when fetching resources that use push.
This commit is contained in:
Loïc Hoguin 2018-05-16 11:00:25 +02:00
parent 204fa12df8
commit ae6c787062
No known key found for this signature in database
GPG key ID: 8A9DF795F6FED764
2 changed files with 33 additions and 15 deletions

View file

@ -706,6 +706,10 @@ commands(State0, Stream0=#stream{local=nofin, te=TE0}, [{trailers, Trailers}|Tai
% [{sendfile, IsFin, Offset, Bytes, Path}|Tail]) -> % [{sendfile, IsFin, Offset, Bytes, Path}|Tail]) ->
% {State, Stream} = send_data(State0, Stream0, IsFin, {sendfile, Offset, Bytes, Path}), % {State, Stream} = send_data(State0, Stream0, IsFin, {sendfile, Offset, Bytes, Path}),
% commands(State, Stream, Tail); % commands(State, Stream, Tail);
%% Push promises are not sent to clients who disabled them.
commands(State=#state{remote_settings=#{enable_push := false}}, Stream,
[{push, _, _, _, _, _, _, _}|Tail]) ->
commands(State, Stream, Tail);
%% Send a push promise. %% Send a push promise.
%% %%
%% @todo We need to keep track of what promises we made so that we don't %% @todo We need to keep track of what promises we made so that we don't

View file

@ -2591,14 +2591,6 @@ settings_header_table_size_server(Config0) ->
%% the table size was updated to HeaderTableSize. %% the table size was updated to HeaderTableSize.
ok. ok.
% SETTINGS_ENABLE_PUSH (0x2): This setting can be used to disable
% server push (Section 8.2). An endpoint MUST NOT send a
% PUSH_PROMISE frame if it receives this parameter set to a value of
% 0. An endpoint that has both set this parameter to 0 and had it
% acknowledged MUST treat the receipt of a PUSH_PROMISE frame as a
% connection error (Section 5.4.1) of type PROTOCOL_ERROR.
%% @todo settings_disable_push
settings_max_concurrent_streams(Config0) -> settings_max_concurrent_streams(Config0) ->
doc("The SETTINGS_MAX_CONCURRENT_STREAMS setting can be used to " doc("The SETTINGS_MAX_CONCURRENT_STREAMS setting can be used to "
"restrict the number of concurrent streams. (RFC7540 5.1.2, RFC7540 6.5.2)"), "restrict the number of concurrent streams. (RFC7540 5.1.2, RFC7540 6.5.2)"),
@ -2882,13 +2874,35 @@ settings_max_frame_size_reject_too_large(Config) ->
% associated with. If the stream identifier field specifies the value % associated with. If the stream identifier field specifies the value
% 0x0, a recipient MUST respond with a connection error (Section 5.4.1) % 0x0, a recipient MUST respond with a connection error (Section 5.4.1)
% of type PROTOCOL_ERROR. % of type PROTOCOL_ERROR.
%
% PUSH_PROMISE MUST NOT be sent if the SETTINGS_ENABLE_PUSH setting of client_settings_disable_push(Config) ->
% the peer endpoint is set to 0. An endpoint that has set this setting doc("PUSH_PROMISE frames must not be sent when the setting "
% and has received acknowledgement MUST treat the receipt of a "SETTINGS_ENABLE_PUSH is disabled. (RFC7540 6.5.2, RFC7540 6.6, RFC7540 8.2)"),
% PUSH_PROMISE frame as a connection error (Section 5.4.1) of type %% Do a prior knowledge handshake.
% PROTOCOL_ERROR. {ok, Socket} = gen_tcp:connect("localhost", config(port, Config), [binary, {active, false}]),
% %% Send a valid preface.
ok = gen_tcp:send(Socket, ["PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n", cow_http2:settings(#{
enable_push => false
})]),
%% Receive the server preface.
{ok, << Len:24 >>} = gen_tcp:recv(Socket, 3, 1000),
{ok, << 4:8, 0:40, _:Len/binary >>} = gen_tcp:recv(Socket, 6 + Len, 1000),
%% Send the SETTINGS ack.
ok = gen_tcp:send(Socket, cow_http2:settings_ack()),
%% Receive the SETTINGS ack.
{ok, << 0:24, 4:8, 1:8, 0:32 >>} = gen_tcp:recv(Socket, 9, 1000),
%% Send a HEADERS frame on a resource that sends PUSH_PROMISE frames.
{HeadersBlock, _} = cow_hpack:encode([
{<<":method">>, <<"GET">>},
{<<":scheme">>, <<"http">>},
{<<":authority">>, <<"localhost">>}, %% @todo Correct port number.
{<<":path">>, <<"/resp/push">>}
]),
ok = gen_tcp:send(Socket, cow_http2:headers(1, fin, HeadersBlock)),
%% Receive a HEADERS frame as a response, no PUSH_PROMISE frames.
{ok, << _:24, 1:8, _:40 >>} = gen_tcp:recv(Socket, 9, 6000),
ok.
% Since PUSH_PROMISE reserves a stream, ignoring a PUSH_PROMISE frame % Since PUSH_PROMISE reserves a stream, ignoring a PUSH_PROMISE frame
% causes the stream state to become indeterminate. A receiver MUST % causes the stream state to become indeterminate. A receiver MUST
% treat the receipt of a PUSH_PROMISE on a stream that is neither % treat the receipt of a PUSH_PROMISE on a stream that is neither