From: Willy Tarreau Date: Fri, 26 Oct 2012 22:34:28 +0000 (+0200) Subject: MINOR: compression: add an offload option to remove the Accept-Encoding header X-Git-Tag: v1.5-dev13~93 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=70737d142fd13ffc6a25f8c4199e4b10f9886461;p=thirdparty%2Fhaproxy.git MINOR: compression: add an offload option to remove the Accept-Encoding header This is used when it is desired that backend servers don't compress (eg: because of buggy implementations). --- diff --git a/doc/configuration.txt b/doc/configuration.txt index 2c427f3aa7..acf3099de8 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -1780,12 +1780,24 @@ clitimeout (deprecated) compression algo [ gzip ] ... compression type ... +compression offload 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. + offload makes haproxy work as a compression offloader only (see notes). + + The "offload" setting makes haproxy remove the Accept-Encoding header to + prevent backend servers from compressing responses. It is strongly + recommended not to do this because this means that all the compression work + will be done on the single point where haproxy is located. However in some + deployment scenarios, haproxy may be installed in front of a buggy gateway + and need to prevent it from emitting invalid payloads. In this case, simply + removing the header in the configuration does not work because it applies + before the header is parsed, so that prevents haproxy from compressing. The + "offload" setting should then be used for such scenarios. Examples : compression algo gzip diff --git a/include/types/compression.h b/include/types/compression.h index 96dd107723..10ac4b1159 100644 --- a/include/types/compression.h +++ b/include/types/compression.h @@ -28,6 +28,7 @@ struct comp { struct comp_algo *algos; struct comp_type *types; + unsigned int offload; }; struct comp_algo { diff --git a/src/cfgparse.c b/src/cfgparse.c index 971371d18a..ef3be08fd6 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -5273,6 +5273,9 @@ stats_error_parsing: continue; } } + else if (!strcmp(args[1], "offload")) { + comp->offload = 1; + } else if (!strcmp(args[1], "type")) { int cur_arg; cur_arg = 2; @@ -5289,7 +5292,7 @@ stats_error_parsing: } } else { - Alert("parsing [%s:%d] : '%s' expects algo or type\n", + Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n", file, linenum, args[0]); err_code |= ERR_ALERT | ERR_FATAL; goto out; diff --git a/src/proto_http.c b/src/proto_http.c index 31d49f9997..6167f1f175 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -1974,6 +1974,7 @@ static inline int http_skip_chunk_crlf(struct http_msg *msg) int select_compression_request_header(struct session *s, struct buffer *req) { struct http_txn *txn = &s->txn; + struct http_msg *msg = &txn->req; struct hdr_ctx ctx; struct comp_algo *comp_algo = NULL; struct comp_algo *comp_algo_back = NULL; @@ -2006,6 +2007,17 @@ int select_compression_request_header(struct session *s, struct buffer *req) for (comp_algo = comp_algo_back; comp_algo; comp_algo = comp_algo->next) { if (word_match(ctx.line + ctx.val, ctx.vlen, comp_algo->name, comp_algo->name_len)) { s->comp_algo = comp_algo; + + /* remove all occurrences of the header when "compression offload" is set */ + + if ((s->be->comp && s->be->comp->offload) || + (s->fe->comp && s->fe->comp->offload)) { + http_remove_header2(msg, &txn->hdr_idx, &ctx); + ctx.idx = 0; + while (http_find_header2("Accept-Encoding", 15, req->p, &txn->hdr_idx, &ctx)) { + http_remove_header2(msg, &txn->hdr_idx, &ctx); + } + } return 1; } }