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

Перевод правил перезаписи htaccess в правила виртуального хоста Apache2

Я пытаюсь установить поддомен с подстановочными знаками RewriteRule объединив некоторые .htaccess правила, которые я успешно реализовал раньше, полагая, что я могу использовать те же правила для моего файла Apache vhosts.

По сути, example.com и www.example.com перейдите к корневому пути и найдите index.php. Все остальные (динамические) запросы субдоменов на корневом уровне, такие как abc.example.com переписать (невидимо для браузера) на example.com/process.php?p=abc.

Во-вторых, любые запросы файлов из субдомена за пределами базового / корневого уровня должны быть переписаны, чтобы они были получены из корневого пути стандартного домена без субдомена. Так abc.example.com/css/style.css должен прийти из example.com/css/style.css

Это моя попытка сделать это. Я получаю сообщение об ошибке Apache:

У вас нет разрешения на доступ к /index.php на этом сервере.

для любой попытки поддомена, кроме www, которая работает, как ожидалось, а также стандарт example.com, который по-прежнему отлично работает.

<VirtualHost *:80>

        ServerAdmin webmaster@example.com
        ServerName example.com
        ServerAlias www.example.com
        DocumentRoot /var/www/example.com/public_html

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

</VirtualHost>

<VirtualHost *:80>
        ServerAdmin webmaster@example.com
        ServerName other.example.com
        ServerAlias *.example.com
        DocumentRoot /var/www/example.com/public_html/

        <Directory /var/www/example.com/public_html/>
        Options FollowSymLinks
        AllowOverride all
        Require all granted

        RewriteCond %{HTTP_HOST} !^www\.example\.com$ [NC]
                RewriteCond %{HTTP_HOST} ^(www\.)?([^\.]+)\.example\.com$ [NC]
                RewriteRule ^$ /process.php?p=%2 [QSA,NC]
                RewriteCond %{REQUEST_FILENAME} !^$ [NC]
                RewriteRule ^(.*) http://www.example.com/$1 [P]
        </Directory>
</VirtualHost>

Я бы основал это на успешном перенаправлении корневого каталога другого домена в example.com используя это .htaccess файл, который включает process.php и отправляет все остальные запросы в корень example.com.

Options +FollowSymLinks
RewriteEngine On
RewriteBase /

# Check the request isn't an existing file
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^$ http://www.example.com/process.php [P]
RewriteCond %{REQUEST_FILENAME} !^$ [NC]
RewriteRule ^(.*) http://www.example.com/$1 [P]

А также от этого .htaccess тест, который я выполнил, чтобы перенаправить субдомен в качестве переменной на process.php успешно, хотя он не перехватил другие файловые запросы, такие как пример css выше:

Options +FollowSymLinks
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} !^www\.example\.com$ [NC]
RewriteCond %{HTTP_HOST} ^(www\.)?([^\.]+)\.example\.com$ [NC]
RewriteRule ^$ /process.php?p=%2 [QSA,NC]


Обновление 1

У меня был (по-видимому) некоторый успех, используя следующее вместо моей второй записи виртуального хоста. В process.php страница выводится, если я использую поддомен. Хотя сопоставление с образцом, похоже, работает в этом отношении, мои фактические process.php получает пустую переменную, а не ожидаемый субдомен в виде строки (для: process.php?p=%2):

<VirtualHost *:80>
        ServerAdmin webmaster@example.com
        ServerName other.example.com
        ServerAlias *.example.com
        DocumentRoot /var/www/example.com/public_html

        <Directory /var/www/example.com/public_html>
        Options FollowSymLinks
        AllowOverride all
        Require all granted
        RewriteEngine on
        RewriteBase /

        RewriteCond %{HTTP_HOST} !^www\.example\.com$ [NC]
        RewriteCond %{HTTP_HOST} ^(www\.)?([^\.]+)\.example\.com$ [NC]
        RewriteCond %{REQUEST_URI} ^/$
        RewriteRule ^$ /process.php?p=%2 [NC,QSA]
        </Directory>
</VirtualHost>


Обновление 2

Я решил это окольным путем, но не уверен, что это самый элегантный способ сделать это.

Используя вышеуказанное обновление 1 код, я увидел, что любая строка запроса все еще добавляется, но %2 не был получен GET в моем process.php страница. Возможно, я ошибочно предположил, что хотя URL-адрес не отображает p=abc переменная в URL-адресе браузера, в соответствии с инструкциями моего кода, что внутренний URL-адрес все еще передавал их. Тем не менее я понял, что process.php все еще может определить субдомен как строку, используя $_SERVER['HTTP_X_FORWARDED_HOST'] в PHP и использовать его в качестве переменной на странице аналогично моей первоначальной идее.

RewriteCond %{HTTP_HOST} !^www\.example\.com$ [NC]
RewriteCond %{HTTP_HOST} ^(www\.)?([^\.]+)\.example\.com$ [NC]
RewriteCond %{REQUEST_URI} ^/$
RewriteRule ^$ /process.php?p=%2 [NC,QSA]

В %2 обратная ссылка не была установлена, потому что это обратная ссылка на вторую захваченную группу последнее совпадение CondPattern (RewriteCond шаблон). Последний совпавший CondPattern: ^/$ у которого нет захваченных групп, поэтому %2 всегда пусто.

Этот третий RewriteCond Директива в любом случае выглядит излишней. Это уже проверяется RewriteRule шаблон ^$ (в контексте каталога префикс каталога удаляется - так что это правильно).

Первый RewriteCond Директива тоже выглядит лишней. Любой запрос на www.example.com будет обнаружен первым VirtualHost, поэтому имя хоста внутри этого VirtualHost никогда не бывает www.example.com в любом случае, поэтому эта директива всегда принимает значение true.

Я бы переписал это так:

RewriteCond %{HTTP_HOST} ^(?:www\.)?([^.]+)\.example\.com$ [NC]
RewriteRule ^$ process.php?p=%1 [QSA]

Я сделал первый группа без захвата, т.е. (?:www\.) - в ?: делает его не захватывающим. Итак, мы получаем только %1 для фактического субдомена. Кроме того, нет необходимости экранировать точку (чтобы соответствовать буквальной точке) в классе символов. В NC флаг на RewriteRule здесь лишнее.

Я также удалил префикс косой черты на RewriteRule замена поскольку вы указали URL-путь в RewriteBase директива.

Это только переписывает abc.example.com/, т.е. запрос на корень документа.

Во-вторых, любые запросы файлов из субдомена за пределами базового / корневого уровня должны быть переписаны, чтобы получить их из корневого пути стандартного домена без субдомена. Так abc.example.com/css/style.css должен прийти из example.com/css/style.css.

поскольку abc.example.com/ и example.com/ указывает на то же место в файловой системе, которое я не вижу, поскольку вам здесь что-то нужно делать? example.com/css/style.css должен указывать на тот же файл, что и abc.example.com/css/style.css.

А как насчет других файлов в корне документа? например. abc.example.com/file. На данный момент это просто проходит без изменений, что и для файлов CSS.