ПРОЕКТЫ 


  АРХИВ 


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: Редирект HTTP заго ловком "Location" 2



Hello!

On Tue, Jul 22, 2008 at 02:07:04AM +0400, Maxim Dounin wrote:

Hello!

On Tue, Jul 22, 2008 at 12:42:12AM +0400, Alexey Kalinnikov wrote:

 Не так давно (по весне) было уже обсуждение темы о редиректе при
 заголовке "Location". Хотяелось бы еще раз поднять ее.

 Проблема в том, что если необходим редирект (в моем случае
 происходит выполнение fcgi perl) то помимо указания Location
 необходимо обязательно указывать "302 Found", в противном случае
 nginx ставит статус 200. Apache, lighttpd и другие сервера ставят
 302 и все отрабатывается "правильно".

 Достаточно четко проблема прописана как в той теме (Редирект HTTP
 заголовком "Location") так и к примеру в
 
http://www.zag.ru/page/item_view/tarakan_tarakan_tarakashechka_zhidkonogaja_kozjavochka_bukashechka.html

 Внимательное изучение RFC 1945 ничего не дало. а гугление выдало
 следующую сентенцию

Курить надо не RFC1945, а спеки FastCGI.  Спеки FastCGI говорят, что:

 % 6.2 Responder
 % A Responder FastCGI application has the same purpose as a CGI/1.1
 % program: It receives all the information associated with an HTTP
 % request and generates an HTTP response.
...
 % The Responder application sends CGI/1.1 stdout data to the Web
% server over FCGI_STDOUT, and CGI/1.1 stderr data over FCGI_STDERR. Т.е. по формату самого ответа нас отсылают к CGI/1.1. Идём курить спеки CGI/1.1 и находим там:

http://hoohoo.ncsa.uiuc.edu/cgi/out.html

 % Parsed headers
 % The output of scripts begins with a small header. This header
 % consists of text lines, in the same format as an HTTP header,
 % terminated by a blank line (a line with only a linefeed or CR/LF).
 % Any headers which are not server directives are sent directly back
 % to the client. Currently, this specification defines three server
 % directives:
 %
 % Content-type
 % This is the MIME type of the document you are returning.
 %
 % Location
 % This is used to specify to the server that you are returning a
 % reference to a document rather than an actual document.
 %
 % If the argument to this is a URL, the server will issue a redirect
% to the client. А в RFC3875 (который ни разу не стандарт, но суть более формальное описание CGI/1.1) так вообще чёрным по белому что должен быть 302:

 % 2.3.  Client Redirect Response
 %
 %    The CGI script can return an absolute URI path in a Location header
 %    field, to indicate to the client that it should reprocess the request
 %    using the URI specified.
 %
 %       client-redir-response = client-Location *extension-field NL
 %
 %    The script MUST not provide any other header fields, except for
 %    server-defined CGI extension fields.  For an HTTP client request, the
 %    server MUST generate a 302 'Found' HTTP response message.

Такая вот многоходовка получается, по которой вообще говоря надо возвращать 302 если fastcgi-скрипт вернул заголовок Location.

 "The HTTP status code changes the way browsers and robots handle
 redirects, so if you are using header(Location:) it's a good idea
 to set the status code at the same time. Browsers typically
 re-request a 307 page every time, cache a 302 page for the session,
 and cache a 301 page for longer, or even indefinitely.
 Search engines typically transfer "page rank" to the new location for 301 
redirects,
 but not for 302, 303 or 307.

 If the status code is not specified, header('Location:') defaults to 302."


 Нельзя ли в и в nginx добавить данный функционал (возврат кода 302
 вместо 200 если в хедере есть указание Location)? Или может быть кто
 то может подсказать как реализовать его "на стороне веб-сервера"?

В ngx_http_fastcgi_module это легко запихивается. Если я сподоблюсь построить тестовую среду для FastCGI - сделаю патч.

Патч.

Maxim Dounin
# HG changeset patch
# User Maxim Dounin <mdounin@xxxxxxxxxx>
# Date 1216680959 -14400
# Node ID 1e54028db936e988171a4eb9a5c8eff81c0ad827
# Parent  1d9bef53cd8e9461c73ed537a953f3a7bae6dbd2
Set 302 status if there is Location header in fastcgi reply.

Per FastCGI specification application reply is actually CGI/1.1 stdout
reply.  And per CGI/1.1 spec if application reply has Location header -
server must generate 302 redirect.

diff --git a/src/http/modules/ngx_http_fastcgi_module.c 
b/src/http/modules/ngx_http_fastcgi_module.c
--- a/src/http/modules/ngx_http_fastcgi_module.c
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -1167,6 +1167,13 @@ ngx_http_fastcgi_process_header(ngx_http
                     u->headers_in.status_n = status;
                     u->headers_in.status_line = *status_line;
 
+                } else if (u->headers_in.location) {
+                    u->headers_in.status_n = 302;
+                    u->headers_in.status_line.len =
+                                           sizeof("302 Moved Temporarily") - 1;
+                    u->headers_in.status_line.data =
+                                           (u_char *) "302 Moved Temporarily";
+
                 } else {
                     u->headers_in.status_n = 200;
                     u->headers_in.status_line.len = sizeof("200 OK") - 1;
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -137,7 +137,8 @@ ngx_http_upstream_header_t  ngx_http_ups
                  ngx_http_upstream_copy_header_line, 0, 0 },
 
     { ngx_string("Location"),
-                 ngx_http_upstream_ignore_header_line, 0,
+                 ngx_http_upstream_process_header_line,
+                 offsetof(ngx_http_upstream_headers_in_t, location),
                  ngx_http_upstream_rewrite_location, 0, 0 },
 
     { ngx_string("Refresh"),


 




Copyright © Lexa Software, 1996-2009.