diff --git a/include/types/compression.h b/include/types/compression.h index e4b1f273d..ae1e87df8 100644 --- a/include/types/compression.h +++ b/include/types/compression.h @@ -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); diff --git a/src/compression.c b/src/compression.c index eadeb9d5f..8ddee57bd 100644 --- a/src/compression.c +++ b/src/compression.c @@ -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; } diff --git a/src/haproxy.c b/src/haproxy.c index 07d67bebf..8063f37b9 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -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"); diff --git a/src/proto_http.c b/src/proto_http.c index 56e4d3f66..24de4abf3 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -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); }