^ персонаж не работает при перезаписи мода в htaccess

У меня очень неприятная проблема с правилами перезаписи в файле .htaccess.

Контекст

Итак, я хочу, чтобы эти два типа URL-адресов переписывались для разных целей:

URL 1 -- http://example.com/rem/call/answer/{Hex String}/{Hex String}/
URL 2 -- http://example.com/answer/{Hex String}/{Hex String}/

Это выдержка из моего файла .htaccess:

RewriteEngine On
RewriteRule rem/call/answer/([a-f0-9]+)/([a-f0-9]+)/?$ /TARGET1
RewriteRule answer/([a-f0-9]+)/([a-f0-9]+)/?$ /TARGET2

Проблема

Теперь проблема в том, что URL 2 хорошо переписывается (с использованием правила #2) и переходит к TARGET 2, но URL 1 strong> перезаписывает оба правила, а не только правило №1.

Я попробовал несколько решений, в том числе очевидное использование символа ^ для начала строки. На тот момент мои правила перезаписи были такими:

RewriteEngine On
RewriteRule rem/call/answer/([a-f0-9]+)/([a-f0-9]+)/?$ /TARGET1
RewriteRule ^answer/([a-f0-9]+)/([a-f0-9]+)/?$ /TARGET2

Однако случилась другая проблема. На этот раз это URL 1, который хорошо переписывается, только с правилом #1 и переходит к TARGET 1. Но теперь URL 2 вообще больше не перезаписывается. Я предполагаю, что это потому, что второе правило перезаписи никогда не соответствует никакому URL-адресу и, следовательно, никогда не применяется.

Единственное решение, которое я нашел до сих пор, это удалить ^ и использовать флаг [L] в конце правила №1, например так:

RewriteEngine On
RewriteRule rem/call/answer/([a-f0-9]+)/([a-f0-9]+)/?$ /TARGET1 [L]
RewriteRule answer/([a-f0-9]+)/([a-f0-9]+)/?$ /TARGET2

Таким образом, он использует правило № 1, соответствует, но никогда не достигает правила № 2. Оба URL-адреса правильно переписываются с этими правилами, но это не очень хорошее решение, так как я, возможно, не захочу останавливать перезапись URL 1 после применения первого правила (что, если у меня есть третье правило, я бы тоже хочу к ней обратиться...)


Мои вопросы к вам

Теперь, когда я изложил проблему, мои вопросы:

  1. Является ли флаг [L] единственным выходом? (в чем я очень сомневаюсь и, конечно, надеюсь, что нет)
  2. Будет ли ^ подходящим решением? (Я так думаю)
  3. Если да, то как заставить его работать и почему он вообще не работает в моем случае?

Что я подозреваю

Я подозреваю, что это как-то связано с тем фактом, что URL-адрес на самом деле http://example.com/answer/{Hex String}/{Hex String}/, а не просто answer/{Hex String}/{Hex String}/, что означает, что answer/.. на самом деле не находится в начале строки, и, таким образом, префикс ^ не работает.

Но тогда это подводит меня к другому вопросу:

Как указать apache удалить URL-адрес части схемы + домена (например, http://example.com/) и сопоставить правила только с остальной частью URL-адреса (например, answer/{Hex String}/{Hex String}/)?


РЕДАКТИРОВАТЬ

Я также должен добавить, что я пробовал базовый пример Алисы-Боба. У меня есть файл с именем bob.html в моем корне и следующее правило в моем файле .htaccess:

RewriteRule alice.html$ /bob.html

Это прекрасно работает и отображает страницу bob.html при запросе alice.html. Однако, если я изменю правило на:

RewriteRule ^alice.html$ /bob.html

Затем я получаю ошибку 404 при запросе страницы alice.html...

Что касается комментария @anubhava, мой полный файл .htaccess составлен следующим образом:

RewriteEngine On

[A bunch of RewriteRule that have nothing to do with the topic at hand
(don't contain any "answer" string in them and all work perfectly)]

RewriteRule rem/call/answer/([a-f0-9]+)/([a-f0-9]+)/?$ /TARGET1 [L]
RewriteRule answer/([a-f0-9]+)/([a-f0-9]+)/?$ /TARGET2

ErrorDocument 404 /404.html
Header set Access-Control-Allow-Origin "*"
SetEnv file_uploads On

person Dolma    schedule 03.09.2015    source источник
comment
из любопытства, а в МИШЕНЯХ есть ответ?   -  person Jon Lin    schedule 03.09.2015
comment
Хм ... что вы подразумеваете под ответом ?   -  person Dolma    schedule 03.09.2015
comment
Есть ли в нем строка answer. ДЛЯ примера: RewriteRule ^answer/(.*)$ /some/path/answer/foo.php? Появляется ли строковый ответ в цели вашего правила?   -  person Jon Lin    schedule 03.09.2015
comment
Да, он перенаправляет на страницу answer.php с двумя захваченными шестнадцатеричными кодами в строке запроса. Кстати, я отредактировал свой вопрос, добавив детали, которые заставляют меня поверить, что это не проблема (или только одна из них).   -  person Dolma    schedule 03.09.2015
comment
@JonLin На самом деле, я исправлен, я перепутал это с другим правилом. В первом правиле на самом деле нет "answer". А у второго что-то вроде "redirect-answer.php?...". Так что я действительно думаю, что проблема исходит откуда-то еще. Где вы думаете о каком-то закольцованном переписывании?   -  person Dolma    schedule 03.09.2015
comment
@anubhava Я отредактировал свой вопрос, добавив структуру моего полного файла .htaccess.   -  person Dolma    schedule 03.09.2015
comment
@anubhava Да, как я уже упоминал Джону Лину, правило № 2, которое я упоминаю в посте, переписывается на redirect-answer.php (цель 2). И файл .htaccess находится в корневом каталоге выше моего каталога www. Меня до сих пор беспокоит, почему даже простой тест Алисы-Боба не сработал...   -  person Dolma    schedule 03.09.2015
comment
Да RewriteRule ^alice.html$ /bob.html должно работать. Разве он не должен находиться в каталоге www?   -  person anubhava    schedule 03.09.2015
comment
@anubhava Тьфу ... ты прав, так и должно быть ... Я помню, что давным-давно проверил, когда впервые настроил свой файл .htaccess, и я прочитал в Интернете, что я должен поместить его над www. До сих пор все работало хорошо, поэтому я не сомневался в этом. Я только что попытался переместить его в каталог www, и ^ теперь работает как шарм. Я чувствую себя действительно глупо ^^ Что ж, проблема решена, большое спасибо!   -  person Dolma    schedule 04.09.2015


Ответы (1)


Итак, благодаря комментариям @anubhava, я легко решил проблему, переместив файл .htaccess на один уровень вниз в каталог www.

Мне все еще было очень любопытно, почему это решило мою проблему, поэтому я продолжил исследовать, как работает переписывание apache. Я не уверен, что правильно понял все детали, но вот что я узнал.

Местоположение расположение

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

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

  2. Второе, что нужно иметь в виду, это то, что каталог public_html (который в моем случае назывался www, просто символическая ссылка на public_html) является корневой папкой содержимого вашего сайта. У вас может быть доступ к его родительским каталогам, но все, что вы помещаете за пределы своего каталога public_html, не является частью контента вашего веб-сайта как такового, любой ресурс, который вы туда помещаете, не будет частью иерархии вашего веб-сайта (т. е. недоступен через http://example.com/path/to/resource).

  3. Параметр регулярного выражения ^ соответствует началу строки, здесь, в контексте перезаписи URL-адреса, это начало рассматриваемого URL-адреса. И это еще не все, кажется, что Apache разрешает совпадения относительно местоположения вашего файла .htaccess. Это означает, что ^ не только ссылается на начало строки, которую вы написали как часть правила, но фактически ссылается на фактический путь к файлу .htaccess, который действует как «локальный корневой каталог» для всех правил перезаписи в этом конкретном .htaccess файл.


Пример

Допустим, у вас есть подкаталог (например, http://example.com/sub/directory/) и внутри него у вас есть два файла:

http://example.com/sub/directory/.htaccess
http://example.com/sub/directory/bob.html

внутри этого файла .htaccess у вас есть правило перезаписи следующим образом:

RewriteRule ^tom.html$ /sub/directory/bob.html

Это правило не будет соответствовать http://example.com/tom.html, как можно было бы ожидать от ^, а вместо этого будет соответствовать http://example.com/sub/directory/tom.html, так как именно здесь находится файл .htaccess.


Вывод

Вообще говоря, допустим, у вас есть правило перезаписи, такое как:

RewriteRule ^PATH$ /TARGET_PATH

Это означает, что правило не будет сопоставлять URL с ^PATH$, а фактически сопоставит его с ^[Location of the .htaccess file]/PATH$.

Другими словами, местоположение файла .htaccess действует как своего рода базовый URL-адрес для всех правил перезаписи в нем (очень похоже на базовый тег в html).

Вот почему мое правило перезаписи с ^ не работало, так как мой файл .htaccess располагался над каталогом public_html, и этот родительский каталог действовал как базовый URL-адрес для моих правил. Таким образом, правило никогда не будет соответствовать какому-либо URL-адресу, поскольку оно будет сравнивать его с путем, к которому никогда не обращались (потому что он находится выше корня содержимого веб-сайта).

Я надеюсь, что это было достаточно ясно, чтобы помочь любому, кто может столкнуться с той же проблемой, что и я.

Ваше здоровье

person Dolma    schedule 03.09.2015