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

Apache перезаписывает любой поддомен, кроме одного, на https без www.

Я пытаюсь уменьшить количество цепочек переадресации 301 на моем сервере, поэтому я хотел бы объединить поддомен с переадресацией без www (кроме случаев, когда поддомен dev) с перенаправлением HTTP на HTTPS (используя %{HTTP:X-Forwarded-Proto}), поскольку экземпляр находится за балансировщиком нагрузки.

Вот что у меня в .htaccess:

# move http to https 
RewriteCond %{HTTP:X-Forwarded-Proto} =http
RewriteRule .* https://%{HTTP:Host}%{REQUEST_URI} [L,R=301]

# Remove leading www 
RewriteCond %{HTTP_HOST} ^www.example.net [NC]
RewriteRule ^(.*)$ https://example.net/$1 [R=301,L]

В моей нынешней реализации есть три проблемы:

  1. Просьба к http://www.example.net будет два редиректа.

  2. Как и большинство примеров перенаправления с www на не-www на этом сайте, он не перенаправляет ww. или wwww. поэтому в моей аналитике есть много неправильно введенных поддоменов, которые не были перенаправлены.

  3. Я бы хотел исключить dev. поддомен из перенаправления, поэтому http://dev.example.net и это https брат, как я использую dev. для разработки и постановки релизов.

Как мне это объединить?

# Remove leading www, always using https regardless of the current URL scheme
RewriteCond %{HTTP_HOST} ^w{2,4}.example.net(?::|$) [NC,NV]
RewriteRule .* https://example.net%{REQUEST_URI} [L,R=301]

# move http to https, except for dev.example.net
RewriteCond %{HTTP:X-Forwarded-Proto} =http [NC,NV]
RewriteCond %{HTTP_HOST} !^dev.example.net(?::|$) [NC,NV]
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
  1. Добавлено NC (nocase) флаг в X-Forwarded-Proto условие, так как его значение казалось неважным, т.е. HTTP = Http = hTTp = http. Вы можете удалить это.
  2. Добавлено NV (novary) флаг в X-Forwarded-Proto условие, чтобы скрыть это от Vary заголовок ответа. Опять же, вы можете удалить это, особенно если это не так (обратный прокси-сервер все равно автоматически фильтрует его перед отправкой клиенту) или необходимо для правильного поведения кеширования (в противном случае кеш не различает http и https содержание).
  3. Добавлено NV (novary) флаг в Host условие заголовка, чтобы скрыть его от Vary заголовок ответа. Вы также можете удалить это, если у вас сломался кеш-сервер.
  4. Сделано RewriteRule порядок флагов согласован (L,R=301 и R=301,L по сути одинаковы).
  5. Предотвращено www.example.net.but.not.actually.yours.com от признания, но все же позволяет, например, www.example.net:443.
  6. Последовательно используйте %{REQUEST_URI} в качестве замены.
  7. Также признаем ww и wwww.

1) Обращение к http://www.example.net будет два редиректа.

Это можно решить, просто поменяв местами два правила. затем www.example.net перенаправляется на HTTPS при первом перенаправлении, поэтому перенаправление HTTP на HTTPS запускать не нужно.

(Это, однако, предполагает, что вы не собираетесь реализовывать HSTS - в этом случае вам нужно будет сохранить их как два перенаправления с момента перенаправления на HTTPS на одном и том же имени хоста первый это требование.)

2) Как и большинство примеров перенаправления с www на не-www на этом сайте, он не перенаправляет ww. или wwww. поэтому в моей аналитике есть много неправильно введенных поддоменов, которые не были перенаправлены.

Обычно запросы ww. или wwww. субдомены просто не разрешаются, так что обычно это не проблема. Чтобы это работало, вам необходимо настроить подстановочный знак поддомен в DNS и настроил сервер для приема таких запросов.

Но это можно объяснить, изменив регулярное выражение (фрагмент) из ^www\. к ^w{2,4}\..

3) Я хочу исключить dev. поддомен из перенаправления, поэтому http://dev.example.net и это https брат, как я использую dev. для разработки и постановки релизов.

Это применимо только к правилу HTTP to HTTPS, поэтому здесь можно применить дополнительное условие для исключения имен хостов, начинающихся с dev..

Объединив указанные выше моменты, попробуйте следующее:

# Remove leading ww, www or wwww (and redirect to HTTPS)
RewriteCond %{HTTP_HOST} ^w{2,4}\.example\.net [NC]
RewriteRule (.*) https://example.net/$1 [R=301,L]

# Move http to https (except dev subdomain)
RewriteCond %{HTTP:Host} !^dev\. [NC]
RewriteCond %{HTTP:X-Forwarded-Proto} =http
RewriteRule ^ https://%{HTTP:Host}%{REQUEST_URI} [R=301,L]

Я продолжал использовать HTTP:Host то же самое (чтобы получить доступ к Host Заголовок HTTP-запроса), если это требование балансировщика нагрузки? В противном случае чаще используют HTTP_HOST здесь переменная сервера.

В ! префикс на CondPattern (т.е. !^dev\.) отменяет регулярное выражение, поэтому условие выполняется, когда Host делает не начать с dev.. (Я предполагаю www.dev. не вещь?)

(.*) такой же как ^(.*)$ поскольку регулярное выражение по умолчанию является жадным.

Перед тестированием вам необходимо очистить кеш браузера. Желательно сначала протестировать с 302 (временными) перенаправлениями, чтобы избежать проблем с кешированием.