Почему этот флаг -f возвращает true?

Недавно я настроил перезапись, чтобы по возможности вместо файлов .webp передавались файлы .jpg. Все вроде бы работало правильно, пока сегодня мы не заметили, что недавно загруженное изображение .jpg возвращало 404, хотя изображение присутствовало. Я провел проверку и обнаружил, что сервер переписывает URL .jpg в .webp, а затем получает 404, потому что .webp еще не был создан.

Затем я переместил правило из vhost_ssl.conf в .htaccess и долго возился, пока не нашел что-то работающее, а затем перенес это решение обратно в vhost_ssl.conf. Но я все еще не понимаю, почему первоначальная перезапись иногда не срабатывала. Может ли кто-нибудь просмотреть и пролить свет на эту тему?

Оригинальная перезапись:

RewriteCond %{HTTP_ACCEPT} image/webp
RewriteCond %{DOCUMENT_ROOT}/%1.webp -f
RewriteRule (.+)\.(?:jpe?g|png)$ $1.webp [NC,T=image/webp,E=webp,L]

Окончательная перезапись:

RewriteCond %{HTTP_ACCEPT} image/webp
RewriteCond %{REQUEST_URI} (.+)\.(?:jpe?g|png)$
RewriteCond %{DOCUMENT_ROOT}/%1.webp -f
RewriteRule .* %1.webp [NC,T=image/webp,E=webp,L]

Единственная реальная разница между двумя методами заключается в том, что в новом методе я проверяю, соответствует ли URI запроса jpeg/png перед условием перезаписи, которое проверяет, существует ли файл. Я думаю, что новый метод менее эффективен, так как правило перезаписи соответствует всему, но, по крайней мере, условие выше фильтрует это, и оно находится в vhost_ssl.conf, что лучше, чем .htaccess.

Некоторые другие заметки:

  • Во время тестирования я изменил первоначальную перезапись на 301 редирект, чтобы увидеть файл, который, как мне казалось, был найден. Конечно, это был тот же файл, что и .jpg, только с расширением .webp - правильный путь и все такое (хотя .webp на самом деле не существовало).
  • Также во время тестирования я попробовал изменить условие перезаписи на RewriteCond %{DOCUMENT_ROOT}/%1.webp_asdfasdfasf -fпросто чтобы убедиться, что оно действительно не сработает, и оно сработало. Таким образом, он знал, что полностью фальшивого файла не существует, но все еще думал, что файл .webp существует.
1
задан 28 May 2019 в 23:20
1 ответ

tl; dr

 RewriteCond% {DOCUMENT_ROOT} /% 1.webp -f
 

Это должно быть $ 1 , а не % 1 в RewriteCond TestString . Хотя непонятно, почему это поведение изменилось совсем недавно (а может, и не изменилось?).


 RewriteCond% {HTTP_ACCEPT} image / webp
RewriteCond% {DOCUMENT_ROOT} /% 1.webp -f
RewriteRule (. +) \. (?: jpe? G | png) $ $ 1.webp [NC, T = image / webp, E = webp, L]
 

Это никогда не должно работать, если только у вас не был файл с именем « .webp » (без базового имени , начинающегося с точки) в документе. корень. Если бы вы это сделали, то он бы всегда переписывал URL-адрес jpeg / png на .webp независимо от того, существует он или нет.

Таким образом, это, похоже, предполагает у вас есть файл с именем .webp (без базового имени) в корне документа? (И / или вы видите кэшированное перенаправление для некоторых запросов? См. Ниже ...)

Обратная ссылка % 1 во втором RewriteCond TestString должна быть $ 1 , а не % 1 .% 1 - это обратная ссылка на первую захваченную группу в последнем сопоставленном CondPattern , которого нет, поэтому % 1 всегда ] пусто. Таким образом, он всегда будет проверять существование /path/to/document-root/.webp . $ 1 , с другой стороны, является обратной ссылкой на первую захваченную группу в шаблоне RewriteRule , т.е. путь / базовое имя файловой системы, исключая расширение файла.

Вы использовали $ 1 в RewriteRule подстановке - вы должны были использовать то же самое в предыдущем condition .

Обратите внимание, что если эти директивы находятся в контексте виртуального хоста, вам следует либо ... удалить косую черту в RewriteCond TestString , например:

RewriteCond %{HTTP_ACCEPT} image/webp
RewriteCond %{DOCUMENT_ROOT}$1.webp -f
RewriteRule (.+)\.(?:jpe?g|png)$ $1.webp [NC,T=image/webp,E=webp,L]

ИЛИ исключить косую черту в захваченной группе RewriteRule . Например:

RewriteCond %{HTTP_ACCEPT} image/webp
RewriteCond %{DOCUMENT_ROOT}/$1.webp -f
RewriteRule ^/(.+)\.(?:jpe?g|png)$ /$1.webp [NC,T=image/webp,E=webp,L]

В противном случае вы получите двойную косую черту в TestString , которую ОС должна будет разрешить.

 RewriteCond% {HTTP_ACCEPT} image / webp
RewriteCond% {REQUEST_URI} (. +) \. (?: jpe? G | png) $
RewriteCond% {DOCUMENT_ROOT} /% 1.webp -f
RewriteRule. *% 1.webp [NC, T = image / webp, E = webp, L]
 

Этим достигается то же самое, что и при простом использовании $ 1 в исходном блоке правил (как упомянуто выше). Любопытно, что вы изменили обратную ссылку в подстановке на % 1 , но знали, что нужно оставить обратную ссылку в условии без изменений (или это просто упустили из виду)?

Во время тестирования я изменил исходную перезапись на 301 редирект ...

Всегда проверяйте с 302 (временными) перенаправлениями. 301-файлы постоянно кэшируются браузером, поэтому позже могут возникнуть проблемы с кешированием. (Фактически, этим можно объяснить "прерывистое" поведение, когда запрос попадает в кеш браузера.)

2
ответ дан 3 December 2019 в 20:07

Теги

Похожие вопросы