Apache 2.4 Конвертируйте .htaccess и перепишите его в vhost.conf

Apache 2.4 Конвертируйте .htaccess и перепишите его в vhost.conf

Я переписываю конфигурацию Apache 2.4, полученную от старой команды разработчиков.

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

RewriteCond %{QUERY_STRING} ^$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteCond %{REQUEST_URI} !^/application-module/(.*)$
RewriteCond %{REQUEST_URI} !(.*)json$ [NC]
RewriteCond %{REQUEST_URI} !playground/local-loader/(.*)$ [NC]
RewriteRule ^(.*)$ /$1/ [R,L,NC]

Когда я просто перемещаю его на виртуальный хост, мой сайт падает в непонятных мне местах.

решение1

Это зависит от того, в какое место <VirtualHost>контейнера вы поместите эти директивы.

Если вы используете <Directory>контейнер (т.е.каталогконтекст) иотключение .htaccessпереопределяет полностью (иначе .htaccessбудет переопределен <Directory>контейнер!), то вы можете фактически скопировать директивы как есть (предполагая, что <Directory>контейнер ссылается на тот же каталог, что .htaccessи файл).

Однако, если вы помещаете эти директивы непосредственно внутрь <VirtualHost>контейнера (вне контейнера <Directory>), т. е. ввиртуальныйхостcontext, то вам нужно внести некоторые изменения. Это связано с тем, что директивы обрабатываются раньше, до того, как запрос будет сопоставлен с файловой системой.

В опубликованных вами директивах необходимо внести только два изменения:

  • Ввиртуальныйхостконтекст, REQUEST_FILENAMEпеременная сервера еще не была преобразована вимя файла. Это то же самое, что REQUEST_URI(т. е. запрашиваемый URL). Таким образом, проверка вашей файловой системы всегда будет неудачной, а условие всегда будет успешным! Вам нужно либо использовать предпросмотр, например, %{LA-U:REQUEST_FILENAME}, либо самостоятельно создать абсолютное имя файла, например, %{DOCUMENT_ROOT}%{REQUEST_URI}. Например:

    RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f
    
  • Ввиртуальныйхостконтекст, URL-путь, который соответствуетRewriteRule шаблонявляется корневым (начинается со слеша). Тогда как в .htaccessон является относительным к каталогу, содержащему .htaccessфайл - без префикса слеша. Таким образом, правило в том виде, в котором оно написано, приведет к двойному слешу в начале URL-пути, его следует переписать следующим образом:

    RewriteRule ^/(.*)$ /$1/ [R,L]
    

    ( NCФлаг здесь не требуется.)

    Или (предпочтительнее) не используйте здесь обратную ссылку, а REQUEST_URIвместо этого используйте переменную сервера (что, естественно, тоже сработает .htaccess). Например:

    RewriteRule ^ %{REQUEST_URI}/ [R,L]
    

    (В стороне:Вероятно, это также должно быть постоянное перенаправление 301 (т. е. R=301). В текущем виде по умолчанию будет установлено временное перенаправление 302. Но меняйте его на 301 — если это и есть намерение — только после того, как убедитесь, что оно работает так, как задумано.)

Итак, вкратце, это будет выглядеть так:

RewriteCond %{QUERY_STRING} ^$
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteCond %{REQUEST_URI} !^/application-module/(.*)$
RewriteCond %{REQUEST_URI} !(.*)json$ [NC]
RewriteCond %{REQUEST_URI} !playground/local-loader/(.*)$ [NC]
RewriteRule ^/(.*)$ /$1/ [R,L]

В стороне:

Вышеизложенное можно сразу немного оптимизировать, переместив проверку файловой системы (которая относительнодорогой) к последнему условию и перемещениесостояниекоторый проверяет, что запрос не заканчивается косой чертой в RewriteRuleдирективе. Также, подшаблоны регулярных выражений (.*)в каждом изусловияне требуются. Таким образом, вышесказанное можно переписать более эффективно:

RewriteCond %{QUERY_STRING} ^$
RewriteCond %{REQUEST_URI} !^/application-module/
RewriteCond %{REQUEST_URI} !json$ [NC]
RewriteCond %{REQUEST_URI} !playground/local-loader/ [NC]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f
RewriteRule !/$ %{REQUEST_URI}/ [R,L]

Проверку файловой системы, возможно, можно вообще убрать, если вместо этого исключить запросы, содержащие (что-то похожее) расширение файла, но это может зависеть от структуры вашего файла.

Theсостояниеэта проверка !json$выглядит так, как будто она действительно должна проверять .jsonрасширение файла, т. е. !\.json$. (Это связано с моим комментарием выше об исключениивсезапросы, имеющие «расширение файла».)

Первыйсостояниепроверка того, что строка запроса пуста, кажется немного странной (поскольку на самом деле не имеет значения, есть ли строка запроса или нет при добавлении слеша к URL-пути), но я предполагаю, что это должно быть конкретное требование?

Связанный контент