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

htaccess RewriteRule приводит к ответу 404

У меня есть сайт, который находится в корневой папке. Оно имеет .htaccess с кодом ниже:

RewriteEngine on
RewriteRule ^(.*)/$ $1.php

Когда я открываю http://example.com/login/ Я получаю сообщение об ошибке «404 Not Found», но когда открываю http://example.com/login без следа / URL открывается без проблем.

я нуждаюсь .htaccess код, который нужно установить в корневом каталоге, чтобы открыть файл PHP, например login.php так как /login/ или /login (без конечных /).

Такое поведение типично для конфликта с MuiltiViews. Вы должны отключить MultiViews в верхней части вашего .htaccess файл:

Options -MultiViews

Это объясняет, почему /login без следа / успешно обслуживает файл - ваш RewriteRule полностью игнорируется в этом сценарии.

При включенных MultiViews при запросе /login/, mod_negotiation создает макет карты перезаписи и выдает внутренний подзапрос для /login.php до того, как mod_rewrite обработает URL. Информация о пути (конечный /) добавляется обратно, чтобы стать /login.php/. Он передается для дальнейшей обработки и соответствует вашему слишком общему (^(.*)/$) RewriteRule шаблон, что привело к внутренней перезаписи на /login.php.php/ и т.д. В зависимости от вашей конфигурации это может привести к 403 (поскольку это может привести к искаженному запросу) или 404 (как вы, кажется, видите).

Отключение только MultiViews (как упоминалось выше) решит эту проблему. Однако вам также следует подумать о том, чтобы RewriteRule шаблон более спокойный. Например, чтобы избежать совпадения URL-адресов, которые уже содержат точку (т. Е. Имеют расширение файла):

RewriteRule ^([^.]+)/$ $1.php [L]

Если просто сделать регулярное выражение более строгим, это может даже «исправить» ошибку. Однако это будут MultiViews, выполняющие внутренний подзапрос, а не mod_rewrite (ваше правило просто будет обойдено).

так как /login/ или /login (с завершающим /)

Чтобы правило могло работать с /login/ или /login (то есть с косой чертой в конце или без) вам нужно будет сделать конечную косую черту необязательной, т.е. /?. Но вам также нужно будет либо сделать предыдущий шаблон не жадным, либо включить косую черту в класс инвертируемых символов, чтобы избежать захвата конечной косой черты в обратной ссылке.

Например, либо:

RewriteRule ^([^.]+?)/?$ $1.php [L]

Или,

RewriteRule ^([^./]+)/?$ $1.php [L]

Но второе правило будет работать только с URL-адресами, содержащими один сегмент пути, тогда как первое будет работать с URL-адресом формы /foo/bar/login.

В итоге

Options -MultiViews

RewriteEngine On
RewriteRule ^([^.]+?)/?$ $1.php [L]

Пытаться ^([^/]+)/?$ и посмотрите, работает ли он так, как ожидалось.