Не могу использовать скобки в RewriteCond QUERY_STRING - PullRequest
1 голос
/ 22 апреля 2020

Перемещено из https://serverfault.com/questions/1013461/cant-use-parentheses-in-rewritecond-query-string, потому что здесь топи c.


Мне нужно захватить UID из старого URL и перенаправить его в новый формат.

example.com/?uid=123 следует перенаправить на example.com/user/123

Что должно работать:

RewriteCond %{QUERY_STRING} ^uid=(\d+)$
RewriteRule ^$ /user/%1? [L]

Это вообще не перенаправляет.

Однако это делает:

RewriteCond %{QUERY_STRING} ^uid=\d+$
RewriteRule ^$ /user/%1? [L]

Идет к example.com/user. UID не указан, но он перенаправляет.

Примечание: все, что я сделал, это удалил скобки во втором примере.

Почему это ?? Как я могу сопоставить запрос И захватить значение UID?


Обновления

Это приложение laravel. Я обнаружил, что редиректы, которые я видел, могли поступать из приложения, а не Apache.

Самооценка скоро ...

Временное добавление R = 302 дает желаемый результат:

RewriteCond %{QUERY_STRING} ^uid=(\d+)$
RewriteRule ^$ /user/%1? [L,R=302]

Это, конечно, отправляет перенаправление 302 на /users/123. Хотелось бы посмотреть, можно ли это сделать с помощью внутренней перезаписи ...

Вот некоторые правила в laravel по умолчанию .htaccess:

# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]

Это ловит пути, которые не указывают на реальные файлы, а указывает на приложение laravel. Когда это удалено, Apache отвечает 404 для /users/1234.

https://httpd.apache.org/docs/2.4/rewrite/flags.html#flag_l

Такое переписывание восходит к Apache Парсер URL. Затем .htaccess снова обрабатывается (так как он все еще применим к этому новому URL). В этот момент я ожидаю, что приведенные выше правила подберут несуществующий путь и укажут его приложению laravel ...

Найден. Пишу ответ сейчас.

1 Ответ

1 голос
/ 22 апреля 2020

Ответ

MrWhite был прав. Вы должны добавить R=302 или R=301, чтобы выполнить перенаправление. Обычная перезапись не будет работать.

RewriteCond %{QUERY_STRING} ^uid=(\d+)$
RewriteRule ^$ /user/%1? [L,R=302]

Причина

Итак, способ Laravel работает так:

  • вы запрашиваете /some/file
  • .htaccess сообщает apache, "эй apache, если у вас есть запрос на файл, который не существует, просто сделайте вид, что он для index.php"
  • apache говорит: «эй php, у меня есть запрос на запуск index.php, а URL-адрес /some/file»
  • php запускает скрипт, который --whoah - это огромное laravel приложение
  • что угодно, "эй laravel, сервер сказал /some/file - это URL"
  • laravel делает все свои причудливые вещи, и это пытается сопоставить URL с одним из ваших маршрутов

Теперь я добавил правило для перезаписи определенного URL на виртуальный URL, который Laravel должен обрабатывать. Я сопоставлял параметры запроса, но это не имело значения. (подробности см. ниже)

Когда модуль перезаписи Apache обнаруживает RewriteRule без флага [R], он перезаписывает URL-адрес и отправляет его обратно в обработчик URL-адресов. Затем обработчик URL-адреса Apache обрабатывает новый URL-адрес в соответствии со всеми правилами, в том числе в любых применимых файлах .htaccess.

Таким образом, все надлежащие правила did применяются.

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

Поэтому мы должны указать Apache отправить ответ 301 или 302 Redirect, вместо того, чтобы просто переписать запрос . Пользователь отправит еще один запрос с URL-адресом, который необходим Laravel для разрешения маршрута.


Но как быть с другим поведением с / без скобок?

Ответ лежит в пределах Laravel по умолчанию .htaccess. Давайте посмотрим мои старые правила без скобок:

RewriteCond %{QUERY_STRING} ^uid=\d+$
RewriteRule ^$ /user/%1? [L]

Без скобок, чтобы получить значение uid, %1 пусто. Таким образом, мы в конечном итоге переписываем URL просто на /user/.

Теперь нам нужно взглянуть на другой набор Laravel правил:

RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R=301]

Это нормализует URL, так что виртуальные пути / маршруты не содержат конечных слешей. Это облегчает анализ маршрута.

Возвращает 301 Redirect для `/ users '. Это очень отличается от 200, которые мы получали с круглыми скобками, но это не значит, что круглые скобки вели себя по-другому. Как сказал г-н Уайт в комментариях, наверняка этим занимался кто-то другой.

Надеюсь, вам понравилась поездка. И я еще больше надеюсь, что это спасет бедную, растерянную душу от часов мучений. :)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...