Недавно я настроил перезапись, чтобы по возможности вместо файлов .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.
Некоторые другие заметки:
RewriteCond %{DOCUMENT_ROOT}/%1.webp_asdfasdfasf -f
просто чтобы убедиться, что оно действительно не сработает, и оно сработало. Таким образом, он знал, что полностью фальшивого файла не существует, но все еще думал, что файл .webp существует. 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
(без базового имени) в корне документа? (И / или вы видите кэшированное перенаправление для некоторых запросов? См. Ниже ...)
Обратная ссылка % 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-файлы постоянно кэшируются браузером, поэтому позже могут возникнуть проблемы с кешированием. (Фактически, этим можно объяснить "прерывистое" поведение, когда запрос попадает в кеш браузера.)