IE7 bug / force response to HTTP/1.0

Igor Sysoev is at rambler-co.ru
Mon Apr 21 22:26:19 MSD 2008


On Mon, Apr 21, 2008 at 07:59:30PM +0400, Igor Sysoev wrote:

> On Mon, Apr 21, 2008 at 03:44:41PM +0400, Andrew V. Statsenko wrote:
> 
> > Коллеги, очень похоже, что наступил за замечательные грабли с MS IE7, а
> > именно:
> > 
> > есть схема: 
> > 
> > [Browser]-->[Nginx frontend]-->[Apache backend]
> > 
> > Иногда, для отчетов apache должен отдавать "Content-Type:
> > application/vnd.ms-excel" и далее динамически формируемые CSV данные для
> > клиента. Если apache отдает Transfer-Encoding: chunked , то IE7
> > предлагает диалог этот файл открыть или сохранить, но при любом выборе
> > "загрузить" этот отчет не может, ругаясь на что-то в духе "узел сети не
> > может быть найден".
> > 
> > Firefix & Opera успешно работают, ответы (проверено через tcpdump &
> > ngrep) все браузеры получают одинаковые.
> > 
> > Проблема на backend решается через форсирование ответа в HTTP/1.0
> > примерно такой конструкцией в apache:
> > 
> > SetEnvIf Request_URI exporter nokeepalive downgrade-1.0
> > force-response-1.0
> > 
> > и этом случае при обращении IE7 напрямую на backend все работает
> > (т.е. ???убираем ???Transfer-Encoding: chunked), но при обращении на
> > frontend IE7 опять ломается (на сей раз по всей видимости из-за
> > отсутствия Content-Length).
> > 
> > Вопросы:
> > 
> > 1. Возможно ли сконфигурировать nginx, так, чтобы по некоторым localtion
> > он форсировал HTTP/1.0 ? То есть _теоретически_ примерно так:
> > 
> > location / 
> > {
> >      force_response_to_1_0;
> > 
> >      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
> >      proxy_set_header Host $http_host;
> >      proxy_pass http://some.backend.host;
> > 
> > }
> > 
> > 
> > 2. Если (1) невозможно/сложно , то есть ли возможность добавить
> > хидер ???Content-Length непосредственно на frontend'е - вычислить эту
> > длину самим nginx'ом и вставить хидер ?
> > 
> > 3. Любые другие варианты решения ?
> > 
> > 
> > P.S.
> > Разломать схему frontend-backend не могу. Слишком будет хлопотно.
> > Чтобы вычислять ??? ???Content-Length на backend, потребуется _сильно_
> > перепиливать генератор отчетов, что _очень_ не хочется делать.
> > 
> > P.S.S.
> > По поводу продукции компании MS испытываю массу разнообразнейших эмоций,
> > но если кто-нибудь знает, о том, что эту багу можно вылечить на стороне
> > браузера (патч, update ?), то был бы безмерно признателен за наводку.
> 
> Прилагаемый патч добавляет директиву
> 
>        chunked_encoding  off;

Предыдущий патч нужно откатить, новый накатить.


-- 
Игорь Сысоев
http://sysoev.ru
-------------- next part --------------
Index: src/http/ngx_http_core_module.c
===================================================================
--- src/http/ngx_http_core_module.c	(revision 1293)
+++ src/http/ngx_http_core_module.c	(working copy)
@@ -486,6 +486,13 @@
       offsetof(ngx_http_core_loc_conf_t, msie_refresh),
       NULL },
 
+    { ngx_string("chunked_encoding"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+      ngx_conf_set_flag_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_core_loc_conf_t, chunked_encoding),
+      NULL },
+
     { ngx_string("log_not_found"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
       ngx_conf_set_flag_slot,
@@ -2717,6 +2724,7 @@
     lcf->port_in_redirect = NGX_CONF_UNSET;
     lcf->msie_padding = NGX_CONF_UNSET;
     lcf->msie_refresh = NGX_CONF_UNSET;
+    lcf->chunked_encoding = NGX_CONF_UNSET;
     lcf->log_not_found = NGX_CONF_UNSET;
     lcf->recursive_error_pages = NGX_CONF_UNSET;
     lcf->server_tokens = NGX_CONF_UNSET;
@@ -2938,6 +2946,7 @@
     ngx_conf_merge_value(conf->port_in_redirect, prev->port_in_redirect, 1);
     ngx_conf_merge_value(conf->msie_padding, prev->msie_padding, 1);
     ngx_conf_merge_value(conf->msie_refresh, prev->msie_refresh, 0);
+    ngx_conf_merge_value(conf->chunked_encoding, prev->chunked_encoding, 1);
     ngx_conf_merge_value(conf->log_not_found, prev->log_not_found, 1);
     ngx_conf_merge_value(conf->recursive_error_pages,
                               prev->recursive_error_pages, 0);
Index: src/http/ngx_http_core_module.h
===================================================================
--- src/http/ngx_http_core_module.h	(revision 1293)
+++ src/http/ngx_http_core_module.h	(working copy)
@@ -302,6 +302,7 @@
     ngx_flag_t    port_in_redirect;        /* port_in_redirect */
     ngx_flag_t    msie_padding;            /* msie_padding */
     ngx_flag_t    msie_refresh;            /* msie_refresh */
+    ngx_flag_t    chunked_encoding;        /* chunked_encoding */
     ngx_flag_t    log_not_found;           /* log_not_found */
     ngx_flag_t    recursive_error_pages;   /* recursive_error_pages */
     ngx_flag_t    server_tokens;           /* server_tokens */
Index: src/http/modules/ngx_http_chunked_filter_module.c
===================================================================
--- src/http/modules/ngx_http_chunked_filter_module.c	(revision 1293)
+++ src/http/modules/ngx_http_chunked_filter_module.c	(working copy)
@@ -50,6 +50,8 @@
 static ngx_int_t
 ngx_http_chunked_header_filter(ngx_http_request_t *r)
 {
+    ngx_http_core_loc_conf_t  *clcf;
+
     if (r->headers_out.status == NGX_HTTP_NOT_MODIFIED
         || r->headers_out.status == NGX_HTTP_NO_CONTENT
         || r->headers_out.status == NGX_HTTP_CREATED
@@ -63,7 +65,14 @@
             r->keepalive = 0;
 
         } else {
-            r->chunked = 1;
+            clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+
+            if (clcf->chunked_encoding == 1) {
+                r->chunked = 1;
+
+            } else {
+                r->keepalive = 0;
+            }
         }
     }
 


More information about the nginx-ru mailing list