Browse Source

Add optional automatic response body compression

This behavior can be enabled with the `compress` protocol option.
See the `compress_response` example for more details.

All tests are now ran with and without compression for both HTTP
and HTTPS.
Loïc Hoguin 12 years ago
parent
commit
01f57ad65d

+ 1 - 1
Makefile

@@ -67,7 +67,7 @@ autobahn:
 
 
 build-plt: app
 build-plt: app
 	@dialyzer --build_plt --output_plt .$(PROJECT).plt \
 	@dialyzer --build_plt --output_plt .$(PROJECT).plt \
-		--apps kernel stdlib sasl inets crypto public_key ssl deps/ranch
+		--apps erts kernel stdlib sasl inets crypto public_key ssl deps/ranch
 
 
 dialyze:
 dialyze:
 	@dialyzer --src src --plt .$(PROJECT).plt --no_native \
 	@dialyzer --src src --plt .$(PROJECT).plt --no_native \

+ 3 - 0
examples/README.md

@@ -4,6 +4,9 @@ Cowboy Examples
  *  [chunked_hello_world](./examples/chunked_hello_world):
  *  [chunked_hello_world](./examples/chunked_hello_world):
     demonstrates chunked data transfer with two one-second delays
     demonstrates chunked data transfer with two one-second delays
 
 
+ *  [compress_response](./examples/compress_response)
+    send a response body compressed if the client supports it
+
  *  [cookie](./examples/cookie):
  *  [cookie](./examples/cookie):
     set cookies from server and client side
     set cookies from server and client side
 
 

+ 62 - 0
examples/compress_response/README.md

@@ -0,0 +1,62 @@
+Cowboy Compress Response
+========================
+
+To compile this example you need rebar in your PATH.
+
+Type the following command:
+```
+$ rebar get-deps compile
+```
+
+You can then start the Erlang node with the following command:
+```
+./start.sh
+```
+
+Then point your browser to the indicated URL.
+
+Example
+-------
+
+``` bash
+$ curl -i http://localhost:8080
+HTTP/1.1 200 OK
+connection: keep-alive
+server: Cowboy
+date: Mon, 07 Jan 2013 18:42:29 GMT
+content-length: 909
+
+A cowboy is an animal herder who tends cattle on ranches in North America,
+traditionally on horseback, and often performs a multitude of other ranch-
+related tasks. The historic American cowboy of the late 19th century arose
+from the vaquero traditions of northern Mexico and became a figure of special
+significance and legend. A subtype, called a wrangler, specifically tends the
+horses used to work cattle. In addition to ranch work, some cowboys work for
+or participate in rodeos. Cowgirls, first defined as such in the late 19th
+century, had a less-well documented historical role, but in the modern world
+have established the ability to work at virtually identical tasks and obtained
+considerable respect for their achievements. There are also cattle handlers
+in many other parts of the world, particularly South America and Australia,
+who perform work similar to the cowboy in their respective nations.
+
+$ curl -i --compressed http://localhost:8080
+HTTP/1.1 200 OK
+connection: keep-alive
+server: Cowboy
+date: Mon, 07 Jan 2013 18:42:30 GMT
+content-encoding: gzip
+content-length: 510
+
+A cowboy is an animal herder who tends cattle on ranches in North America,
+traditionally on horseback, and often performs a multitude of other ranch-
+related tasks. The historic American cowboy of the late 19th century arose
+from the vaquero traditions of northern Mexico and became a figure of special
+significance and legend. A subtype, called a wrangler, specifically tends the
+horses used to work cattle. In addition to ranch work, some cowboys work for
+or participate in rodeos. Cowgirls, first defined as such in the late 19th
+century, had a less-well documented historical role, but in the modern world
+have established the ability to work at virtually identical tasks and obtained
+considerable respect for their achievements. There are also cattle handlers
+in many other parts of the world, particularly South America and Australia,
+who perform work similar to the cowboy in their respective nations.
+```

