ПРОЕКТЫ 


  АРХИВ 


Apache-Talk @lexa.ru 

Inet-Admins @info.east.ru 

Filmscanners @halftone.co.uk 

Security-alerts @yandex-team.ru 

nginx-ru @sysoev.ru 


  СТАТЬИ 


  ПЕРСОНАЛЬНОЕ 


  ПРОГРАММЫ 



ПИШИТЕ
ПИСЬМА












     АРХИВ :: nginx-ru
Nginx-ru mailing list archive (nginx-ru@sysoev.ru)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: IE7 bug / force response to HTTP/1.0



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
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
@@ -58,6 +60,12 @@
         return ngx_http_next_header_filter(r);
     }
 
+    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+
+    if (clcf->chunked_encoding == 0) {
+        return ngx_http_next_header_filter(r);
+    }
+
     if (r->headers_out.content_length_n == -1) {
         if (r->http_version < NGX_HTTP_VERSION_11) {
             r->keepalive = 0;


 




Copyright © Lexa Software, 1996-2009.