diff options
author | Loïc Hoguin <[email protected]> | 2024-01-04 15:15:41 +0100 |
---|---|---|
committer | Loïc Hoguin <[email protected]> | 2024-01-04 15:50:12 +0100 |
commit | fd9711d9495e4ddcd41eda7a284dfc7f37c11f15 (patch) | |
tree | 887d4f6569b7bf06ee584ad50b2fe9647b7394c6 /test/handlers/decompress_h.erl | |
parent | 3ed1b24dd6ef6cd3e78a2fa6d600cce082b6984a (diff) | |
download | cowboy-fd9711d9495e4ddcd41eda7a284dfc7f37c11f15.tar.gz cowboy-fd9711d9495e4ddcd41eda7a284dfc7f37c11f15.tar.bz2 cowboy-fd9711d9495e4ddcd41eda7a284dfc7f37c11f15.zip |
Rework and improve the decompress stream handler
The read buffer was changed into an iovec to avoid doing
too many binary concatenations and allocations.
Decompression happens transparently: when decoding gzip,
the content-encoding header is removed (we only decode
when "gzip" is the only encoding so nothing remains).
We always add a content_decoded key to the Req object.
This key contains a list of codings that were decoded,
in the reverse order in which they were. Currently it
can only be empty or contain <<"gzip">> but future
improvements or user handlers may see it contain more
values.
The option to disable decompression was renamed to
decompress_enabled and defaults to true.
It is no longer possible to enable/disable decompression
in the middle of reading the body: this ensures that the
data we pass forward is always valid.
Various smaller improvements were made to the code,
tests and manual pages.
Diffstat (limited to 'test/handlers/decompress_h.erl')
-rw-r--r-- | test/handlers/decompress_h.erl | 98 |
1 files changed, 57 insertions, 41 deletions
diff --git a/test/handlers/decompress_h.erl b/test/handlers/decompress_h.erl index 346200b..deb6de0 100644 --- a/test/handlers/decompress_h.erl +++ b/test/handlers/decompress_h.erl @@ -5,10 +5,10 @@ -export([init/2]). -init(Req0, State=[]) -> +init(Req0, State=echo) -> case cowboy_req:binding(what, Req0) of - <<"decompress_ignore">> -> - cowboy_req:cast({set_options, #{decompress_ignore => true}}, Req0); + <<"decompress_disable">> -> + cowboy_req:cast({set_options, #{decompress_enabled => false}}, Req0); <<"decompress_ratio_limit">> -> cowboy_req:cast({set_options, #{decompress_ratio_limit => 0.5}}, Req0); <<"normal">> -> ok @@ -16,46 +16,62 @@ init(Req0, State=[]) -> {ok, Body, Req1} = read_body(Req0), Req = cowboy_req:reply(200, #{}, Body, Req1), {ok, Req, State}; +init(Req0, State=test) -> + Req = test(Req0, cowboy_req:binding(what, Req0)), + {ok, Req, State}. -init(Req0, State=header_command) -> - {ok, Body, Req1} = read_body(Req0), - Req2 = cowboy_req:stream_reply(200, #{}, Req1), - Req = cowboy_req:stream_body(Body, fin, Req2), - {ok, Req, State}; - -init(Req0, State=accept_identity) -> - {ok, Body, Req1} = read_body(Req0), - Req = cowboy_req:reply(200, #{<<"accept-encoding">> => <<"identity">>}, Body, Req1), - {ok, Req, State}; - -init(Req0, State=invalid_header) -> - {ok, Body, Req1} = read_body(Req0), - Req = cowboy_req:reply(200, #{<<"accept-encoding">> => <<";">>}, Body, Req1), - {ok, Req, State}; - -init(Req0, State=reject_explicit_header) -> - {ok, Body, Req1} = read_body(Req0), - Req = cowboy_req:reply(200, #{<<"accept-encoding">> => <<"identity, gzip;q=0">>}, - Body, Req1), - {ok, Req, State}; - -init(Req0, State=reject_implicit_header) -> - {ok, Body, Req1} = read_body(Req0), - Req = cowboy_req:reply(200, #{<<"accept-encoding">> => <<"identity, *;q=0">>}, - Body, Req1), - {ok, Req, State}; - -init(Req0, State=accept_explicit_header) -> - {ok, Body, Req1} = read_body(Req0), - Req = cowboy_req:reply(200, #{<<"accept-encoding">> => <<"identity, gzip;q=0.5">>}, - Body, Req1), - {ok, Req, State}; - -init(Req0, State=accept_implicit_header) -> +test(Req, <<"content-encoding">>) -> + cowboy_req:reply(200, #{}, + cowboy_req:header(<<"content-encoding">>, Req, <<"undefined">>), + Req); +test(Req, <<"content-decoded">>) -> + cowboy_req:reply(200, #{}, + io_lib:format("~0p", [maps:get(content_decoded, Req, undefined)]), + Req); +test(Req0, <<"disable-in-the-middle">>) -> + {Status, Data, Req1} = cowboy_req:read_body(Req0, #{length => 1000}), + cowboy_req:cast({set_options, #{decompress_enabled => false}}, Req1), + {ok, Body, Req} = do_read_body(Status, Req1, Data), + cowboy_req:reply(200, #{}, Body, Req); +test(Req0, <<"enable-in-the-middle">>) -> + {Status, Data, Req1} = cowboy_req:read_body(Req0, #{length => 1000}), + cowboy_req:cast({set_options, #{decompress_enabled => true}}, Req1), + {ok, Body, Req} = do_read_body(Status, Req1, Data), + cowboy_req:reply(200, #{}, Body, Req); +test(Req0, <<"header-command">>) -> {ok, Body, Req1} = read_body(Req0), - Req = cowboy_req:reply(200, #{<<"accept-encoding">> => <<"identity, *;q=0.5">>}, - Body, Req1), - {ok, Req, State}. + Req = cowboy_req:stream_reply(200, #{}, Req1), + cowboy_req:stream_body(Body, fin, Req); +test(Req0, <<"accept-identity">>) -> + {ok, Body, Req} = read_body(Req0), + cowboy_req:reply(200, + #{<<"accept-encoding">> => <<"identity">>}, + Body, Req); +test(Req0, <<"invalid-header">>) -> + {ok, Body, Req} = read_body(Req0), + cowboy_req:reply(200, + #{<<"accept-encoding">> => <<";">>}, + Body, Req); +test(Req0, <<"reject-explicit-header">>) -> + {ok, Body, Req} = read_body(Req0), + cowboy_req:reply(200, + #{<<"accept-encoding">> => <<"identity, gzip;q=0">>}, + Body, Req); +test(Req0, <<"reject-implicit-header">>) -> + {ok, Body, Req} = read_body(Req0), + cowboy_req:reply(200, + #{<<"accept-encoding">> => <<"identity, *;q=0">>}, + Body, Req); +test(Req0, <<"accept-explicit-header">>) -> + {ok, Body, Req} = read_body(Req0), + cowboy_req:reply(200, + #{<<"accept-encoding">> => <<"identity, gzip;q=0.5">>}, + Body, Req); +test(Req0, <<"accept-implicit-header">>) -> + {ok, Body, Req} = read_body(Req0), + cowboy_req:reply(200, + #{<<"accept-encoding">> => <<"identity, *;q=0.5">>}, + Body, Req). read_body(Req0) -> {Status, Data, Req} = cowboy_req:read_body(Req0, #{length => 1000}), |