+ 4 - 0
examples/compress_response/rebar.config

@@ -0,0 +1,4 @@
+{deps, [
+	{cowboy, ".*",
+		{git, "git://github.com/extend/cowboy.git", "master"}}
+]}.

+ 15 - 0
examples/compress_response/src/compress_response.app.src

@@ -0,0 +1,15 @@
+%% Feel free to use, reuse and abuse the code in this file.
+
+{application, compress_response, [
+	{description, "Cowboy Compress Response example."},
+	{vsn, "1"},
+	{modules, []},
+	{registered, []},
+	{applications, [
+		kernel,
+		stdlib,
+		cowboy
+	]},
+	{mod, {compress_response_app, []}},
+	{env, []}
+]}.

+ 14 - 0
examples/compress_response/src/compress_response.erl

@@ -0,0 +1,14 @@
+%% Feel free to use, reuse and abuse the code in this file.
+
+-module(compress_response).
+
+%% API.
+-export([start/0]).
+
+%% API.
+
+start() ->
+	ok = application:start(crypto),
+	ok = application:start(ranch),
+	ok = application:start(cowboy),
+	ok = application:start(compress_response).

+ 26 - 0
examples/compress_response/src/compress_response_app.erl

@@ -0,0 +1,26 @@
+%% Feel free to use, reuse and abuse the code in this file.
+
+%% @private
+-module(compress_response_app).
+-behaviour(application).
+
+%% API.
+-export([start/2]).
+-export([stop/1]).
+
+%% API.
+
+start(_Type, _Args) ->
+	Dispatch = [
+		{'_', [
+			{[], toppage_handler, []}
+		]}
+	],
+	{ok, _} = cowboy:start_http(http, 100, [{port, 8080}], [
+		{compress, true},
+		{env, [{dispatch, Dispatch}]}
+	]),
+	compress_response_sup:start_link().
+
+stop(_State) ->
+	ok.

+ 23 - 0
examples/compress_response/src/compress_response_sup.erl

@@ -0,0 +1,23 @@
+%% Feel free to use, reuse and abuse the code in this file.
+
+%% @private
+-module(compress_response_sup).
+-behaviour(supervisor).
+
+%% API.
+-export([start_link/0]).
+
+%% supervisor.
+-export([init/1]).
+
+%% API.
+
+-spec start_link() -> {ok, pid()}.
+start_link() ->
+	supervisor:start_link({local, ?MODULE}, ?MODULE, []).
+
+%% supervisor.
+
+init([]) ->
+	Procs = [],
+	{ok, {{one_for_one, 10, 10}, Procs}}.

+ 31 - 0
examples/compress_response/src/toppage_handler.erl

@@ -0,0 +1,31 @@
+%% Feel free to use, reuse and abuse the code in this file.
+
+%% @doc Compress response handler.
+-module(toppage_handler).
+
+-export([init/3]).
+-export([handle/2]).
+-export([terminate/2]).
+
+init(_Transport, Req, []) ->
+	{ok, Req, undefined}.
+
+handle(Req, State) ->
+	BigBody =
+<<"A cowboy is an animal herder who tends cattle on ranches in North America,
+traditionally on horseback, and often performs a multitude of other ranch-
+related tasks. The historic American cowboy of the late 19th century arose
+from the vaquero traditions of northern Mexico and became a figure of special
+significance and legend. A subtype, called a wrangler, specifically tends the
+horses used to work cattle. In addition to ranch work, some cowboys work for
+or participate in rodeos. Cowgirls, first defined as such in the late 19th
+century, had a less-well documented historical role, but in the modern world
+have established the ability to work at virtually identical tasks and obtained
+considerable respect for their achievements. There are also cattle handlers
+in many other parts of the world, particularly South America and Australia,
+who perform work similar to the cowboy in their respective nations.\n">>,
+	{ok, Req2} = cowboy_req:reply(200, [], BigBody, Req),
+	{ok, Req2, State}.
+
+terminate(_Req, _State) ->
+	ok.

