From 09bf1199aa3e33a73970ee4ce38714be087b0df0 Mon Sep 17 00:00:00 2001 From: Steve Domin Date: Sat, 17 Feb 2018 16:43:46 +0300 Subject: [PATCH] Add compress_threshold protocol option Currently the compression threshold is set to 300 and hardcoded in the codebase. There are cases where it make sense to allow this to be configured, for instance when you want to enforce all responses to be compressed regarldess of their size. --- src/cowboy_compress_h.erl | 12 +++++++----- src/cowboy_http.erl | 5 ++++- src/cowboy_http2.erl | 5 ++++- test/handlers/compress_h.erl | 2 ++ 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/cowboy_compress_h.erl b/src/cowboy_compress_h.erl index fb5ed713..781cc0a9 100644 --- a/src/cowboy_compress_h.erl +++ b/src/cowboy_compress_h.erl @@ -23,6 +23,7 @@ -record(state, { next :: any(), + threshold :: non_neg_integer() | undefined, compress = undefined :: undefined | gzip, deflate = undefined :: undefined | zlib:zstream() }). @@ -31,8 +32,9 @@ -> {cowboy_stream:commands(), #state{}}. init(StreamID, Req, Opts) -> State0 = check_req(Req), + CompressThreshold = maps:get(compress_threshold, Opts, 300), {Commands0, Next} = cowboy_stream:init(StreamID, Req, Opts), - fold(Commands0, State0#state{next=Next}). + fold(Commands0, State0#state{next=Next, threshold=CompressThreshold}). -spec data(cowboy_stream:streamid(), cowboy_stream:fin(), cowboy_req:resp_body(), State) -> {cowboy_stream:commands(), State} when State::#state{}. @@ -100,16 +102,16 @@ fold([], State, Acc) -> fold([Response={response, _, _, {sendfile, _, _, _}}|Tail], State, Acc) -> fold(Tail, State, [Response|Acc]); %% We compress full responses directly, unless they are lower than -%% 300 bytes or we find we are not able to by looking at the headers. -%% @todo It might be good to allow this size to be configured? -fold([Response0={response, _, Headers, Body}|Tail], State0, Acc) -> +%% the configured threshold or we find we are not able to by looking at the headers. +fold([Response0={response, _, Headers, Body}|Tail], + State0=#state{threshold=CompressThreshold}, Acc) -> case check_resp_headers(Headers, State0) of State=#state{compress=undefined} -> fold(Tail, State, [Response0|Acc]); State1 -> BodyLength = iolist_size(Body), if - BodyLength =< 300 -> + BodyLength =< CompressThreshold -> fold(Tail, State1, [Response0|Acc]); true -> {Response, State} = gzip_response(Response0, State1), diff --git a/src/cowboy_http.erl b/src/cowboy_http.erl index 340ced7b..91a539f4 100644 --- a/src/cowboy_http.erl +++ b/src/cowboy_http.erl @@ -25,6 +25,7 @@ -export([system_code_change/4]). -type opts() :: #{ + compress_threshold => non_neg_integer(), connection_type => worker | supervisor, env => cowboy_middleware:env(), idle_timeout => timeout(), @@ -46,7 +47,9 @@ shutdown_timeout => timeout(), stream_handlers => [module()], tracer_callback => cowboy_tracer_h:tracer_callback(), - tracer_match_specs => cowboy_tracer_h:tracer_match_specs() + tracer_match_specs => cowboy_tracer_h:tracer_match_specs(), + %% Open ended because configured stream handlers might add options. + _ => _ }. -export_type([opts/0]). diff --git a/src/cowboy_http2.erl b/src/cowboy_http2.erl index f6f9cf53..a1dd93ee 100644 --- a/src/cowboy_http2.erl +++ b/src/cowboy_http2.erl @@ -27,6 +27,7 @@ -export([system_code_change/4]). -type opts() :: #{ + compress_threshold => non_neg_integer(), connection_type => worker | supervisor, enable_connect_protocol => boolean(), env => cowboy_middleware:env(), @@ -47,7 +48,9 @@ shutdown_timeout => timeout(), stream_handlers => [module()], tracer_callback => cowboy_tracer_h:tracer_callback(), - tracer_match_specs => cowboy_tracer_h:tracer_match_specs() + tracer_match_specs => cowboy_tracer_h:tracer_match_specs(), + %% Open ended because configured stream handlers might add options. + _ => _ }. -export_type([opts/0]). diff --git a/test/handlers/compress_h.erl b/test/handlers/compress_h.erl index 5787b667..4b4dbe73 100644 --- a/test/handlers/compress_h.erl +++ b/test/handlers/compress_h.erl @@ -11,6 +11,8 @@ init(Req0, State=reply) -> cowboy_req:reply(200, #{}, lists:duplicate(100, $a), Req0); <<"large">> -> cowboy_req:reply(200, #{}, lists:duplicate(100000, $a), Req0); + <<"over-threshold">> -> + cowboy_req:reply(200, #{}, lists:duplicate(200, $a), Req0); <<"content-encoding">> -> cowboy_req:reply(200, #{<<"content-encoding">> => <<"compress">>}, lists:duplicate(100000, $a), Req0);