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

htaccess заменяет полный URL вместо REQUEST_URI

Я работаю над чем-то, что должно быть действительно простым, но на второй день биться головой об стену. Требования к перенаправлению URL-адресов:

Проблема: когда я прошу https://example.com/file.html Я получаю r = 301, чтобы

https://example.com/utilities/template_handler.php?filename=https://www.example.com/file.html

Мой .htaccess:

RewriteEngine On
RewriteBase /

RewriteCond %{HTTPS} off
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [R=301]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule .* https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301]

RewriteRule ^(.*)\.html$ /utilities/template_handler.php?filename=$1.html [NC]

Я использую веб-сервер litespeed, но для устранения неполадок настраиваю и Apache, результат тот же. После включения отладки я вижу:

strip base: '/' from URI: '/file.html'
Rule: Match 'file.html' with pattern '.*', result: 1
Cond: Match 'on' with pattern 'off', result: -1
Rule: Match 'file.html' with pattern '.*', result: 1
Cond: Match 'domain.com' with pattern '^www\.', result: -1
Source URI: 'file.html' => Result URI: 'https://www.example.com/file.html'
Rule: Match 'https://www.example.com/file.html' with pattern '^(.*)\.html$', result: 2
Source URI: 'https://www.example.com/file.html' => Result URI: '/utilities/template_handler.php?filename=https://www.example.com/file.html'
replace current query string with 'filename=https://www.example.com/file.html'

Если я закомментирую последнее правило, первые два требования будут обработаны правильно.

Та же ошибка, если запрос отправлен на не-www или на www, но не-ssl.

RewriteCond %{HTTPS} off
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [R=301]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule .* https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301]

Вам нужно включить L (last) на обоих RewriteRule директивы, в противном случае обработка файла будет продолжена, а URL-адрес будет перезаписан RewriteRule следующее (используя результат предыдущей директивы). И поскольку внешнее перенаправление уже было инициировано предыдущими директивами, вы получите перенаправлен извне к /utilities/template_handler.php?filename=...., скорее, чем внутренне переписанный.

Эти директивы также должны быть отменены, чтобы избежать ненужного двойного перенаправления при запросе URL-адреса формы http://example.com/.... (В частности, с добавлением L флаг.)

Например:

RewriteCond %{HTTP_HOST} !^www\.
RewriteRule .* https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
RewriteCond %{HTTPS} off
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

Обратите внимание: я удалил NC флаг отрицаемого !^www\. состояние. Поскольку это отрицается регулярное выражение, вы хотите, чтобы он перенаправлялся, когда он не запускается www - все строчные. Вам по-прежнему нужны "плохие" запросы в форме WwW для перенаправления - но если вы включите NC флага здесь они не будут.

Вы можете включить L флаг на самом последнем RewriteRule если хотите - хотя это было бы хорошей практикой. Фактически это подразумевается, так как в любом случае это последнее правило, но если вы добавили больше директив, вам, возможно, придется не забыть добавить его.