Редирект HTTP заголовком "Location" 2
Maxim Dounin
mdounin at mdounin.ru
Tue Jul 22 03:04:11 MSD 2008
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
-------------- next part --------------
# HG changeset patch
# User Maxim Dounin <mdounin at mdounin.ru>
# 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"),
More information about the nginx-ru
mailing list