Архив рубрики: Apache

Как перенаправить посетителя на HTTPS, если Апач глубоко

Время от времени помогаю знакомым старта́перам в части, относящейся к вебу. В процессе обнаруживаю странное: есть сайты, которыми не сильно можно порулить, даже если и хочется: хостинг-провайдер предоставляет лишь возможность править апачный конфигурационный файл .htaccess. Всё бы ничего, но между файлами и посетителем сайта не только Apache — там ещё и Nginx, чья конфигурация вообще недоступна.

Сейчас в 2023 году редко какой сайт не использует HTTPS (этот — один из них, но сейчас не о нём речь). Если сайт сделан на какой-нибудь CMS, там вполне может существовать возможность указать в настройках основной адрес сайта и включить перенаправление на него — так можно перенаправляться на использование HTTPS и в WordPress, и в Open Journal Systems.

Но что делать, если сайт — статичный? Вроде бы, можно обойтись средствами самого́ Апача, а точнее, его модуля mod_rewrite — напишем в .htaccess:

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteCond %{HTTPS} off
  RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</IfModule>

Этот код включает механизм перенаправлений, проверяет, используется ли HTTPS и если нет — перенаправляет посетителя. Только в нашем случае условие RewriteCond всегда истинно, что вызывает циклические перенаправления. Причина — Apache в конкретном случае работает всегда по HTTP, поэтому значение переменной HTTPS — всегда off. С другими переменными аналогично — например, SERVER_PORT всегда равен 80.

В случае, когда есть доступ к настройкам Nginx, проблем нет — всё настраивается там. Но если нет, приходится искать другие переменные, которые однозначно покажут, как именно посетитель обращается к сайту. Nginx, передавая запрос Апачу, добавляет в него поля, чьи имена начинаются с X-Forwarded — среди них есть и X-Forwarded-Proto, где хранится запрашиваемый посетителем протокол — http или https. В итоге работоспособным оказался такой код:

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteCond %{HTTP:X-Forwarded-Proto} !https
  RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</IfModule>

Может возникнуть вопрос — нельзя ли в условии вместо !https написать более короткое http? Оказалось, что нет — сама по себе строка без знака равенства не проверяется на совпадение, а сопоставляется с образцом, то есть, происходит pattern matching. А такому условию удовлетворяли бы оба рассмотренных значения и условие всегда оказывалось бы истинным, что снова бы вызвало циклические перенаправления.

Почти что Перл с Апачем

Новости географии: в одном люксембургском углу находится никому не известная деревня Шенген, ближайшая к ней железнодорожная платформа, буквально на другом берегу реки — Perl (по-русски всё-таки Перль), это же имя носит и муниципалитет (в других переводах — коммуна), и крупнейший его населённый пункт. А рядом с ними — Apach, но по-русски это не Апач, а, если верить википедии, Апаш, хотя, думаю, немцы могут прочесть и как Апах. При этом все три эти деревни — в разных странах.

Карта

Точка конф

Apache 2.2 у маленьких конфигурационных файлов, вызываемых из основного, не использует расширение (хотя и не запрещает его применячть, конечно же). Старый Апач 1.3 — использовал. Как выяснилось методом тыка и чтения stackoverflow, новый Апач 2.4 — снова использует, во всяком случае команды a2ensite something и a2dissite something пытаются найти файл sites-available/something.conf. Да и в остальных каталогах /etc/apache2/*-available — куча conf-файлов.

Кусок конфигурационного файла

Значит, при неизбежном когда-нибудь обновлении апача надо будет вспомнить о необходимости переименования конфигурационных файлов.

Указание языка в URL страниц в Open Journal Systems

Open Journal Systems — система управления электронными научными журналами — имеет одинаковые адреса страниц, написанных на разных языках. Посетитель, зашедший на сайт научного журнала, работающего на OJS, либо увидит страницу на языке по умолчанию либо, если раньше уже заходил и менял язык, на том, что выбрал. Кому-то такой подход нравится, кому-то — нет. На самом деле — вполне нормальная ситуация.

Тем не менее, возникла задача всё-таки получить возможность явно указать язык в адресе страниц. Переключение выбранного языка делается средствами самой OJS — достаточно зайти (то есть, выполнить GET-запрос) по адресу вида адрес-журнала/user/setLocale/локаль?source=путь/куда/идти/дальше, например, http://vestnik.susu.ru/cmi/user/setLocale/ru_RU?source=/cmi/issue/current — переход по этой ссылке приведёт к выведенному на русском языке оглавлению текущего выпуска серии «Вычислительная математика и информатика» Вестника Южно-Уральского государственного университета.

С одной стороны, всё украдено до нас ничего делать не надо — URL с указанием языка уже доступен. Но какой-то он длинный, неаккуратный. Хочется сделать покороче. Чтоб не лезть во внутренности OJS, можно исправить настройки сервера. Для случая, когда используется Apache, а адрес журнала имеет вид http://hostname/journal, достаточно добавить пару правил для mod_rewrite:

RewriteRule ^en(glish)?/(\w+)(/?.*)$ /$2/user/setLocale/en_US?source=/$2$3 [L]
RewriteRule ^ru(ssian)?/(\w+)(/?.*)$ /$2/user/setLocale/ru_RU?source=/$2$3 [L]

Это даст возможность использовать URL вида http://hostname/язык/journal/путь, где язык может быть как названием нужного языка, так и его двухбуквенным кодом. Для уже рассмотренной серии «Вестника ЮУрГУ» теперь можно применять такие ссылки: