]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: compression: add a distinction between UA- and config- algorithms
authorWilly Tarreau <w@1wt.eu>
Sat, 28 Mar 2015 15:40:46 +0000 (16:40 +0100)
committerWilly Tarreau <w@1wt.eu>
Sat, 28 Mar 2015 15:46:38 +0000 (16:46 +0100)
Thanks to MSIE/IIS, the "deflate" name is ambigous. According to the RFC
it's a zlib-wrapped deflate stream, but IIS used to send only a raw deflate
stream, which is the only format MSIE understands for "deflate". The other
widely used browsers do support both formats. For this reason some people
prefer to emit a raw deflate stream on "deflate" to serve more users even
it that means violating the standards. Haproxy only follows the standard,
so they cannot do this.

This patch makes it possible to have one algorithm name in the configuration
and another one in the protocol. This will make it possible to have a new
configuration token to add a different algorithm so that users can decide if
they want a raw deflate or the standard one.

include/types/compression.h
src/compression.c
src/haproxy.c
src/proto_http.c

index e4b1f273d35e760c60f04b6928d722ba7fa88f1f..ae1e87df8e5d6263e8968f0b47665a43810ae26f 100644 (file)
@@ -47,9 +47,19 @@ struct comp_ctx {
        int cur_lvl;
 };
 
+/* Thanks to MSIE/IIS, the "deflate" name is ambigous, as according to the RFC
+ * it's a zlib-wrapped deflate stream, but MSIE only understands a raw deflate
+ * stream. For this reason some people prefer to emit a raw deflate stream on
+ * "deflate" and we'll need two algos for the same name, they are distinguished
+ * with the config name.
+ */
 struct comp_algo {
-       char *name;
-       int name_len;
+       char *cfg_name;  /* config name */
+       int cfg_name_len;
+
+       char *ua_name;  /* name for the user-agent */
+       int ua_name_len;
+
        int (*init)(struct comp_ctx **comp_ctx, int level);
        int (*add_data)(struct comp_ctx *comp_ctx, const char *in_data, int in_len, struct buffer *out);
        int (*flush)(struct comp_ctx *comp_ctx, struct buffer *out, int flag);
index eadeb9d5f9b63a07764f11c8f2aaddc7a38c4998..8ddee57bd92b8930facb9130c1e07dcfddda9f61 100644 (file)
@@ -73,12 +73,12 @@ static int deflate_end(struct comp_ctx **comp_ctx);
 
 const struct comp_algo comp_algos[] =
 {
-       { "identity", 8, identity_init, identity_add_data, identity_flush, identity_reset, identity_end },
+       { "identity",     8, "identity", 8, identity_init, identity_add_data, identity_flush, identity_reset, identity_end },
 #ifdef USE_ZLIB
-       { "deflate",  7, deflate_init,  deflate_add_data,  deflate_flush,  deflate_reset,  deflate_end },
-       { "gzip",     4, gzip_init,     deflate_add_data,  deflate_flush,  deflate_reset,  deflate_end },
+       { "deflate",      7, "deflate",  7, deflate_init,  deflate_add_data,  deflate_flush,  deflate_reset,  deflate_end },
+       { "gzip",         4, "gzip",     4, gzip_init,     deflate_add_data,  deflate_flush,  deflate_reset,  deflate_end },
 #endif /* USE_ZLIB */
-       { NULL,       0, NULL ,         NULL,              NULL,           NULL,           NULL }
+       { NULL,       0, NULL,          0, NULL ,         NULL,              NULL,           NULL,           NULL }
 };
 
 /*
@@ -104,8 +104,8 @@ int comp_append_algo(struct comp *comp, const char *algo)
        struct comp_algo *comp_algo;
        int i;
 
-       for (i = 0; comp_algos[i].name; i++) {
-               if (!strcmp(algo, comp_algos[i].name)) {
+       for (i = 0; comp_algos[i].cfg_name; i++) {
+               if (!strcmp(algo, comp_algos[i].cfg_name)) {
                        comp_algo = calloc(1, sizeof(struct comp_algo));
                        memmove(comp_algo, &comp_algos[i], sizeof(struct comp_algo));
                        comp_algo->next = comp->algos;
@@ -669,8 +669,8 @@ smp_fetch_res_comp_algo(struct proxy *px, struct session *l4, void *l7, unsigned
 
        smp->type = SMP_T_STR;
        smp->flags = SMP_F_CONST;
-       smp->data.str.str = l4->comp_algo->name;
-       smp->data.str.len = l4->comp_algo->name_len;
+       smp->data.str.str = l4->comp_algo->cfg_name;
+       smp->data.str.len = l4->comp_algo->cfg_name_len;
        return 1;
 }
 
index 07d67bebfa212b3b808e07979f54d37e5ca40f66..8063f37b96ac24023aa210d34286dbf4237c6bcf 100644 (file)
@@ -262,8 +262,8 @@ void display_build_opts()
        {
                int i;
 
-               for (i = 0; comp_algos[i].name; i++) {
-                       printf("%s %s", (i == 0 ? "" : ","), comp_algos[i].name);
+               for (i = 0; comp_algos[i].cfg_name; i++) {
+                       printf("%s %s(\"%s\")", (i == 0 ? "" : ","), comp_algos[i].cfg_name, comp_algos[i].ua_name);
                }
                if (i == 0) {
                        printf("none");
index 56e4d3f66c9e5f6c4502a1372d42f999ce2dee18..24de4abf32d9009e46ab998c9b0ff2c9ffaadf07 100644 (file)
@@ -2309,7 +2309,7 @@ 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 (*(ctx.line + ctx.val) == '*' ||
-                                   word_match(ctx.line + ctx.val, toklen, comp_algo->name, comp_algo->name_len)) {
+                                   word_match(ctx.line + ctx.val, toklen, comp_algo->ua_name, comp_algo->ua_name_len)) {
                                        s->comp_algo = comp_algo;
                                        best_q = q;
                                        break;
@@ -2333,7 +2333,7 @@ int select_compression_request_header(struct session *s, struct buffer *req)
        /* identity is implicit does not require headers */
        if ((s->be->comp && (comp_algo_back = s->be->comp->algos)) || (s->fe->comp && (comp_algo_back = s->fe->comp->algos))) {
                for (comp_algo = comp_algo_back; comp_algo; comp_algo = comp_algo->next) {
-                       if (comp_algo->name_len == 8 && memcmp(comp_algo->name, "identity", 8) == 0) {
+                       if (comp_algo->cfg_name_len == 8 && memcmp(comp_algo->cfg_name, "identity", 8) == 0) {
                                s->comp_algo = comp_algo;
                                return 1;
                        }
@@ -2445,11 +2445,11 @@ int select_compression_response_header(struct session *s, struct buffer *res)
         * Accept-Encoding header, and SHOULD NOT be used in the Content-Encoding
         * header.
         */
-       if (s->comp_algo->name_len != 8 || memcmp(s->comp_algo->name, "identity", 8) != 0) {
+       if (s->comp_algo->cfg_name_len != 8 || memcmp(s->comp_algo->cfg_name, "identity", 8) != 0) {
                trash.len = 18;
                memcpy(trash.str, "Content-Encoding: ", trash.len);
-               memcpy(trash.str + trash.len, s->comp_algo->name, s->comp_algo->name_len);
-               trash.len += s->comp_algo->name_len;
+               memcpy(trash.str + trash.len, s->comp_algo->ua_name, s->comp_algo->ua_name_len);
+               trash.len += s->comp_algo->ua_name_len;
                trash.str[trash.len] = '\0';
                http_header_add_tail2(&txn->rsp, &txn->hdr_idx, trash.str, trash.len);
        }