ПРОЕКТЫ 


  АРХИВ 


Apache-Talk @lexa.ru 

Inet-Admins @info.east.ru 

Filmscanners @halftone.co.uk 

Security-alerts @yandex-team.ru 

nginx-ru @sysoev.ru 

  СТАТЬИ 


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


  ПРОГРАММЫ 



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














     АРХИВ :: Apache-Talk
Apache-Talk mailing list archive (apache-talk@lists.lexa.ru)

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

[apache-talk] "Location:" redirect & keep-alive


  • To: apache-talk@xxxxxxxxxxxxx
  • Subject: [apache-talk] "Location:" redirect & keep-alive
  • From: Sergey Skvortsov <skv@xxxxxxxxx>
  • Date: Thu, 12 May 2005 20:53:24 +0400
  • Content-length: 2866
  • Organization: 3W Graphics

Имеем ситуацию - cервер (назовём его server) с включенным keep-alive.

httpd.conf:
Redirect temp /aaa http://server/bbb.htm

wget -S server/aaa

HTTP/1.1 302 Found
Location: http://server/bbb.htm
Connection: close
Content-Type: text/html; charset=iso-8859-1

Location: http://server/bbb.htm [following]

HTTP/1.1 200 OK
Accept-Ranges: bytes
Content-Length: XXX
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Content-Type: text/html

(для простоты часть header'ов поскипана).

Всё бы хорошо. Если бы не "Connection: close" в первом response.
Это - типичная фишка apach'а, напрямую следующая из логики
ap_set_keepalive() (src/main/http_protocol.c). Если, скажем, нет заголовка
"Content-Length" (или просто body, или ещё десяток условий) - то закрываем
соединение.

Эта логика была бы логична, если исходить из того, что redirect
всенепременнейше ведёт на другие сайты. Но вся прелесть в том, что чаще-то
redirect определяется в пределах одного сервера. Типичнейший (для меня)
пример - сайт с несколькими языками, и проброс с корня сайта на его
версию-с-языком-по-умолчанию, скажем так:

RewriteRule     ^/(index\.html?)?$      en/index.htm    [R,L]

Именно этот момент "проброса" хочется сделать моментальным, раз уж, скрепя
сердце, разрешён keep-alive для сервера (с побочным эффектом в виде
ненавистных FIN_WAIT_2). Быстро вывести первую страницу - это почти как
победа в сражении.

Решений напрашивается два:
1. Выдавать body и, соотв., выставлять честный "Content-Length".
Это удобно для redirect'ов, приходящих от backend'а (скажем, как результат
авторизации) - keep-alive гарантированно заработает.
И так делают многие и для frontend'ов (см. wget -S google.com).

2. Патчить mod_alias.c/mod_rewrite.c на предмет добавления после строки:
	ap_table_setn(r->headers_out, "Location", ret);
такой вот вещи как:
	r->header_only = 1;

(Выставлять "Content-Length: 0" - явный моветон).

Пропатченный сервер делает всё как надо:

HTTP/1.1 302 Found
Location: http://server/bbb.htm
Keep-Alive: timeout=15, max=99
Connection: Keep-Alive
Content-Type: text/html; charset=iso-8859-1

Location: http://server/bbb.htm [following]
......

Вопрос первый - стоит ли так вот пошло обманывать Apache?

Он, в принципе, и сам обманываться рад - см. в ap_set_byterange() (всё тот
же src/main/http_protocol.c) такие строчки:
	r->header_only = 1;
	r->status = HTTP_RANGE_NOT_SATISFIABLE;

Вопрос второй - а не послать ли этот патчик, чтоб данное поведение стало
по-умолчанию?

Конечно основная проблема не в сути патча (проще выкинуть mod_rewrite и
написать нехитрый модуль для "проброса") - а в изменении r->header_only и
правомерности самого подхода - возвращать "Location" с "Connection:
Keep-Alive" но без "Content-Length". В RFC2616 вопрос соответствия http
status codes и заголовка "Connection" как-то вовсе не рассматривается.

-- 
Sergey Skvortsov
mailto: skv@xxxxxxxxx



 




Copyright © Lexa Software, 1996-2009.