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

Как совместить RewriteRule index.php и перезапись запросов и избежать ошибки сервера 404?

Оба RewriteRule работают нормально, кроме случаев, когда они используются вместе.

1. удалить все запросы кроме запроса ?callback=.*:

# /api?callback=foo       has no rewrite
# /whatever?whatever=foo  has 301 redirect  /whatever
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /([^?#\ ]*)\?[^\ ]*\ HTTP/ [NC]
RewriteCond %{REQUEST_URI}?%{QUERY_STRING} !/api(/.*)?\?callback=.*
RewriteRule .*$ %{REQUEST_URI}? [R=301,L]

2. перепишите index.php запросы api и url=$1:

# /api           returns data  index.php?api&url=
# /api/whatever  returns data  index.php?api&url=whatever
RewriteRule ^api(?:/([^/]*))?$ index.php?api&url=$1 [QSA,L]
RewriteRule ^([^.]*)$ index.php?url=$1 [QSA,L]

Любая допустимая комбинация этого правила RewriteRule для сохранения его функциональности?

Эта комбинация вернет ошибку сервера 404 в / api /? callback = foo:

# Remove all queries except query "callback"
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /([^?#\ ]*)\?[^\ ]*\ HTTP/ [NC]
RewriteCond %{REQUEST_URI}?%{QUERY_STRING} !/api(/.*)?\?callback=.*
RewriteRule .*$ %{REQUEST_URI}? [R=301,L]

# Rewrite index.php queries
RewriteCond %{REQUEST_URI}?%{QUERY_STRING} !/api(/.*)?\?callback=.*
# Server Error 404 on /api/?callback=foo and /api/whatever?callback=foo
RewriteRule ^api(?:/([^/]*))?$ index.php?api&url=$1 [QSA,L]
RewriteCond %{REQUEST_URI}?%{QUERY_STRING} !/api(/.*)?\?callback=.*
RewriteRule ^([^.]*)$ index.php?url=$1 [QSA,L]

Включить RewriteRule для index.php, необходимо добавить исключения при перезаписи запроса.

Эти правила работают нормально и устраняют эту проблему:

# Remove question mark and parameters
RewriteCond %{QUERY_STRING} .+
# Query rewrite exceptions
RewriteCond %{REQUEST_FILENAME} !index.php
RewriteCond %{REQUEST_URI}?%{QUERY_STRING} !/api(/.*)?\?callback=.*
RewriteRule .*$ %{REQUEST_URI}? [R=301,L]

# index.php query rewrite
RewriteRule ^api(?:/([^/]*))?$ index.php?api&url=$1 [QSA,L]
RewriteRule ^([^.]*)$ index.php?url=$1 [QSA,L]

Думаю, мне нужно это объяснить после трех комментариев с просьбой удалить ! из вашего состояния:

# Rewrite index.php queries
RewriteCond %{REQUEST_URI}?%{QUERY_STRING} !/api(/.*)?\?callback=.*
# Server Error 404 on /api/?callback=foo and /api/whatever?callback=foo
RewriteRule ^api(?:/([^/]*))?$ index.php?api&url=$1 [QSA,L]

Это ваше правило, которое, по-видимому, пытается справиться с /api запросы, и вот что происходит:

  1. Вы просите /api?callback=foo
  2. Проверить по условию RewriteCond %{REQUEST_URI}?%{QUERY_STRING} !/api(/.*)?\?callback=.*
  3. Не совпадает, потому что /api?callback=foo не совпадает !/api(/.*)?\?callback=.*. В ! говорит "URI НЕ ДОЛЖЕН БЫТЬ / api`
  4. Правило заканчивается, ничего не происходит, потому что условие не выполняется

Другой пример

  1. Вы просите /blah/
  2. Проверить по условию RewriteCond %{REQUEST_URI}?%{QUERY_STRING} !/api(/.*)?\?callback=.*
  3. Условие совпадает, потому что /blah не является /api?callback=
  4. Попробуйте применить правило RewriteRule ^api(?:/([^/]*))?$ index.php?api&url=$1 [QSA,L]
  5. Правило не работает, потому что регулярное выражение говорит: URI ДОЛЖЕН НАЧАТЬ С / api, поскольку URI /blah, правило не применяется, ничего не происходит.

Итак, как видите, несмотря ни на что, ваше правило никогда ничего не сделает. Вам нужно изменить свое состояние, чтобы оно не сводило на нет /api, так как ВЫ ХОТИТЕ / api, в этом весь смысл правила. Просто сопоставьте строку запроса:

RewriteCond %{QUERY_STRING} callback=
RewriteRule ^api(?:/([^/]*))?$ index.php?api&url=$1 [QSA,L]

Просто удалите ! достаточно хорошо, но это избыточно, потому что вы сопоставляете /api в любом случае в правиле:

# This works too
# Look! no more ! here -------------------v
RewriteCond %{REQUEST_URI}?%{QUERY_STRING} /api(/.*)?\?callback=.*
RewriteRule ^api(?:/([^/]*))?$ index.php?api&url=$1 [QSA,L]