mirror of
https://github.com/ninenines/cowboy.git
synced 2025-07-14 12:20:24 +00:00
Don't automatically compress when response has etag
In the cowboy_compress_h stream handler. Otherwise this could cause issues with caching, with the etag being the same for compressed/uncompressed content. Users that wish to send etags AND compress will have to do it manually for the time being.
This commit is contained in:
parent
67df6fedae
commit
5b2f600036
4 changed files with 31 additions and 1 deletions
|
@ -9,7 +9,7 @@ cowboy_compress_h - Compress stream handler
|
||||||
The module `cowboy_compress_h` compresses response bodies
|
The module `cowboy_compress_h` compresses response bodies
|
||||||
automatically when the client supports it. It will not
|
automatically when the client supports it. It will not
|
||||||
try to compress responses that already have a content
|
try to compress responses that already have a content
|
||||||
encoding.
|
encoding or that have an etag header defined.
|
||||||
|
|
||||||
Normal responses will only be compressed when their
|
Normal responses will only be compressed when their
|
||||||
size is lower than the configured threshold. Streamed
|
size is lower than the configured threshold. Streamed
|
||||||
|
@ -55,6 +55,8 @@ The compress stream handler does not produce any event.
|
||||||
|
|
||||||
== Changelog
|
== Changelog
|
||||||
|
|
||||||
|
* *2.11*: Compression is now disabled when the etag
|
||||||
|
header is in the response headers.
|
||||||
* *2.6*: The options `compress_buffering` and
|
* *2.6*: The options `compress_buffering` and
|
||||||
`compress_threshold` were added.
|
`compress_threshold` were added.
|
||||||
* *2.0*: Module introduced.
|
* *2.0*: Module introduced.
|
||||||
|
|
|
@ -96,6 +96,9 @@ check_req(Req) ->
|
||||||
%% Do not compress responses that contain the content-encoding header.
|
%% Do not compress responses that contain the content-encoding header.
|
||||||
check_resp_headers(#{<<"content-encoding">> := _}, State) ->
|
check_resp_headers(#{<<"content-encoding">> := _}, State) ->
|
||||||
State#state{compress=undefined};
|
State#state{compress=undefined};
|
||||||
|
%% Do not compress responses that contain the etag header.
|
||||||
|
check_resp_headers(#{<<"etag">> := _}, State) ->
|
||||||
|
State#state{compress=undefined};
|
||||||
check_resp_headers(_, State) ->
|
check_resp_headers(_, State) ->
|
||||||
State.
|
State.
|
||||||
|
|
||||||
|
|
|
@ -109,6 +109,17 @@ gzip_reply_content_encoding(Config) ->
|
||||||
{_, <<"100000">>} = lists:keyfind(<<"content-length">>, 1, Headers),
|
{_, <<"100000">>} = lists:keyfind(<<"content-length">>, 1, Headers),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
|
gzip_reply_etag(Config) ->
|
||||||
|
doc("Reply with etag header; get an uncompressed response."),
|
||||||
|
{200, Headers, _} = do_get("/reply/etag",
|
||||||
|
[{<<"accept-encoding">>, <<"gzip">>}], Config),
|
||||||
|
%% We set a strong etag.
|
||||||
|
{_, <<"\"STRONK\"">>} = lists:keyfind(<<"etag">>, 1, Headers),
|
||||||
|
%% The reply didn't include a vary header.
|
||||||
|
false = lists:keyfind(<<"vary">>, 1, Headers),
|
||||||
|
{_, <<"100000">>} = lists:keyfind(<<"content-length">>, 1, Headers),
|
||||||
|
ok.
|
||||||
|
|
||||||
gzip_reply_large_body(Config) ->
|
gzip_reply_large_body(Config) ->
|
||||||
doc("Reply a large body; get a gzipped response."),
|
doc("Reply a large body; get a gzipped response."),
|
||||||
{200, Headers, GzBody} = do_get("/reply/large",
|
{200, Headers, GzBody} = do_get("/reply/large",
|
||||||
|
@ -174,6 +185,15 @@ gzip_stream_reply_content_encoding(Config) ->
|
||||||
100000 = iolist_size(Body),
|
100000 = iolist_size(Body),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
|
gzip_stream_reply_etag(Config) ->
|
||||||
|
doc("Stream reply with etag header; get an uncompressed response."),
|
||||||
|
{200, Headers, Body} = do_get("/stream_reply/etag",
|
||||||
|
[{<<"accept-encoding">>, <<"gzip">>}], Config),
|
||||||
|
{_, <<"\"STRONK\"">>} = lists:keyfind(<<"etag">>, 1, Headers),
|
||||||
|
false = lists:keyfind(<<"vary">>, 1, Headers),
|
||||||
|
100000 = iolist_size(Body),
|
||||||
|
ok.
|
||||||
|
|
||||||
opts_compress_buffering_false(Config0) ->
|
opts_compress_buffering_false(Config0) ->
|
||||||
doc("Confirm that the compress_buffering option can be set to false, "
|
doc("Confirm that the compress_buffering option can be set to false, "
|
||||||
"which is the default."),
|
"which is the default."),
|
||||||
|
|
|
@ -19,6 +19,9 @@ init(Req0, State=reply) ->
|
||||||
<<"content-encoding">> ->
|
<<"content-encoding">> ->
|
||||||
cowboy_req:reply(200, #{<<"content-encoding">> => <<"compress">>},
|
cowboy_req:reply(200, #{<<"content-encoding">> => <<"compress">>},
|
||||||
lists:duplicate(100000, $a), Req0);
|
lists:duplicate(100000, $a), Req0);
|
||||||
|
<<"etag">> ->
|
||||||
|
cowboy_req:reply(200, #{<<"etag">> => <<"\"STRONK\"">>},
|
||||||
|
lists:duplicate(100000, $a), Req0);
|
||||||
<<"sendfile">> ->
|
<<"sendfile">> ->
|
||||||
AppFile = code:where_is_file("cowboy.app"),
|
AppFile = code:where_is_file("cowboy.app"),
|
||||||
Size = filelib:file_size(AppFile),
|
Size = filelib:file_size(AppFile),
|
||||||
|
@ -34,6 +37,8 @@ init(Req0, State=stream_reply) ->
|
||||||
stream_reply(#{}, Req0);
|
stream_reply(#{}, Req0);
|
||||||
<<"content-encoding">> ->
|
<<"content-encoding">> ->
|
||||||
stream_reply(#{<<"content-encoding">> => <<"compress">>}, Req0);
|
stream_reply(#{<<"content-encoding">> => <<"compress">>}, Req0);
|
||||||
|
<<"etag">> ->
|
||||||
|
stream_reply(#{<<"etag">> => <<"\"STRONK\"">>}, Req0);
|
||||||
<<"sendfile">> ->
|
<<"sendfile">> ->
|
||||||
Data = lists:duplicate(10000, $a),
|
Data = lists:duplicate(10000, $a),
|
||||||
AppFile = code:where_is_file("cowboy.app"),
|
AppFile = code:where_is_file("cowboy.app"),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue