#.htaccess #mod-rewrite #apache2
#.htaccess #мод-перезапись #apache2
Вопрос:
Я уже давно сижу с этим и не могу разобраться в этом.
По сути, функциональность, которую я ищу в конце, была бы аналогична следующей:
http://example.com
перенаправляет на https://example.com
— текущий рабочий
и для
http://*.example.com
и https://*.example.com
перенаправить на https://example.com/*
— не работает. В настоящее время все поддомены перенаправляются на основной домен без соответствующего пути к папке. Кроме того, при переходе к https://test.example.com
он вообще не перенаправляет.
Вот example.com.conf
из sites-enabled
:
<IfModule mod_ssl.c&&t;
<VirtualHost *:80&&t;
ServerName example.com
ServerAlias www.example.com
# Redirect permanent / https://example.com/
<Directory /var/www/example.com/public_html&&t;
Options FollowSymLinks
AllowOverride All
Require all &ranted
</Directory&&t;
<IfModule mod_rewrite.c&&t;
# Redirect all traffic to HTTPS
RewriteCond %{HTTPS} !on
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [QSA,R=301,L]
</IfModule&&t;
</VirtualHost&&t;
<VirtualHost _default_:443&&t;
ServerAdmin webmaster@localhost
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example.com/public_html
<Directory /var/www/example.com/public_html&&t;
Options FollowSymLinks
AllowOverride All
Require all &ranted
</Directory&&t;
<IfModule mod_rewrite.c&&t;
# Remove www
RewriteCond %{HTTP_HOST} ^www.(. )$ [NC]
RewriteRule ^(.*)$ http://%1%{REQUEST_URI} [QSA,R=301,L]
RewriteCond %{HTTP_HOST} !^(www). [NC]
RewriteCond %{HTTP_HOST} ^(.*).example.com [NC]
RewriteRule ^(.*)$ https://example.com/%1/$1 [R=301,L]
</IfModule&&t;
ErrorLo& ${APACHE_LOG_DIR}/error.lo&
CustomLo& ${APACHE_LOG_DIR}/access.lo& combined
SSLEn&ine on
SSLCertificateFile /etc/ssl/civrpssl/example.com.crt
SSLCertificateKeyFile /etc/ssl/civrpssl/example.com.key
SSLCACertificateFile /etc/ssl/civrpssl/ca-example.com.crt
<FilesMatch ".(c&i|shtml|phtml|php)$"&&t;
SSLOptions StdEnvVars
</FilesMatch&&t;
<Directory /usr/lib/c&i-bin&&t;
SSLOptions StdEnvVars
</Directory&&t;
</VirtualHost&&t;
</IfModule&&t;
И, наконец, вот .htaccess
из example.com/public_html/
:
removed, see edit #2.
Я надеюсь, что это довольно очевидная проблема, которую я не смог увидеть. В противном случае, пожалуйста, не мог бы кто-нибудь просветить меня, с чего мне следует начать поиск проблемы? Я предполагаю, что перенаправление HTTPS мешает перенаправлению поддомена в файле .htaccess, но не знаю, как я мог бы выразить это по-другому.
ПРАВКА # 1: я только что заметил, что www.example.com
выдает ошибку «URL не найден» вместо перенаправления на https://example.com
. Почему он не перехватывается при первой перезаписи в .htaccess
?
ПРАВКА # 2:
- Перенесено перезапись с
.htaccess
наexample.com.conf
(код обновлен в post). - Добавлен VHost для порта 80, по сути, просто перенаправляющий весь трафик на HTTPS. Я обнаружил, что перенаправление сработало, однако оно не включало бы поддомены and в перенаправление, поэтому
http://test.example.com
привело бы только кhttps://example.com
. - Выполнялся
a2enmod rewrite
, поскольку, по-видимому, он не был включен.
Комментарии:
1. Как насчет виртуального хостинга для порта 80? Размещенный вами виртуальный хостинг исключает только запросы к
example.com
— никакие поддомены (включаяwww
) не принимаются. Однако, если это самый первый vHost, определенный в вашей конфигурации, то он все еще может перехватывать эти запросы. В противном случае ваши.htaccess
директивы выглядят «НОРМАЛЬНО», за исключением того, что если вы обращаетесь к конфигурации сервера, то в идеале вы должны перенаправлять HTTP и поддомены в конфигурации вашего сервера.2. Спасибо за отзыв! Я обновил сообщение. Пожалуйста, если у вас есть время, просмотрите его еще раз.
Ответ №1:
ServerName example.com ServerAlias www.example.com
Ни один из <VirtualHost&&t;
контейнеров не принимает запросы ни для каких поддоменов, за исключением www
. vHost все еще может перехватывать дополнительные поддомены (фактически, любое имя хоста), если это первый определенный vHost в конфигурации сервера. Чтобы перехватить «любой» поддомен, вам понадобится другой «подстановочный знак» ServerAlias
вида:
ServerAlias *.example.com
Удалите <IfModule mod_rewrite.c&&t;
оболочки — они не требуются. Они только замаскируют ошибку, если mod_rewrite недоступен. <IfModule&&t;
Оболочку следует использовать только в том случае, если эти директивы полностью необязательны и конфигурация должна быть перенесена на другие системы, где mod_rewrite недоступен.
ОБНОВЛЕНИЕ: вам также не хватало RewriteEn&ine On
директивы в vHost. Если механизм перезаписи уже не был включен где-либо в конфигурации сервера (маловероятно), то эти директивы mod_rewrite были бы просто пропущены вообще.
На vHost HTTP (порт 80)…
# Redirect all traffic to HTTPS RewriteCond %{HTTPS} !on RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [QSA,R=301,L]
Нет смысла проверять HTTPS
наличие порта 80 на vHost, поскольку это всегда будет off
. Если вы хотите перенаправить непосредственно из поддомена в подкаталог, вам нужно будет изменить приведенное выше значение на следующее:
# Redirect HTTP subdomains to HTTPS subdirectory (excludin& www)
RewriteCond %{HTTP_HOST} !^www. [NC]
RewriteCond %{HTTP_HOST} ^([^.] ).example.com [NC]
RewriteRule ^/(.*) https://example.com/%1/$1 [R=301,L]
# Redirect HTTP to HTTPS
RewriteRule ^/(.*) https://example.com/$1 [R=301,L]
Однако, если у вас есть какие-либо намерения внедрить HSTS в будущем, вам сначала нужно будет перенаправить на HTTPS на том же хосте и выполнить второе перенаправление в подкаталог на vHost только для порта 443. (Перенаправление с HTTP на HTTPS с использованием Redirect
директивы — в настоящее время закомментировано — хотя для этого потребовался бы отдельный (минимальный) vHost для каждого поддомена, что может быть нежелательно.)
^/(.*)
— Обратите внимание на добавление префикса косой черты за пределами подшаблона захвата в RewriteRule
шаблоне. В контексте виртуального хостинга полный URL-путь соответствует RewriteRule
шаблону. Завершение $
не требуется, поскольку регулярное выражение по умолчанию является жадным.
Обратите также внимание на регулярное выражение ([^.] )
(вместо (.*)
), которое конкретно соответствует только поддомену (без точек).
В вашем vHost для HTTPS (порт 443) у вас есть:
# Remove www RewriteCond %{HTTP_HOST} ^www.(. )$ [NC] RewriteRule ^(.*)$ http://%1%{REQUEST_URI} [QSA,R=301,L]
Вы перенаправляетесь обратно на HTTP (хотя, похоже, это ошибка, которую вы ввели после редактирования?).
Нет необходимости фиксировать RewriteRule
шаблон, если вы используете REQUEST_URI
переменную.
Затем то же самое редактирование применяется к перенаправлению поддомена в подкаталог, как упоминалось выше.
Краткие сведения
Объединив вышеуказанные моменты, мы получаем что-то вроде:
<VirtualHost *:80&&t;
ServerName example.com
ServerAlias www.example.com
ServerAlias *.example.com
#Redirect permanent / https://example.com/
RewriteEn&ine On
# Redirect HTTP subdomains to HTTPS subdirectory (excludin& www)
RewriteCond %{HTTP_HOST} !^www. [NC]
RewriteCond %{HTTP_HOST} ^([^.] ).example.com [NC]
RewriteRule ^/(.*) https://example.com/%1/$1 [R=301,L]
# Redirect HTTP to HTTPS (www and domain apex)
RewriteRule ^/(.*) https://example.com/$1 [R=301,L]
</VirtualHost&&t;
<VirtualHost *:443&&t;
ServerAdmin webmaster@localhost
ServerName example.com
ServerAlias www.example.com
ServerAlias *.example.com
DocumentRoot /var/www/example.com/public_html
<Directory /var/www/example.com/public_html&&t;
Options FollowSymLinks
# Set "AllowOverride None" to disable .htaccess altoðer
AllowOverride All
Require all &ranted
</Directory&&t;
RewriteEn&ine On
# Remove www
RewriteCond %{HTTP_HOST} ^www.(. )$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [QSA,R=301,L]
# Redirect other subdomains to subdirectory
RewriteCond %{HTTP_HOST} ^([^.] ).example.com [NC]
RewriteRule ^/(.*) https://example.com/%1/$1 [R=301,L]
ErrorLo& ${APACHE_LOG_DIR}/error.lo&
CustomLo& ${APACHE_LOG_DIR}/access.lo& combined
SSLEn&ine on
SSLCertificateFile /etc/ssl/civrpssl/example.com.crt
SSLCertificateKeyFile /etc/ssl/civrpssl/example.com.key
SSLCACertificateFile /etc/ssl/civrpssl/ca-example.com.crt
<FilesMatch ".(c&i|shtml|phtml|php)$"&&t;
SSLOptions StdEnvVars
</FilesMatch&&t;
<Directory /usr/lib/c&i-bin&&t;
SSLOptions StdEnvVars
</Directory&&t;
</VirtualHost&&t;
Сначала вам следует протестировать 302 (временные) перенаправления, чтобы избежать потенциальных проблем с кэшированием.
И очистите кэш вашего браузера перед тестированием (все ошибочные 301s будут кэшированы браузером).
Комментарии:
1. Приветствую, приятель! Это работает как шарм. Я также заметил, что в исходном сообщении и ответе отсутствовали
RewriteEn&ine on
, поэтому я добавил и это.2. Последующий вопрос по
Redirect from HTTP to HTTPS usin& the Redirect directive - currently commented out.
. Я пробовал это, но предполагал, что поддомен был потерян при таком перенаправлении? Можно ли полностью удалить перезапись с vhost для порта 80 и обработать все это на 443, просто раскомментировав строку перенаправления?3. «Я также заметил, что в исходном сообщении и ответе отсутствовали
RewriteEn&ine on
, поэтому я добавил и это». — Упс, да, вам это понадобится! (Если только он еще не включен где-либо в конфигурации сервера — маловероятно.) — Я обновлю свой ответ, чтобы включить это.4. «Можно ли полностью удалить перезапись с vhost для порта 80 и обработать все это на 443, просто раскомментировав строку перенаправления?» — Ну, не все так просто. Вам нужно было бы создать минимальный vHost для каждого поддомена, который содержал бы
Redirect
— так что это может быть нежелательно. Вероятно, предпочтительнее придерживаться mod_rewrite, особенно если у вас много таких поддоменов.