+ 3 - 0
examples/compress_response/start.sh

@@ -0,0 +1,3 @@
+#!/bin/sh
+erl -pa ebin deps/*/ebin -s compress_response \
+	-eval "io:format(\"Point your browser at http://localhost:8080~n\")."

+ 9 - 5
src/cowboy_protocol.erl

@@ -17,6 +17,8 @@
 %%
 %%
 %% The available options are:
 %% The available options are:
 %% <dl>
 %% <dl>
+%%  <dt>compress</dt><dd>Whether to automatically compress the response
+%%   body when the conditions are met. Disabled by default.</dd>
 %%  <dt>env</dt><dd>The environment passed and optionally modified
 %%  <dt>env</dt><dd>The environment passed and optionally modified
 %%   by middlewares.</dd>
 %%   by middlewares.</dd>
 %%  <dt>max_empty_lines</dt><dd>Max number of empty lines before a request.
 %%  <dt>max_empty_lines</dt><dd>Max number of empty lines before a request.
@@ -64,6 +66,7 @@
 	socket :: inet:socket(),
 	socket :: inet:socket(),
 	transport :: module(),
 	transport :: module(),
 	middlewares :: [module()],
 	middlewares :: [module()],
+	compress :: boolean(),
 	env :: cowboy_middleware:env(),
 	env :: cowboy_middleware:env(),
 	onrequest :: undefined | onrequest_fun(),
 	onrequest :: undefined | onrequest_fun(),
 	onresponse = undefined :: undefined | onresponse_fun(),
 	onresponse = undefined :: undefined | onresponse_fun(),
@@ -99,6 +102,7 @@ get_value(Key, Opts, Default) ->
 %% @private
 %% @private
 -spec init(pid(), inet:socket(), module(), any()) -> ok.
 -spec init(pid(), inet:socket(), module(), any()) -> ok.
 init(ListenerPid, Socket, Transport, Opts) ->
 init(ListenerPid, Socket, Transport, Opts) ->
+	Compress = get_value(compress, Opts, false),
 	MaxEmptyLines = get_value(max_empty_lines, Opts, 5),
 	MaxEmptyLines = get_value(max_empty_lines, Opts, 5),
 	MaxHeaderNameLength = get_value(max_header_name_length, Opts, 64),
 	MaxHeaderNameLength = get_value(max_header_name_length, Opts, 64),
 	MaxHeaderValueLength = get_value(max_header_value_length, Opts, 4096),
 	MaxHeaderValueLength = get_value(max_header_value_length, Opts, 4096),
@@ -112,7 +116,7 @@ init(ListenerPid, Socket, Transport, Opts) ->
 	Timeout = get_value(timeout, Opts, 5000),
 	Timeout = get_value(timeout, Opts, 5000),
 	ok = ranch:accept_ack(ListenerPid),
 	ok = ranch:accept_ack(ListenerPid),
 	wait_request(<<>>, #state{socket=Socket, transport=Transport,
 	wait_request(<<>>, #state{socket=Socket, transport=Transport,
-		middlewares=Middlewares, env=Env,
+		middlewares=Middlewares, compress=Compress, env=Env,
 		max_empty_lines=MaxEmptyLines, max_keepalive=MaxKeepalive,
 		max_empty_lines=MaxEmptyLines, max_keepalive=MaxKeepalive,
 		max_request_line_length=MaxRequestLineLength,
 		max_request_line_length=MaxRequestLineLength,
 		max_header_name_length=MaxHeaderNameLength,
 		max_header_name_length=MaxHeaderNameLength,
@@ -457,11 +461,11 @@ parse_host(<< C, Rest/bits >>, Acc) ->
 
 
 request(Buffer, State=#state{socket=Socket, transport=Transport,
 request(Buffer, State=#state{socket=Socket, transport=Transport,
 		req_keepalive=ReqKeepalive, max_keepalive=MaxKeepalive,
 		req_keepalive=ReqKeepalive, max_keepalive=MaxKeepalive,
-		onresponse=OnResponse},
+		compress=Compress, onresponse=OnResponse},
 		Method, Path, Query, Fragment, Version, Headers, Host, Port) ->
 		Method, Path, Query, Fragment, Version, Headers, Host, Port) ->
 	Req = cowboy_req:new(Socket, Transport, Method, Path, Query, Fragment,
 	Req = cowboy_req:new(Socket, Transport, Method, Path, Query, Fragment,
 		Version, Headers, Host, Port, Buffer, ReqKeepalive < MaxKeepalive,
 		Version, Headers, Host, Port, Buffer, ReqKeepalive < MaxKeepalive,
-		OnResponse),
+		Compress, OnResponse),
 	onrequest(Req, State).
 	onrequest(Req, State).
 
 
 %% Call the global onrequest callback. The callback can send a reply,
 %% Call the global onrequest callback. The callback can send a reply,
@@ -546,13 +550,13 @@ error_terminate(Code, Req, State) ->
 %% Only send an error reply if there is no resp_sent message.
 %% Only send an error reply if there is no resp_sent message.
 -spec error_terminate(cowboy_http:status(), #state{}) -> ok.
 -spec error_terminate(cowboy_http:status(), #state{}) -> ok.
 error_terminate(Code, State=#state{socket=Socket, transport=Transport,
 error_terminate(Code, State=#state{socket=Socket, transport=Transport,
-		onresponse=OnResponse}) ->
+		compress=Compress, onresponse=OnResponse}) ->
 	receive
 	receive
 		{cowboy_req, resp_sent} -> ok
 		{cowboy_req, resp_sent} -> ok
 	after 0 ->
 	after 0 ->
 		_ = cowboy_req:reply(Code, cowboy_req:new(Socket, Transport,
 		_ = cowboy_req:reply(Code, cowboy_req:new(Socket, Transport,
 			<<"GET">>, <<>>, <<>>, <<>>, {1, 1}, [], <<>>, undefined,
 			<<"GET">>, <<>>, <<>>, <<>>, {1, 1}, [], <<>>, undefined,
-			<<>>, false, OnResponse)),
+			<<>>, false, Compress, OnResponse)),
 		ok
 		ok
 	end,
 	end,
 	terminate(State).
 	terminate(State).

+ 56 - 12
src/cowboy_req.erl

@@ -42,7 +42,7 @@
 -module(cowboy_req).
 -module(cowboy_req).
 
 
 %% Request API.
 %% Request API.
--export([new/13]).
+-export([new/14]).
 -export([method/1]).
 -export([method/1]).
 -export([version/1]).
 -export([version/1]).
 -export([peer/1]).
 -export([peer/1]).
@@ -156,6 +156,7 @@
 	buffer = <<>> :: binary(),
 	buffer = <<>> :: binary(),
 
 
 	%% Response.
 	%% Response.
+	resp_compress = false :: boolean(),
 	resp_state = waiting :: locked | waiting | chunks | done,
 	resp_state = waiting :: locked | waiting | chunks | done,
 	resp_headers = [] :: cowboy_http:headers(),
 	resp_headers = [] :: cowboy_http:headers(),
 	resp_body = <<>> :: iodata() | resp_body_fun()
 	resp_body = <<>> :: iodata() | resp_body_fun()
@@ -179,16 +180,16 @@
 %% in an optimized way and add the parsed value to p_headers' cache.
 %% in an optimized way and add the parsed value to p_headers' cache.
 -spec new(inet:socket(), module(), binary(), binary(), binary(), binary(),
 -spec new(inet:socket(), module(), binary(), binary(), binary(), binary(),
 	cowboy_http:version(), cowboy_http:headers(), binary(),
 	cowboy_http:version(), cowboy_http:headers(), binary(),
-	inet:port_number() | undefined, binary(), boolean(),
+	inet:port_number() | undefined, binary(), boolean(), boolean(),
 	undefined | cowboy_protocol:onresponse_fun())
 	undefined | cowboy_protocol:onresponse_fun())
 	-> req().
 	-> req().
 new(Socket, Transport, Method, Path, Query, Fragment,
 new(Socket, Transport, Method, Path, Query, Fragment,
 		Version, Headers, Host, Port, Buffer, CanKeepalive,
 		Version, Headers, Host, Port, Buffer, CanKeepalive,
-		OnResponse) ->
+		Compress, OnResponse) ->
 	Req = #http_req{socket=Socket, transport=Transport, pid=self(),
 	Req = #http_req{socket=Socket, transport=Transport, pid=self(),
 		method=Method, path=Path, qs=Query, fragment=Fragment, version=Version,
 		method=Method, path=Path, qs=Query, fragment=Fragment, version=Version,
 		headers=Headers, host=Host, port=Port, buffer=Buffer,
 		headers=Headers, host=Host, port=Port, buffer=Buffer,
-		onresponse=OnResponse},
+		resp_compress=Compress, onresponse=OnResponse},
 	case CanKeepalive and (Version =:= {1, 1}) of
 	case CanKeepalive and (Version =:= {1, 1}) of
 		false ->
 		false ->
 			Req#http_req{connection=close};
 			Req#http_req{connection=close};
@@ -892,7 +893,8 @@ reply(Status, Headers, Req=#http_req{resp_body=Body}) ->
 reply(Status, Headers, Body, Req=#http_req{
 reply(Status, Headers, Body, Req=#http_req{
 		socket=Socket, transport=Transport,
 		socket=Socket, transport=Transport,
 		version=Version, connection=Connection,
 		version=Version, connection=Connection,
-		method=Method, resp_state=waiting, resp_headers=RespHeaders}) ->
+		method=Method, resp_compress=Compress,
+		resp_state=waiting, resp_headers=RespHeaders}) ->
 	RespConn = response_connection(Headers, Connection),
 	RespConn = response_connection(Headers, Connection),
 	HTTP11Headers = case Version of
 	HTTP11Headers = case Version of
 		{1, 1} -> [{<<"connection">>, atom_to_connection(Connection)}];
 		{1, 1} -> [{<<"connection">>, atom_to_connection(Connection)}];
@@ -922,18 +924,60 @@ reply(Status, Headers, Body, Req=#http_req{
 					BodyFun(Socket, Transport);
 					BodyFun(Socket, Transport);
 				true -> ok
 				true -> ok
 			end;
 			end;
+		_ when Compress ->
+			Req2 = reply_may_compress(Status, Headers, Body, Req,
+				RespHeaders, HTTP11Headers, Method);
 		_ ->
 		_ ->
-			{_, Req2} = response(Status, Headers, RespHeaders, [
-					{<<"content-length">>, integer_to_list(iolist_size(Body))},
-					{<<"date">>, cowboy_clock:rfc1123()},
-					{<<"server">>, <<"Cowboy">>}
-				|HTTP11Headers],
-				case Method of <<"HEAD">> -> <<>>; _ -> Body end,
-				Req)
+			Req2 = reply_no_compress(Status, Headers, Body, Req,
+				RespHeaders, HTTP11Headers, Method, iolist_size(Body))
 	end,
 	end,
 	{ok, Req2#http_req{connection=RespConn, resp_state=done,
 	{ok, Req2#http_req{connection=RespConn, resp_state=done,
 		resp_headers=[], resp_body= <<>>}}.
 		resp_headers=[], resp_body= <<>>}}.
 
 
+reply_may_compress(Status, Headers, Body, Req,
+		RespHeaders, HTTP11Headers, Method) ->
+	BodySize = iolist_size(Body),
+	{ok, Encodings, Req2}
+		= cowboy_req:parse_header(<<"accept-encoding">>, Req),
+	CanGzip = (BodySize > 300)
+		andalso (false =:= lists:keyfind(<<"content-encoding">>,
+			1, Headers))
+		andalso (false =:= lists:keyfind(<<"content-encoding">>,
+			1, RespHeaders))
+		andalso (false =:= lists:keyfind(<<"transfer-encoding">>,
+			1, Headers))
+		andalso (false =:= lists:keyfind(<<"transfer-encoding">>,
+			1, RespHeaders))
+		andalso (Encodings =/= undefined)
+		andalso (false =/= lists:keyfind(<<"gzip">>, 1, Encodings)),
+	case CanGzip of
+		true ->
+			GzBody = zlib:gzip(Body),
+			{_, Req3} = response(Status, Headers, RespHeaders, [
+					{<<"content-length">>, integer_to_list(byte_size(GzBody))},
+					{<<"content-encoding">>, <<"gzip">>},
+					{<<"date">>, cowboy_clock:rfc1123()},
+					{<<"server">>, <<"Cowboy">>}
+				|HTTP11Headers],
+				case Method of <<"HEAD">> -> <<>>; _ -> GzBody end,
+				Req2),
+			Req3;
+		false ->
+			reply_no_compress(Status, Headers, Body, Req,
+				RespHeaders, HTTP11Headers, Method, BodySize)
+	end.
+
+reply_no_compress(Status, Headers, Body, Req,
+		RespHeaders, HTTP11Headers, Method, BodySize) ->
+	{_, Req2} = response(Status, Headers, RespHeaders, [
+			{<<"content-length">>, integer_to_list(BodySize)},
+			{<<"date">>, cowboy_clock:rfc1123()},
+			{<<"server">>, <<"Cowboy">>}
+		|HTTP11Headers],
+		case Method of <<"HEAD">> -> <<>>; _ -> Body end,
+		Req),
+	Req2.
+
 %% @equiv chunked_reply(Status, [], Req)
 %% @equiv chunked_reply(Status, [], Req)
 -spec chunked_reply(cowboy_http:status(), Req) -> {ok, Req} when Req::req().
 -spec chunked_reply(cowboy_http:status(), Req) -> {ok, Req} when Req::req().
 chunked_reply(Status, Req) ->
 chunked_reply(Status, Req) ->

+ 47 - 5
test/http_SUITE.erl

@@ -78,7 +78,14 @@
 %% ct.
 %% ct.
 
 
 all() ->
 all() ->
-	[{group, http}, {group, https}, {group, onrequest}, {group, onresponse}].
+	[
+		{group, http},
+		{group, https},
+		{group, http_compress},
+		{group, https_compress},
+		{group, onrequest},
+		{group, onresponse}
+	].
 
 
 groups() ->
 groups() ->
 	Tests = [
 	Tests = [
@@ -130,6 +137,8 @@ groups() ->
 	[
 	[
 		{http, [], Tests},
 		{http, [], Tests},
 		{https, [], Tests},
 		{https, [], Tests},
+		{http_compress, [], Tests},
+		{https_compress, [], Tests},
 		{onrequest, [], [
 		{onrequest, [], [
 			onrequest,
 			onrequest,
 			onrequest_reply
 			onrequest_reply
@@ -185,9 +194,42 @@ init_per_group(https, Config) ->
 	{ok, Client} = cowboy_client:init(Opts),
 	{ok, Client} = cowboy_client:init(Opts),
 	[{scheme, <<"https">>}, {port, Port}, {opts, Opts},
 	[{scheme, <<"https">>}, {port, Port}, {opts, Opts},
 		{transport, Transport}, {client, Client}|Config1];
 		{transport, Transport}, {client, Client}|Config1];
-init_per_group(onrequest, Config) ->
+init_per_group(http_compress, Config) ->
 	Port = 33082,
 	Port = 33082,
 	Transport = ranch_tcp,
 	Transport = ranch_tcp,
+	Config1 = init_static_dir(Config),
+	{ok, _} = cowboy:start_http(http_compress, 100, [{port, Port}], [
+		{compress, true},
+		{env, [{dispatch, init_dispatch(Config1)}]},
+		{max_keepalive, 50},
+		{timeout, 500}
+	]),
+	{ok, Client} = cowboy_client:init([]),
+	[{scheme, <<"http">>}, {port, Port}, {opts, []},
+		{transport, Transport}, {client, Client}|Config1];
+init_per_group(https_compress, Config) ->
+	Port = 33083,
+	Transport = ranch_ssl,
+	Opts = [
+		{certfile, ?config(data_dir, Config) ++ "cert.pem"},
+		{keyfile, ?config(data_dir, Config) ++ "key.pem"},
+		{password, "cowboy"}
+	],
+	Config1 = init_static_dir(Config),
+	application:start(public_key),
+	application:start(ssl),
+	{ok, _} = cowboy:start_https(https_compress, 100, Opts ++ [{port, Port}], [
+		{compress, true},
+		{env, [{dispatch, init_dispatch(Config1)}]},
+		{max_keepalive, 50},
+		{timeout, 500}
+	]),
+	{ok, Client} = cowboy_client:init(Opts),
+	[{scheme, <<"https">>}, {port, Port}, {opts, Opts},
+		{transport, Transport}, {client, Client}|Config1];
+init_per_group(onrequest, Config) ->
+	Port = 33084,
+	Transport = ranch_tcp,
 	{ok, _} = cowboy:start_http(onrequest, 100, [{port, Port}], [
 	{ok, _} = cowboy:start_http(onrequest, 100, [{port, Port}], [
 		{env, [{dispatch, init_dispatch(Config)}]},
 		{env, [{dispatch, init_dispatch(Config)}]},
 		{max_keepalive, 50},
 		{max_keepalive, 50},
@@ -198,7 +240,7 @@ init_per_group(onrequest, Config) ->
 	[{scheme, <<"http">>}, {port, Port}, {opts, []},
 	[{scheme, <<"http">>}, {port, Port}, {opts, []},
 		{transport, Transport}, {client, Client}|Config];
 		{transport, Transport}, {client, Client}|Config];
 init_per_group(onresponse, Config) ->
 init_per_group(onresponse, Config) ->
-	Port = 33083,
+	Port = 33085,
 	Transport = ranch_tcp,
 	Transport = ranch_tcp,
 	{ok, _} = cowboy:start_http(onresponse, 100, [{port, Port}], [
 	{ok, _} = cowboy:start_http(onresponse, 100, [{port, Port}], [
 		{env, [{dispatch, init_dispatch(Config)}]},
 		{env, [{dispatch, init_dispatch(Config)}]},
@@ -210,13 +252,13 @@ init_per_group(onresponse, Config) ->
 	[{scheme, <<"http">>}, {port, Port}, {opts, []},
 	[{scheme, <<"http">>}, {port, Port}, {opts, []},
 		{transport, Transport}, {client, Client}|Config].
 		{transport, Transport}, {client, Client}|Config].
 
 
-end_per_group(https, Config) ->
+end_per_group(Group, Config) when Group =:= https; Group =:= https_compress ->
 	cowboy:stop_listener(https),
 	cowboy:stop_listener(https),
 	application:stop(ssl),
 	application:stop(ssl),
 	application:stop(public_key),
 	application:stop(public_key),
 	end_static_dir(Config),
 	end_static_dir(Config),
 	ok;
 	ok;
-end_per_group(http, Config) ->
+end_per_group(Group, Config) when Group =:= http; Group =:= http_compress ->
 	cowboy:stop_listener(http),
 	cowboy:stop_listener(http),
 	end_static_dir(Config);
 	end_static_dir(Config);
 end_per_group(Name, _) ->
 end_per_group(Name, _) ->