Назад | Перейти на главную страницу

Почему Apache явно принудительно перенаправляет с абсолютным URL-адресом?

Контекст

Со следующим правилом:

# Redirect root url to /tvs
RewriteRule ^/$ /tvs [R=301,L]

У меня есть абсолютное перенаправление вроде:

HTTP/1.1 301 Moved Permanently
Server: nginx
Date: Fri, 24 Mar 2017 16:42:23 GMT
Content-Type: text/html; charset=iso-8859-1
Content-Length: 312
Location: http://www.tvsvizzera.it/tvs
Vary: Accept-Encoding
X-Node: pcache02
X-Cached: MISS
Proxy-Connection: Keep-Alive
Connection: Keep-Alive

и в rewrite.log у меня есть следующие

10.101.114.1 - - [24/Mar/2017:16:43:34 +0100] [www.tvsvizzera.it/sid#7fd446c22168][rid#7fd446d6eb48/initial] (2) init rewrite engine with requested uri /
10.101.114.1 - - [24/Mar/2017:16:43:34 +0100] [www.tvsvizzera.it/sid#7fd446c22168][rid#7fd446d6eb48/initial] (2) rewrite '/' -> '/tvs'
10.101.114.1 - - [24/Mar/2017:16:43:34 +0100] [www.tvsvizzera.it/sid#7fd446c22168][rid#7fd446d6eb48/initial] (2) explicitly forcing redirect with http://www.tvsvizzera.it/
tvs
10.101.114.1 - - [24/Mar/2017:16:43:34 +0100] [www.tvsvizzera.it/sid#7fd446c22168][rid#7fd446d6eb48/initial] (1) escaping http://www.tvsvizzera.it/tvs for redirect
10.101.114.1 - - [24/Mar/2017:16:43:34 +0100] [www.tvsvizzera.it/sid#7fd446c22168][rid#7fd446d6eb48/initial] (1) redirect to http://www.tvsvizzera.it/tvs [REDIRECT/301]

Почему apache явно заставляет перенаправление быть абсолютным?

Проблема

Сервер находится за обратным прокси-сервером, выполняющим разгрузку SSL. Таким образом, если перенаправление останется относительным, то же правило будет работать для обоих протоколов HTTP / HTTPS. Но это не тот случай, и при запросе с https происходит перенаправление на http.

Я знаю, что могу изменить правило, чтобы оно было примерно таким

RewriteRule ^/$ %{ENV:REQUEST_SCHEME}://%{HTTP_HOST}/tvs [R=permanent,L]

Но я хотел понять это поведение.

Спасибо за любые объяснения.

Все внешние перенаправления (R flag) приводят к тому, что mod_rewrite требует абсолютного URL. Если вы явно не включаете схему и имя хоста в RewriteRule замена тогда Apache будет использовать текущий протокол, имя сервера и порт. Apache (или, строго говоря, mod_rewrite) не отправляет относительный URL-адрес обратно в Location: Заголовок ответа HTTP в надежде, что пользовательский агент разрешит URL.

(Так было до июня 2014 г. (RFC 7231) который родственник URL-адреса в Location: header официально стал частью стандарта. Так что, особенно если вы все еще используете Apache 2.2, трудно утверждать, что Apache здесь делает что-то не так.)

Если Apache отправляет обратно URL-адрес HTTP (в отличие от HTTPS), то может показаться, что Apache отправляет ответ обратно через HTTP, а не HTTPS.

Да, вы можете вручную «исправить» URL с помощью mod_rewrite. Однако REQUEST_SCHEME переменная сервера скорее всего имеет ту же "проблему". Если вы находитесь за прокси, вам может потребоваться проверить X-Forwarded-Proto заголовок (или аналогичный) относительно того, "http" или "https".

Помимо (условно) принудительного использования HTTPS в самой директиве, вы также можете сила HTTPS в конфигурации сервера с ServerNameUseCanonicalName) директива (ы). Однако я считаю, что это нежелательно, и вам нужно проявлять гибкость?

Вы также можете редактировать то Location: заголовок, прежде чем он будет отправлен обратно клиенту. Используя mod_headers, вы можете принудительно указать относительный URL-адрес, вручную удалив схему + имя хоста, как предлагается в этот ответ StackOverflow:

Header edit Location "^https?://[a-zA-Z0-9.-]+" ""

Дополнительная ссылка: