mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-04-11 03:31:36 +00:00
MEDIUM: compression: Make it so we can compress requests as well.
Add code so that compression can be used for requests as well. New compression keywords are introduced : "direction" that specifies what we want to compress. Valid values are "request", "response", or "both". "type-req" and "type-res" define content-type to be compressed for requests and responses, respectively. "type" is kept as an alias for "type-res" for backward compatibilty. "algo-req" specifies the compression algorithm to be used for requests. Only one algorithm can be provided. "algo-res" provides the list of algorithm that can be used to compress responses. "algo" is kept as an alias for "algo-res" for backward compatibility.
This commit is contained in:
parent
dea25f51b6
commit
ead43fe4f2
@ -5014,13 +5014,25 @@ clitcpka-intvl <timeout>
|
||||
|
||||
|
||||
compression algo <algorithm> ...
|
||||
compression algo-req <algorithm>
|
||||
compression algo-res <algorithm>
|
||||
compression type <mime type> ...
|
||||
Enable HTTP compression.
|
||||
May be used in sections : defaults | frontend | listen | backend
|
||||
yes | yes | yes | yes
|
||||
Arguments :
|
||||
algo is followed by the list of supported compression algorithms.
|
||||
type is followed by the list of MIME types that will be compressed.
|
||||
algo is followed by the list of supported compression algorithms for
|
||||
responses (legacy keyword)
|
||||
algo-req is followed by compression algorithm for request (only one is
|
||||
provided).
|
||||
algo-res is followed by the list of supported compression algorithms for
|
||||
responses.
|
||||
type is followed by the list of MIME types that will be compressed for
|
||||
responses (legacy keyword).
|
||||
type-req is followed by the list of MIME types that will be compressed for
|
||||
requests.
|
||||
type-res is followed by the list of MIME types that will be compressed for
|
||||
responses.
|
||||
|
||||
The currently supported algorithms are :
|
||||
identity this is mostly for debugging, and it was useful for developing
|
||||
@ -5077,7 +5089,7 @@ compression type <mime type> ...
|
||||
compression algo gzip
|
||||
compression type text/html text/plain
|
||||
|
||||
See also : "compression offload"
|
||||
See also : "compression offload", "compression direction"
|
||||
|
||||
compression offload
|
||||
Makes HAProxy work as a compression offloader only.
|
||||
@ -5099,7 +5111,15 @@ compression offload
|
||||
If this setting is used in a defaults section, a warning is emitted and the
|
||||
option is ignored.
|
||||
|
||||
See also : "compression type", "compression algo"
|
||||
See also : "compression type", "compression algo", "compression direction"
|
||||
|
||||
compression direction <direction>
|
||||
Makes haproxy able to compress both requests and responses.
|
||||
Valid values are "request", to compress only requests, "response", to
|
||||
compress only responses, or "both", when you want to compress both.
|
||||
The default value is "response".
|
||||
|
||||
See also : "compression type", "compression algo", "compression offload"
|
||||
|
||||
cookie <name> [ rewrite | insert | prefix ] [ indirect ] [ nocache ]
|
||||
[ postonly ] [ preserve ] [ httponly ] [ secure ]
|
||||
|
@ -42,6 +42,9 @@
|
||||
/* Compression flags */
|
||||
|
||||
#define COMP_FL_OFFLOAD 0x00000001 /* Compression offload */
|
||||
#define COMP_FL_DIR_REQ 0x00000002 /* Compress requests */
|
||||
#define COMP_FL_DIR_RES 0x00000004 /* Compress responses */
|
||||
|
||||
struct comp {
|
||||
struct comp_algo *algos_res; /* Algos available for response */
|
||||
struct comp_algo *algo_req; /* Algo to use for request */
|
||||
|
@ -130,17 +130,109 @@ comp_strm_deinit(struct stream *s, struct filter *filter)
|
||||
filter->ctx = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
comp_prepare_compress_request(struct comp_state *st, struct stream *s, struct http_msg *msg)
|
||||
{
|
||||
struct htx *htx = htxbuf(&msg->chn->buf);
|
||||
struct http_txn *txn = s->txn;
|
||||
struct http_hdr_ctx ctx;
|
||||
struct comp_type *comp_type;
|
||||
|
||||
ctx.blk = NULL;
|
||||
/* Already compressed, don't bother */
|
||||
if (http_find_header(htx, ist("Content-Encoding"), &ctx, 1))
|
||||
return;
|
||||
/* HTTP < 1.1 should not be compressed */
|
||||
if (!(msg->flags & HTTP_MSGF_VER_11) || !(txn->req.flags & HTTP_MSGF_VER_11))
|
||||
return;
|
||||
comp_type = NULL;
|
||||
|
||||
/*
|
||||
* We don't want to compress content-types not listed in the "compression type" directive if any. If no content-type was found but configuration
|
||||
* requires one, we don't compress either. Backend has the priority.
|
||||
*/
|
||||
ctx.blk = NULL;
|
||||
if (http_find_header(htx, ist("Content-Type"), &ctx, 1)) {
|
||||
if ((s->be->comp && (comp_type = s->be->comp->types_req)) ||
|
||||
(strm_fe(s)->comp && (comp_type = strm_fe(s)->comp->types_req))) {
|
||||
for (; comp_type; comp_type = comp_type->next) {
|
||||
if (ctx.value.len >= comp_type->name_len &&
|
||||
strncasecmp(ctx.value.ptr, comp_type->name, comp_type->name_len) == 0)
|
||||
/* this Content-Type should be compressed */
|
||||
break;
|
||||
}
|
||||
/* this Content-Type should not be compressed */
|
||||
if (comp_type == NULL)
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else { /* no content-type header */
|
||||
if ((s->be->comp && s->be->comp->types_req) ||
|
||||
(strm_fe(s)->comp && strm_fe(s)->comp->types_req))
|
||||
goto fail; /* a content-type was required */
|
||||
}
|
||||
|
||||
/* limit compression rate */
|
||||
if (global.comp_rate_lim > 0)
|
||||
if (read_freq_ctr(&global.comp_bps_in) > global.comp_rate_lim)
|
||||
goto fail;
|
||||
|
||||
/* limit cpu usage */
|
||||
if (th_ctx->idle_pct < compress_min_idle)
|
||||
goto fail;
|
||||
|
||||
if (txn->meth == HTTP_METH_HEAD)
|
||||
return;
|
||||
if (s->be->comp->algo_req != NULL)
|
||||
st->comp_algo[COMP_DIR_REQ] = s->be->comp->algo_req;
|
||||
else if (strm_fe(s)->comp->algo_req != NULL)
|
||||
st->comp_algo[COMP_DIR_REQ] = strm_fe(s)->comp->algo_req;
|
||||
|
||||
|
||||
/* limit compression rate */
|
||||
if (global.comp_rate_lim > 0)
|
||||
if (read_freq_ctr(&global.comp_bps_in) > global.comp_rate_lim)
|
||||
goto fail;
|
||||
|
||||
/* limit cpu usage */
|
||||
if (th_ctx->idle_pct < compress_min_idle)
|
||||
goto fail;
|
||||
|
||||
/* initialize compression */
|
||||
if (st->comp_algo[COMP_DIR_REQ]->init(&st->comp_ctx[COMP_DIR_REQ], global.tune.comp_maxlevel) < 0)
|
||||
goto fail;
|
||||
|
||||
return;
|
||||
fail:
|
||||
st->comp_algo[COMP_DIR_REQ] = NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
comp_http_headers(struct stream *s, struct filter *filter, struct http_msg *msg)
|
||||
{
|
||||
struct comp_state *st = filter->ctx;
|
||||
int comp_flags = 0;
|
||||
|
||||
if (!strm_fe(s)->comp && !s->be->comp)
|
||||
goto end;
|
||||
if (strm_fe(s)->comp)
|
||||
comp_flags |= strm_fe(s)->comp->flags;
|
||||
if (s->be->comp)
|
||||
comp_flags |= s->be->comp->flags;
|
||||
|
||||
if (!(msg->chn->flags & CF_ISRESP))
|
||||
select_compression_request_header(st, s, msg);
|
||||
else {
|
||||
if (!(msg->chn->flags & CF_ISRESP)) {
|
||||
if (comp_flags & COMP_FL_DIR_REQ) {
|
||||
comp_prepare_compress_request(st, s, msg);
|
||||
if (st->comp_algo[COMP_DIR_REQ]) {
|
||||
if (!set_compression_header(st, s, msg))
|
||||
goto end;
|
||||
register_data_filter(s, msg->chn, filter);
|
||||
st->flags |= COMP_STATE_PROCESSING;
|
||||
}
|
||||
}
|
||||
if (comp_flags & COMP_FL_DIR_RES)
|
||||
select_compression_request_header(st, s, msg);
|
||||
} else if (comp_flags & COMP_FL_DIR_RES) {
|
||||
/* Response headers have already been checked in
|
||||
* comp_http_post_analyze callback. */
|
||||
if (st->comp_algo[COMP_DIR_RES]) {
|
||||
@ -669,6 +761,8 @@ parse_compression_options(char **args, int section, struct proxy *proxy,
|
||||
|
||||
if (proxy->comp == NULL) {
|
||||
comp = calloc(1, sizeof(*comp));
|
||||
/* Always default to compress responses */
|
||||
comp->flags = COMP_FL_DIR_RES;
|
||||
proxy->comp = comp;
|
||||
}
|
||||
else
|
||||
@ -709,6 +803,30 @@ parse_compression_options(char **args, int section, struct proxy *proxy,
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (strcmp(args[1], "algo-req") == 0) {
|
||||
struct comp_ctx *ctx;
|
||||
int retval = comp_append_algo(&comp->algo_req, args[2]);
|
||||
|
||||
if (retval) {
|
||||
if (retval < 0)
|
||||
memprintf(err, "'%s' : '%s' is not a supported algorithm.",
|
||||
args[0], args[2]);
|
||||
else
|
||||
memprintf(err, "'%s' : out of memory while parsing algo '%s'.",
|
||||
args[0], args[2]);
|
||||
ret = -1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (proxy->comp->algo_req->init(&ctx, 9) == 0)
|
||||
proxy->comp->algo_req->end(&ctx);
|
||||
else {
|
||||
memprintf(err, "'%s' : Can't init '%s' algorithm.",
|
||||
args[0], args[2]);
|
||||
ret = -1;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
else if (strcmp(args[1], "offload") == 0) {
|
||||
if (proxy->cap & PR_CAP_DEF) {
|
||||
memprintf(err, "'%s' : '%s' ignored in 'defaults' section.",
|
||||
@ -735,8 +853,46 @@ parse_compression_options(char **args, int section, struct proxy *proxy,
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (strcmp(args[1], "type-req") == 0) {
|
||||
int cur_arg = 2;
|
||||
|
||||
if (!*args[cur_arg]) {
|
||||
memprintf(err, "'%s' expects <type>.", args[0]);
|
||||
ret = -1;
|
||||
goto end;
|
||||
}
|
||||
while (*(args[cur_arg])) {
|
||||
if (comp_append_type(&comp->types_req, args[cur_arg])) {
|
||||
memprintf(err, "'%s': out of memory.", args[0]);
|
||||
ret = -1;
|
||||
goto end;
|
||||
}
|
||||
cur_arg++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (strcmp(args[1], "direction") == 0) {
|
||||
if (!args[2]) {
|
||||
memprintf(err, "'%s' expects 'request', 'response', or 'both'.", args[0]);
|
||||
ret = -1;
|
||||
goto end;
|
||||
}
|
||||
if (strcmp(args[2], "request") == 0) {
|
||||
comp->flags &= ~COMP_FL_DIR_RES;
|
||||
comp->flags |= COMP_FL_DIR_REQ;
|
||||
} else if (strcmp(args[2], "response") == 0) {
|
||||
comp->flags &= COMP_FL_DIR_REQ;
|
||||
comp->flags |= COMP_FL_DIR_RES;
|
||||
} else if (strcmp(args[2], "both") == 0)
|
||||
comp->flags |= COMP_FL_DIR_REQ | COMP_FL_DIR_RES;
|
||||
else {
|
||||
memprintf(err, "'%s' expects 'request', 'response', or 'both'.", args[0]);
|
||||
ret = -1;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
else {
|
||||
memprintf(err, "'%s' expects 'algo', 'type' or 'offload'",
|
||||
memprintf(err, "'%s' expects 'algo', 'type' 'direction' or 'offload'",
|
||||
args[0]);
|
||||
ret = -1;
|
||||
goto end;
|
||||
|
Loading…
Reference in New Issue
Block a user