#apache #.htaccess
#apache #.htaccess
Вопрос:
В нашем .htaccess
файле есть несколько правил перезаписи на основе пути. Например, если URI указывает на /foobar/somestring
перенаправление на /foo/somestring
страницу, но мы также хотим принудительно загрузить ресурс https
.
Мы могли бы включить https://%{HTTP_HOST}
во все RewriteRule
s, сначала адресуя более конкретные URI, но я почти уверен, что в этом не должно быть необходимости.
Я просмотрел документы apache flags, но у меня возникли проблемы с поиском способа указать серверу обратиться к scheme
одному из способов и продолжить чтение правил и условий для обращения paths
.
Это долгосрочный подход, который у нас есть сейчас:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_URI} ^/foo
# Long list
RewriteRule ^foobar/(bat.*)$ https://%{HTTP_HOST}/foo/$1 [L,R=301]
RewriteRule ^foobar/(bas.*)$ https://%{HTTP_HOST}/foo/$1 [L,R=301]
# URI not found
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ https://%{HTTP_HOST}/index.php [L]
# And finally
RewriteCond %{HTTPS} !=on
RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R=301,L,NC]
</IfModule>
Большое спасибо.
Комментарии:
1. Это сложная задача для Apache. Лично я бы для простоты жестко запрограммировал
https
и покончил с этим. Также я бы поместил всю логику перенаправления https перед логикой маршрутизации 404, чтобы пользователи не видели index.php прямо в их браузере. Пожалуйста, используйте 302 перенаправления при тестировании такого рода материалов, чтобы вы не получили кэшированные 301-е в вашем браузере и не пропустили подобные вещи. Для достижения этого сначала используйте обычные перезаписи, а затем только перенаправляйте внизу. Флаг пропуска, или получение / настройка переменных ENV, или сравнение текущего URI с REQUEST_URI — все это может быть достигнуто.2. На самом деле нет реальной необходимости комбинировать эти две вещи. Вы реализуете перенаправление на
https
протокол самостоятельно. Причина в том, что 1. это должно быть сделано только один раз для любого клиента, независимо от того, сколько запросов они отправляют, и 2. что перезапись выполняется на другом хосте внутри вашего http-сервера.3. @Ultimater что вы подразумеваете под «жестко запрограммировать
https
для простоты»?
Ответ №1:
Ключевой проблемой здесь является понимание разницы между перенаправлением и перезаписью. Короче говоря, перенаправление происходит на стороне клиента, изменяя URL в браузере. Перезапись происходит на стороне сервера и прозрачна для браузера / клиента.
-
Примером перенаправления может быть изменение протокола с
http://
наhttps://
или добавление или удалениеwww
поддомена. -
Примером перезаписи может быть получение пути, подобного
/foo-bar-bas
и, перед отправкой его на обработку сервером (через ASP, Python, php, ruby on rails, node.js и т.д.), переписывая его какarticle.aspx?name=foo_bar_bar
или что-то подобное.
Вы можете видеть в OP выше, перенаправление с http://
на https://
, когда оно находилось в верхней части блока правил, приводило к короткому замыканию перезаписей под ним из-за следующих двух флагов:
R=301
который сообщает браузеру: «этот (A) ресурс переместился, теперь он находится в этом (B) местоположении».L
который сообщает Apache «прекратить обработку набора правил».- Третий флаг,
NC
означает игнорировать регистр, и/?(.*)
в любом случае не чувствителен к регистру.
Все, что нужно, это:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteBase /
RewriteCond %{HTTPS} !=on
RewriteRule ^/?(.*) https://%{HTTP_HOST}/$1
RewriteCond %{REQUEST_URI} ^/foobar
RewriteRule ^foobar/(bat.*)$ /foo/$1 [L,R=301]
RewriteRule ^foobar/(bas.*)$ /foo/$1 [L,R=301]
</IfModule>
Отчасти сбивает с толку то, что мы используем правило «Перезаписи» для достижения «Перенаправления» (а также перезаписи под ним.) Apache также поддерживает директиву перенаправления вне mod_rewrite
модуля. Я не уверен, сработает ли это здесь.
Стоит повторить комментарий @Ultimater выше о том, что при тестировании использование кода состояния 302 найдено в отличие от кода состояния 301 перемещено постоянно с R
флагом предотвратит отправку неправильного сообщения веб-сканерам или (потенциально вашим собственным) браузерам.