2024-01-04 15:15:41 +01:00
|
|
|
%% Copyright (c) 2024, jdamanalo <joshuadavid.agustin@manalo.ph>
|
2024-01-25 11:22:54 +01:00
|
|
|
%% Copyright (c) 2024, Loïc Hoguin <essen@ninenines.eu>
|
2024-01-04 15:15:41 +01:00
|
|
|
%%
|
|
|
|
%% Permission to use, copy, modify, and/or distribute this software for any
|
|
|
|
%% purpose with or without fee is hereby granted, provided that the above
|
|
|
|
%% copyright notice and this permission notice appear in all copies.
|
|
|
|
%%
|
|
|
|
%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
|
|
%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
|
|
%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
|
|
%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
|
%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
|
|
%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
|
|
%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
|
2023-03-31 15:56:23 +08:00
|
|
|
-module(decompress_SUITE).
|
|
|
|
-compile(export_all).
|
|
|
|
-compile(nowarn_export_all).
|
|
|
|
|
|
|
|
-import(ct_helper, [config/2]).
|
|
|
|
-import(ct_helper, [doc/1]).
|
|
|
|
-import(cowboy_test, [gun_open/1]).
|
|
|
|
|
|
|
|
%% ct.
|
|
|
|
|
|
|
|
all() ->
|
|
|
|
cowboy_test:common_all().
|
|
|
|
|
|
|
|
groups() ->
|
|
|
|
cowboy_test:common_groups(ct_helper:all(?MODULE)).
|
|
|
|
|
|
|
|
init_per_group(Name = http, Config) ->
|
|
|
|
cowboy_test:init_http(Name, init_plain_opts(Config), Config);
|
|
|
|
init_per_group(Name = https, Config) ->
|
|
|
|
cowboy_test:init_http(Name, init_plain_opts(Config), Config);
|
|
|
|
init_per_group(Name = h2, Config) ->
|
|
|
|
cowboy_test:init_http2(Name, init_plain_opts(Config), Config);
|
|
|
|
init_per_group(Name = h2c, Config) ->
|
|
|
|
Config1 = cowboy_test:init_http(Name, init_plain_opts(Config), Config),
|
|
|
|
lists:keyreplace(protocol, 1, Config1, {protocol, http2});
|
2023-01-31 11:07:31 +01:00
|
|
|
init_per_group(Name = h3, Config) ->
|
|
|
|
cowboy_test:init_http3(Name, init_plain_opts(Config), Config);
|
2023-03-31 15:56:23 +08:00
|
|
|
init_per_group(Name = http_compress, Config) ->
|
|
|
|
cowboy_test:init_http(Name, init_compress_opts(Config), Config);
|
|
|
|
init_per_group(Name = https_compress, Config) ->
|
|
|
|
cowboy_test:init_http(Name, init_compress_opts(Config), Config);
|
|
|
|
init_per_group(Name = h2_compress, Config) ->
|
|
|
|
cowboy_test:init_http2(Name, init_compress_opts(Config), Config);
|
|
|
|
init_per_group(Name = h2c_compress, Config) ->
|
|
|
|
Config1 = cowboy_test:init_http(Name, init_compress_opts(Config), Config),
|
2023-01-31 11:07:31 +01:00
|
|
|
lists:keyreplace(protocol, 1, Config1, {protocol, http2});
|
|
|
|
init_per_group(Name = h3_compress, Config) ->
|
|
|
|
cowboy_test:init_http3(Name, init_compress_opts(Config), Config).
|
2023-03-31 15:56:23 +08:00
|
|
|
|
|
|
|
end_per_group(Name, _) ->
|
|
|
|
cowboy:stop_listener(Name).
|
|
|
|
|
|
|
|
init_plain_opts(Config) ->
|
|
|
|
#{
|
|
|
|
env => #{dispatch => cowboy_router:compile(init_routes(Config))},
|
|
|
|
stream_handlers => [cowboy_decompress_h, cowboy_stream_h]
|
|
|
|
}.
|
|
|
|
|
|
|
|
init_compress_opts(Config) ->
|
|
|
|
#{
|
|
|
|
env => #{dispatch => cowboy_router:compile(init_routes(Config))},
|
|
|
|
stream_handlers => [cowboy_decompress_h, cowboy_compress_h, cowboy_stream_h]
|
|
|
|
}.
|
|
|
|
|
|
|
|
init_routes(_) ->
|
|
|
|
[{'_', [
|
2024-01-04 15:15:41 +01:00
|
|
|
{"/echo/:what", decompress_h, echo},
|
|
|
|
{"/test/:what", decompress_h, test}
|
2023-03-31 15:56:23 +08:00
|
|
|
]}].
|
|
|
|
|
|
|
|
%% Internal.
|
|
|
|
|
|
|
|
do_post(Path, ReqHeaders, Body, Config) ->
|
|
|
|
ConnPid = gun_open(Config),
|
|
|
|
Ref = gun:post(ConnPid, Path, ReqHeaders, Body),
|
|
|
|
{response, IsFin, Status, RespHeaders} = gun:await(ConnPid, Ref),
|
|
|
|
{ok, ResponseBody} = case IsFin of
|
|
|
|
nofin -> gun:await_body(ConnPid, Ref);
|
|
|
|
fin -> {ok, <<>>}
|
|
|
|
end,
|
|
|
|
gun:close(ConnPid),
|
|
|
|
{Status, RespHeaders, ResponseBody}.
|
|
|
|
|
|
|
|
create_gzip_bomb() ->
|
|
|
|
Z = zlib:open(),
|
|
|
|
zlib:deflateInit(Z, 9, deflated, 31, 8, default),
|
|
|
|
%% 1000 chunks of 100000 zeroes (100MB).
|
|
|
|
Bomb = do_create_gzip_bomb(Z, 1000),
|
|
|
|
zlib:deflateEnd(Z),
|
|
|
|
zlib:close(Z),
|
|
|
|
iolist_to_binary(Bomb).
|
|
|
|
|
|
|
|
do_create_gzip_bomb(Z, 0) ->
|
|
|
|
zlib:deflate(Z, << >>, finish);
|
|
|
|
do_create_gzip_bomb(Z, N) ->
|
|
|
|
Data = <<0:800000>>,
|
|
|
|
Deflate = zlib:deflate(Z, Data),
|
|
|
|
[Deflate | do_create_gzip_bomb(Z, N - 1)].
|
|
|
|
|
|
|
|
%% Tests.
|
|
|
|
|
|
|
|
content_encoding_none(Config) ->
|
2024-01-04 15:15:41 +01:00
|
|
|
doc("Requests without content-encoding are processed normally."),
|
2023-03-31 15:56:23 +08:00
|
|
|
Body = <<"test">>,
|
2024-01-04 15:15:41 +01:00
|
|
|
{200, _, Body} = do_post("/echo/normal", [], Body, Config),
|
|
|
|
%% The content-encoding header would be propagated,
|
|
|
|
%% but there was no content-encoding header to propagate.
|
|
|
|
{200, _, <<"undefined">>} = do_post("/test/content-encoding", [], Body, Config),
|
|
|
|
%% The content_decoded list is empty.
|
|
|
|
{200, _, <<"[]">>} = do_post("/test/content-decoded", [], Body, Config),
|
2023-03-31 15:56:23 +08:00
|
|
|
ok.
|
|
|
|
|
|
|
|
content_encoding_malformed(Config) ->
|
2024-01-04 15:15:41 +01:00
|
|
|
doc("Requests with a malformed content-encoding are processed "
|
|
|
|
"as if no content-encoding was sent."),
|
2023-03-31 15:56:23 +08:00
|
|
|
Body = <<"test">>,
|
|
|
|
{200, _, Body} = do_post("/echo/normal",
|
|
|
|
[{<<"content-encoding">>, <<";">>}], Body, Config),
|
2024-01-04 15:15:41 +01:00
|
|
|
%% The content-encoding header is propagated.
|
|
|
|
{200, _, <<";">>} = do_post("/test/content-encoding",
|
|
|
|
[{<<"content-encoding">>, <<";">>}], Body, Config),
|
|
|
|
%% The content_decoded list is empty.
|
|
|
|
{200, _, <<"[]">>} = do_post("/test/content-decoded",
|
|
|
|
[{<<"content-encoding">>, <<";">>}], Body, Config),
|
2023-03-31 15:56:23 +08:00
|
|
|
ok.
|
|
|
|
|
|
|
|
content_encoding_not_supported(Config) ->
|
2024-01-04 15:15:41 +01:00
|
|
|
doc("Requests with an unsupported content-encoding are processed "
|
|
|
|
"as if no content-encoding was sent."),
|
2023-03-31 15:56:23 +08:00
|
|
|
Body = <<"test">>,
|
|
|
|
{200, _, Body} = do_post("/echo/normal",
|
|
|
|
[{<<"content-encoding">>, <<"compress">>}], Body, Config),
|
2024-01-04 15:15:41 +01:00
|
|
|
%% The content-encoding header is propagated.
|
|
|
|
{200, _, <<"compress">>} = do_post("/test/content-encoding",
|
|
|
|
[{<<"content-encoding">>, <<"compress">>}], Body, Config),
|
|
|
|
%% The content_decoded list is empty.
|
|
|
|
{200, _, <<"[]">>} = do_post("/test/content-decoded",
|
|
|
|
[{<<"content-encoding">>, <<"compress">>}], Body, Config),
|
2023-03-31 15:56:23 +08:00
|
|
|
ok.
|
|
|
|
|
2024-01-04 15:15:41 +01:00
|
|
|
content_encoding_multiple(Config) ->
|
|
|
|
doc("Requests with multiple content-encoding values are processed "
|
|
|
|
"as if no content-encoding was sent."),
|
2023-03-31 15:56:23 +08:00
|
|
|
Body = <<"test">>,
|
2024-01-04 15:15:41 +01:00
|
|
|
{200, _, Body} = do_post("/echo/normal",
|
|
|
|
[{<<"content-encoding">>, <<"gzip, compress">>}], Body, Config),
|
|
|
|
%% The content-encoding header is propagated.
|
|
|
|
{200, _, <<"gzip, compress">>} = do_post("/test/content-encoding",
|
|
|
|
[{<<"content-encoding">>, <<"gzip, compress">>}], Body, Config),
|
|
|
|
%% The content_decoded list is empty.
|
|
|
|
{200, _, <<"[]">>} = do_post("/test/content-decoded",
|
|
|
|
[{<<"content-encoding">>, <<"gzip, compress">>}], Body, Config),
|
2023-03-31 15:56:23 +08:00
|
|
|
ok.
|
|
|
|
|
|
|
|
decompress(Config) ->
|
2024-01-04 15:15:41 +01:00
|
|
|
doc("Requests with content-encoding set to gzip and gzipped data "
|
|
|
|
"are transparently decompressed."),
|
2023-03-31 15:56:23 +08:00
|
|
|
Data = <<"test">>,
|
|
|
|
Body = zlib:gzip(Data),
|
|
|
|
{200, _, Data} = do_post("/echo/normal",
|
|
|
|
[{<<"content-encoding">>, <<"gzip">>}], Body, Config),
|
2024-01-04 15:15:41 +01:00
|
|
|
%% The content-encoding header is NOT propagated.
|
|
|
|
{200, _, <<"undefined">>} = do_post("/test/content-encoding",
|
|
|
|
[{<<"content-encoding">>, <<"gzip">>}], Body, Config),
|
|
|
|
%% The content_decoded list contains <<"gzip">>.
|
|
|
|
{200, _, <<"[<<\"gzip\">>]">>} = do_post("/test/content-decoded",
|
|
|
|
[{<<"content-encoding">>, <<"gzip">>}], Body, Config),
|
|
|
|
ok.
|
|
|
|
|
|
|
|
decompress_error(Config) ->
|
|
|
|
doc("Requests with content-encoding set to gzip but the data "
|
|
|
|
"cannot be decoded are rejected with a 400 Bad Request error."),
|
|
|
|
Body = <<"test">>,
|
|
|
|
{400, _, _} = do_post("/echo/normal",
|
|
|
|
[{<<"content-encoding">>, <<"gzip">>}], Body, Config),
|
2023-03-31 15:56:23 +08:00
|
|
|
ok.
|
|
|
|
|
|
|
|
decompress_stream(Config) ->
|
2024-01-04 15:15:41 +01:00
|
|
|
doc("Requests with content-encoding set to gzip and gzipped data "
|
|
|
|
"are transparently decompressed, even when the data is streamed."),
|
2023-03-31 15:56:23 +08:00
|
|
|
%% Handler read length 1KB. Compressing 3KB should be enough to trigger more.
|
|
|
|
Data = crypto:strong_rand_bytes(3000),
|
|
|
|
Body = zlib:gzip(Data),
|
|
|
|
Size = byte_size(Body),
|
|
|
|
ConnPid = gun_open(Config),
|
2024-01-04 15:15:41 +01:00
|
|
|
Ref = gun:post(ConnPid, "/echo/normal",
|
|
|
|
[{<<"content-encoding">>, <<"gzip">>}]),
|
2023-03-31 15:56:23 +08:00
|
|
|
gun:data(ConnPid, Ref, nofin, binary:part(Body, 0, Size div 2)),
|
|
|
|
timer:sleep(1000),
|
|
|
|
gun:data(ConnPid, Ref, fin, binary:part(Body, Size div 2, Size div 2 + Size rem 2)),
|
|
|
|
{response, IsFin, 200, _} = gun:await(ConnPid, Ref),
|
|
|
|
{ok, Data} = case IsFin of
|
|
|
|
nofin -> gun:await_body(ConnPid, Ref);
|
|
|
|
fin -> {ok, <<>>}
|
|
|
|
end,
|
|
|
|
gun:close(ConnPid),
|
2024-01-04 15:15:41 +01:00
|
|
|
%% The content-encoding header is NOT propagated.
|
|
|
|
ConnPid2 = gun_open(Config),
|
|
|
|
Ref2 = gun:post(ConnPid2, "/test/content-encoding",
|
|
|
|
[{<<"content-encoding">>, <<"gzip">>}]),
|
|
|
|
{response, nofin, 200, _} = gun:await(ConnPid2, Ref2),
|
|
|
|
{ok, <<"undefined">>} = gun:await_body(ConnPid2, Ref2),
|
|
|
|
gun:close(ConnPid2),
|
|
|
|
%% The content_decoded list contains <<"gzip">>.
|
|
|
|
ConnPid3 = gun_open(Config),
|
|
|
|
Ref3 = gun:post(ConnPid3, "/test/content-decoded",
|
|
|
|
[{<<"content-encoding">>, <<"gzip">>}]),
|
|
|
|
{response, nofin, 200, _} = gun:await(ConnPid3, Ref3),
|
|
|
|
{ok, <<"[<<\"gzip\">>]">>} = gun:await_body(ConnPid3, Ref3),
|
|
|
|
gun:close(ConnPid3).
|
|
|
|
|
|
|
|
opts_decompress_enabled_false(Config0) ->
|
|
|
|
doc("Confirm that the decompress_enabled option can be set."),
|
2023-03-31 15:56:23 +08:00
|
|
|
Fun = case config(ref, Config0) of
|
|
|
|
HTTPS when HTTPS =:= https_compress; HTTPS =:= https -> init_https;
|
|
|
|
H2 when H2 =:= h2_compress; H2 =:= h2 -> init_http2;
|
|
|
|
_ -> init_http
|
|
|
|
end,
|
|
|
|
Config = cowboy_test:Fun(?FUNCTION_NAME, #{
|
|
|
|
env => #{dispatch => cowboy_router:compile(init_routes(Config0))},
|
|
|
|
stream_handlers => [cowboy_decompress_h, cowboy_stream_h],
|
2024-01-04 15:15:41 +01:00
|
|
|
decompress_enabled => false
|
2023-03-31 15:56:23 +08:00
|
|
|
}, Config0),
|
|
|
|
Data = <<"test">>,
|
|
|
|
Body = zlib:gzip(Data),
|
|
|
|
try
|
2024-01-04 15:15:41 +01:00
|
|
|
{200, Headers, Body} = do_post("/echo/normal",
|
|
|
|
[{<<"content-encoding">>, <<"gzip">>}], Body, Config),
|
|
|
|
%% We do not set accept-encoding when we are disabled.
|
|
|
|
false = lists:keyfind(<<"accept-encoding">>, 1, Headers)
|
2023-03-31 15:56:23 +08:00
|
|
|
after
|
|
|
|
cowboy:stop_listener(?FUNCTION_NAME)
|
|
|
|
end.
|
|
|
|
|
2024-01-04 15:15:41 +01:00
|
|
|
set_options_decompress_enabled_false(Config) ->
|
|
|
|
doc("Confirm that the decompress_enabled option can be dynamically "
|
|
|
|
"set to false and the data received is not decompressed."),
|
2023-03-31 15:56:23 +08:00
|
|
|
Data = <<"test">>,
|
|
|
|
Body = zlib:gzip(Data),
|
2024-01-04 15:15:41 +01:00
|
|
|
{200, Headers, Body} = do_post("/echo/decompress_disable",
|
2023-03-31 15:56:23 +08:00
|
|
|
[{<<"content-encoding">>, <<"gzip">>}], Body, Config),
|
2024-01-04 15:15:41 +01:00
|
|
|
%% We do not set accept-encoding when we are disabled.
|
|
|
|
false = lists:keyfind(<<"accept-encoding">>, 1, Headers),
|
2023-03-31 15:56:23 +08:00
|
|
|
ok.
|
|
|
|
|
2024-01-04 15:15:41 +01:00
|
|
|
set_options_decompress_disable_in_the_middle(Config) ->
|
|
|
|
doc("Confirm that setting the decompress_enabled option dynamically "
|
|
|
|
"to false after starting to read the body does not disable decompression "
|
|
|
|
"and the data received is decompressed."),
|
|
|
|
Data = rand:bytes(1000000),
|
|
|
|
Body = zlib:gzip(Data),
|
|
|
|
%% Since we were not ignoring before starting to read,
|
|
|
|
%% we receive the entire body decompressed.
|
|
|
|
{200, Headers, Data} = do_post("/test/disable-in-the-middle",
|
|
|
|
[{<<"content-encoding">>, <<"gzip">>}], Body, Config),
|
|
|
|
%% We do set accept-encoding when we are enabled,
|
|
|
|
%% even if an attempt to disable in the middle is ignored.
|
|
|
|
{_, _} = lists:keyfind(<<"accept-encoding">>, 1, Headers),
|
|
|
|
ok.
|
|
|
|
|
|
|
|
set_options_decompress_enable_in_the_middle(Config0) ->
|
|
|
|
doc("Confirm that setting the decompress_enabled option dynamically "
|
|
|
|
"to true after starting to read the body does not enable decompression "
|
|
|
|
"and the data received is not decompressed."),
|
|
|
|
Fun = case config(ref, Config0) of
|
|
|
|
HTTPS when HTTPS =:= https_compress; HTTPS =:= https -> init_https;
|
|
|
|
H2 when H2 =:= h2_compress; H2 =:= h2 -> init_http2;
|
|
|
|
_ -> init_http
|
|
|
|
end,
|
|
|
|
Config = cowboy_test:Fun(?FUNCTION_NAME, #{
|
|
|
|
env => #{dispatch => cowboy_router:compile(init_routes(Config0))},
|
|
|
|
stream_handlers => [cowboy_decompress_h, cowboy_stream_h],
|
|
|
|
decompress_enabled => false
|
|
|
|
}, Config0),
|
|
|
|
Data = rand:bytes(1000000),
|
|
|
|
Body = zlib:gzip(Data),
|
|
|
|
try
|
|
|
|
%% Since we were ignoring before starting to read,
|
|
|
|
%% we receive the entire body compressed.
|
|
|
|
{200, Headers, Body} = do_post("/test/enable-in-the-middle",
|
|
|
|
[{<<"content-encoding">>, <<"gzip">>}], Body, Config),
|
|
|
|
%% We do not set accept-encoding when we are disabled,
|
|
|
|
%% even if an attempt to enable in the middle is ignored.
|
|
|
|
false = lists:keyfind(<<"accept-encoding">>, 1, Headers)
|
|
|
|
after
|
|
|
|
cowboy:stop_listener(?FUNCTION_NAME)
|
|
|
|
end.
|
|
|
|
|
2023-03-31 15:56:23 +08:00
|
|
|
opts_decompress_ratio_limit(Config0) ->
|
2024-01-04 15:15:41 +01:00
|
|
|
doc("Confirm that the decompress_ratio_limit option can be set."),
|
2023-03-31 15:56:23 +08:00
|
|
|
Fun = case config(ref, Config0) of
|
|
|
|
HTTPS when HTTPS =:= https_compress; HTTPS =:= https -> init_https;
|
|
|
|
H2 when H2 =:= h2_compress; H2 =:= h2 -> init_http2;
|
|
|
|
_ -> init_http
|
|
|
|
end,
|
|
|
|
Config = cowboy_test:Fun(?FUNCTION_NAME, #{
|
|
|
|
env => #{dispatch => cowboy_router:compile(init_routes(Config0))},
|
|
|
|
stream_handlers => [cowboy_decompress_h, cowboy_stream_h],
|
|
|
|
decompress_ratio_limit => 1
|
|
|
|
}, Config0),
|
2024-01-04 15:15:41 +01:00
|
|
|
%% Data must be big enough for compression to be effective,
|
|
|
|
%% so that ratio_limit=1 will fail.
|
2023-03-31 15:56:23 +08:00
|
|
|
Data = <<0:800>>,
|
|
|
|
Body = zlib:gzip(Data),
|
|
|
|
try
|
|
|
|
{413, _, _} = do_post("/echo/normal",
|
|
|
|
[{<<"content-encoding">>, <<"gzip">>}], Body, Config)
|
|
|
|
after
|
|
|
|
cowboy:stop_listener(?FUNCTION_NAME)
|
|
|
|
end.
|
|
|
|
|
|
|
|
set_options_decompress_ratio_limit(Config) ->
|
|
|
|
doc("Confirm that the decompress_ratio_limit option can be dynamically set."),
|
2024-01-04 15:15:41 +01:00
|
|
|
%% Data must be big enough for compression to be effective,
|
|
|
|
%% so that ratio_limit=1 will fail.
|
2023-03-31 15:56:23 +08:00
|
|
|
Data = <<0:800>>,
|
|
|
|
Body = zlib:gzip(Data),
|
|
|
|
{413, _, _} = do_post("/echo/decompress_ratio_limit",
|
|
|
|
[{<<"content-encoding">>, <<"gzip">>}], Body, Config),
|
|
|
|
ok.
|
|
|
|
|
|
|
|
gzip_bomb(Config) ->
|
2024-01-04 15:15:41 +01:00
|
|
|
doc("Confirm that requests are rejected with a 413 Payload Too Large "
|
|
|
|
"error when the ratio limit is exceeded."),
|
2023-03-31 15:56:23 +08:00
|
|
|
Body = create_gzip_bomb(),
|
|
|
|
{413, _, _} = do_post("/echo/normal",
|
|
|
|
[{<<"content-encoding">>, <<"gzip">>}], Body, Config),
|
|
|
|
ok.
|
|
|
|
|
|
|
|
set_accept_encoding_response(Config) ->
|
2024-01-04 15:15:41 +01:00
|
|
|
doc("Header accept-encoding must be set on valid response command. "
|
|
|
|
"(RFC9110 12.5.3)"),
|
2023-03-31 15:56:23 +08:00
|
|
|
Data = <<"test">>,
|
|
|
|
Body = zlib:gzip(Data),
|
|
|
|
{200, Headers, Data} = do_post("/echo/normal",
|
|
|
|
[{<<"content-encoding">>, <<"gzip">>}], Body, Config),
|
|
|
|
{_, <<"gzip">>} = lists:keyfind(<<"accept-encoding">>, 1, Headers),
|
|
|
|
ok.
|
|
|
|
|
|
|
|
set_accept_encoding_header(Config) ->
|
2024-01-04 15:15:41 +01:00
|
|
|
doc("Header accept-encoding must be set on valid header command. "
|
|
|
|
"(RFC9110 12.5.3)"),
|
2023-03-31 15:56:23 +08:00
|
|
|
Data = <<"test">>,
|
|
|
|
Body = zlib:gzip(Data),
|
2024-01-04 15:15:41 +01:00
|
|
|
{200, Headers, Data} = do_post("/test/header-command",
|
2023-03-31 15:56:23 +08:00
|
|
|
[{<<"content-encoding">>, <<"gzip">>}], Body, Config),
|
|
|
|
{_, <<"gzip">>} = lists:keyfind(<<"accept-encoding">>, 1, Headers),
|
|
|
|
ok.
|
|
|
|
|
|
|
|
add_accept_encoding_header_valid(Config) ->
|
2024-01-04 15:15:41 +01:00
|
|
|
doc("Supported content codings must be added to the accept-encoding "
|
|
|
|
"header if it already exists. (RFC9110 12.5.3)"),
|
2023-03-31 15:56:23 +08:00
|
|
|
Data = <<"test">>,
|
|
|
|
Body = zlib:gzip(Data),
|
2024-01-04 15:15:41 +01:00
|
|
|
{200, Headers, Data} = do_post("/test/accept-identity",
|
2023-03-31 15:56:23 +08:00
|
|
|
[{<<"content-encoding">>, <<"gzip">>}], Body, Config),
|
|
|
|
{_, <<"identity, gzip">>} = lists:keyfind(<<"accept-encoding">>, 1, Headers),
|
|
|
|
ok.
|
|
|
|
|
|
|
|
override_accept_encoding_header_invalid(Config) ->
|
2024-01-04 15:15:41 +01:00
|
|
|
doc("When the stream handler cannot parse the accept-encoding header "
|
|
|
|
"found in the response, it overrides it."),
|
2023-03-31 15:56:23 +08:00
|
|
|
Data = <<"test">>,
|
|
|
|
Body = zlib:gzip(Data),
|
2024-01-04 15:15:41 +01:00
|
|
|
{200, Headers, Data} = do_post("/test/invalid-header",
|
2023-03-31 15:56:23 +08:00
|
|
|
[{<<"content-encoding">>, <<"gzip">>}], Body, Config),
|
|
|
|
{_, <<"gzip">>} = lists:keyfind(<<"accept-encoding">>, 1, Headers),
|
|
|
|
ok.
|
|
|
|
|
|
|
|
override_accept_encoding_excluded(Config) ->
|
2024-01-04 15:15:41 +01:00
|
|
|
doc("The stream handler must ensure that the content encodings "
|
|
|
|
"it supports are not marked as unsupported in response headers. "
|
|
|
|
"The stream handler enables gzip when explicitly excluded. "
|
|
|
|
"(RFC9110 12.5.3)"),
|
2023-03-31 15:56:23 +08:00
|
|
|
Data = <<"test">>,
|
|
|
|
Body = zlib:gzip(Data),
|
2024-01-04 15:15:41 +01:00
|
|
|
{200, Headers, Data} = do_post("/test/reject-explicit-header",
|
2023-03-31 15:56:23 +08:00
|
|
|
[{<<"content-encoding">>, <<"gzip">>}], Body, Config),
|
|
|
|
{_, <<"identity;q=1, gzip;q=1">>} = lists:keyfind(<<"accept-encoding">>, 1, Headers),
|
|
|
|
ok.
|
|
|
|
|
2024-01-04 15:15:41 +01:00
|
|
|
%% *;q=0 will reject codings that are not listed. Supported codings
|
|
|
|
%% must always be enabled when the handler is used.
|
2023-03-31 15:56:23 +08:00
|
|
|
add_accept_encoding_excluded(Config) ->
|
2024-01-04 15:15:41 +01:00
|
|
|
doc("The stream handler must ensure that the content encodings "
|
|
|
|
"it supports are not marked as unsupported in response headers. "
|
|
|
|
"The stream handler enables gzip when implicitly excluded (*;q=0). "
|
|
|
|
"(RFC9110 12.5.3)"),
|
2023-03-31 15:56:23 +08:00
|
|
|
Data = <<"test">>,
|
|
|
|
Body = zlib:gzip(Data),
|
2024-01-04 15:15:41 +01:00
|
|
|
{200, Headers, Data} = do_post("/test/reject-implicit-header",
|
2023-03-31 15:56:23 +08:00
|
|
|
[{<<"content-encoding">>, <<"gzip">>}], Body, Config),
|
|
|
|
{_, <<"gzip;q=1, identity;q=1, *;q=0">>} = lists:keyfind(<<"accept-encoding">>, 1, Headers),
|
|
|
|
ok.
|
|
|
|
|
|
|
|
no_override_accept_coding_set_explicit(Config) ->
|
2024-01-04 15:15:41 +01:00
|
|
|
doc("Confirm that accept-encoding is not overridden when the "
|
|
|
|
"content encodings it supports are explicitly set. "
|
|
|
|
"(RFC9110 12.5.3)"),
|
2023-03-31 15:56:23 +08:00
|
|
|
Data = <<"test">>,
|
|
|
|
Body = zlib:gzip(Data),
|
2024-01-04 15:15:41 +01:00
|
|
|
{200, Headers, Data} = do_post("/test/accept-explicit-header",
|
2023-03-31 15:56:23 +08:00
|
|
|
[{<<"content-encoding">>, <<"gzip">>}], Body, Config),
|
|
|
|
{_, <<"identity, gzip;q=0.5">>} = lists:keyfind(<<"accept-encoding">>, 1, Headers),
|
|
|
|
ok.
|
|
|
|
|
|
|
|
no_override_accept_coding_set_implicit(Config) ->
|
2024-01-04 15:15:41 +01:00
|
|
|
doc("Confirm that accept-encoding is not overridden when the "
|
|
|
|
"content encodings it supports are implicitly set. "
|
|
|
|
"(RFC9110 12.5.3)"),
|
2023-03-31 15:56:23 +08:00
|
|
|
Data = <<"test">>,
|
|
|
|
Body = zlib:gzip(Data),
|
2024-01-04 15:15:41 +01:00
|
|
|
{200, Headers, Data} = do_post("/test/accept-implicit-header",
|
2023-03-31 15:56:23 +08:00
|
|
|
[{<<"content-encoding">>, <<"gzip">>}], Body, Config),
|
|
|
|
{_, <<"identity, *;q=0.5">>} = lists:keyfind(<<"accept-encoding">>, 1, Headers),
|
|
|
|
ok.
|