Действительно в тупике, потому что форма и синтаксис кажутся прекрасными.
RewriteCond для REQUEST_URI не соответствует явному пути и имени файла. В изолированном состоянии RewriteCond для REQUEST_FILENAME отлично подходит. С помощью phpinfo() я проверил, что REQUEST_URI содержит начальную косую черту, а также протестировал ее без косой черты.
Цель здесь состоит в том, чтобы узнать, что запрос относится к этому файлу, и, если он не существует, выдать ошибку 410.
RewriteCond %{REQUEST_URI} ^/dir1/dir2/dir3/v_9991_0726dd5b5e8dd67a214c0c243436d131_all\.css$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ - [R=410,L]
Я не хочу пропускать первый Cond, потому что я хочу сделать это только для нескольких файлов, подобных этому.
ОБНОВЛЕНИЕ I
пытаясь получить окончательный тест. Испытательная установка:
RewriteCond %{REQUEST_URI} ^/testmee\.txt$
#RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ - [R=410,L]
против
#RewriteCond %{REQUEST_URI} ^/testmee\.txt$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ - [R=410,L]
ОБНОВЛЕНИЕ II
Ответ для MrWhite:
угу, тот же симптом. Возможно, придется смириться с тем, что гуглбот выдает ошибку 404 вместо желаемой ошибки 410 для устаревших css/js. Ничего страшного в долгосрочной перспективе, наверное.
Спасибо за тестовое перенаправление request_uri. В этих тестах все работает нормально. Имена страниц и т. д. возвращаются, как и ожидалось, в URL-адресе перезаписи var=.
На данный момент я думаю, что это должна быть какая-то внутренняя обработка ошибок 404, связанных с расширениями типов файлов. Смотрите подсказку ниже. У меня есть программное обеспечение для корзины покупок Prestashop, и оно должно вызывать 404 для типов файлов.
Это перенаправит в Google (чтобы подтвердить соответствие шаблону):
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^testmee\.txt$ http://www.google.com/ [L]
(L flag is needed or else other Rules further down will interfere.)
Это будет продолжать возвращать 404 вместо 410:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^testmee\.txt$ - [NC,R=410]
И в качестве контрольного теста это вернет 410:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^.*$ - [NC,R=410]
Если в приведенном выше неудачном тесте тип файла — css, то мой пользовательский контроллер 404 не вызывается. Я просто получаю простой ответ 404 без пользовательского 404, который обернут всеми шаблонами моего сайта.
Например:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^testmee\.css$ - [NC,R=410]
Боюсь, я потратил впустую часть вашего времени. Мои извенения. Я никогда не думал, что код Prestashop будет вызывать ошибку 404 в зависимости от типа файла, но другого объяснения я не вижу. Я мог бы покопаться в этом и, возможно, найти место в контроллерах, которое это делает. Однако надо сделать перерыв.
Да много. Казалось, что если я поставлю это вверху, то флаг Last завершит обработку для этого прохода, вернет 410 и не сделает дополнительный проход через htaccess, потому что не было сделано подстановки. Если REQUEST_FILENAME совпало нормально и сразу же сработало таким образом, то REQUEST_URI (сам по себе с RewriteRule) тоже должен совпасть, 410, стоп, не так ли? Даже в такой изоляции REQUEST_URI не будет совпадать. Одна вещь: если я попаду в совершенно пустой обычный файл (например, testme.txt в корне), сервер направит его на результат 404. Это может быть связано с этим?
@MrWhite хорошо, я думаю, что сервер может быть неправильно настроен. Не делать поспешных выводов опрометчиво или без тестирования. Я сделал несколько тестов с текстовым файлом в корне сайта, и я могу заставить его соответствовать REQUEST_URI. Происходят странные вещи. При совпадении я могу перенаправить, скажем, на google.com. Затем я меняю результат на «бросок 410», и он выдает 404. Bluehost недавно обновился до apache 2.4.39. У нас может быть какая-то неправильная конфигурация там.
"throw a 301" it throws a 304
- Когда вы делаете это, вы устанавливаете строку замена (которая в данном случае будет обязательной) - вы сказали, что она перенаправляет на google.com
, в этом случае она должна возвращать 301/2/3? Я дам ответ ... не совсем основательный ответ, но есть что попробовать (слишком много для комментария).
да, я понимаю, что вы имеете в виду, говоря о том, что 301 нужна строка подстановки, а не просто флаг. Я также хотел удалить этот комментарий, потому что это мог быть просто правильный неизмененный результат. Я МОГУ заставить его выдать 410, если я использую только второй Cond с несуществующим именем файла, но не могу получить 410 с первым Cond, когда я знаю, что он соответствует (потому что получил его для перенаправления в Google только с совпавшим первое условие). Сервер буквально не хочет выдавать 410 только с совпавшим первым Cond. Сервер, кажется, настаивает на 404 в этом случае.
На самом деле это не надежный ответ, это скорее попытка помочь отладить это и развеять некоторые мифы...
I have verified using
phpinfo()
thatREQUEST_URI
contains the leading slash
Да, переменная сервера REQUEST_URI
Apache действительно содержит начальную косую черту. Он содержит полный URL-путь.
Однако серверная переменная REQUEST_URI
Apache не обязательно совпадает с суперглобальной $_SERVER['REQUEST_URI']
PHP — на самом деле это совсем не одно и то же. Между этими переменными есть некоторые существенные различия (в некотором смысле, возможно, немного жаль, что они имеют одно и то же имя). Примечательно, что PHP superglobal содержит начальный URL-адрес из запроса и включает строку запроса (если есть) и не подвергается %-декодированию. Принимая во внимание, что одноименная переменная сервера Apache содержит переписанный URL (не обязательно запрошенный URL-адрес), не содержит строку запроса и %-декодируется.
Итак, вот почему я спросил, есть ли у вас другие директивы mod_rewrite. У вас вполне мог быть конфликт. Если другая директива переписывает URL-адрес, то условие никогда не будет соответствовать (несмотря на то, что суперглобальный PHP предполагает, что так и должно быть).
It seemed that if I put this at the top, the Last flag would end processing for that trip through, return the 410
Эта директива, безусловно, должна находиться в верхней части файла .htaccess
, чтобы избежать перезаписи URL-адреса ранее. Флаг L
на самом деле лишний при использовании с R=410
(любым, кроме 3xx
) — в данном случае он подразумевается.
Then I change the result to be "throw a 410" and it throws a 404.
Это, безусловно, может быть вызвано переопределением на стороне сервера. Но вы можете выбросить 410 в других ситуациях, так что это, кажется, исключает это. Однако вы можете сбросить документ об ошибке в .htaccess
, если сомневаетесь (если вы уже не используете собственный документ об ошибке):
ErrorDocument 410 default
RewriteCond %{REQUEST_URI} ^/dir1/dir2/dir3/v_9991_0726dd5b5e8dd67a214c0c243436d131_all\.css$ RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)$ - [R=410,L]
Хотя это на самом деле не влияет на поведение правила, вам не нужна первая директива RewriteCond
, которая проверяет соответствие REQUEST_URI
. Вместо этого вы должны выполнять эту проверку в RewriteRule
шаблон (что будет более эффективно, поскольку оно обрабатывается первым). Например:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^dir1/dir2/dir3/v_9991_0726dd5b5e8dd67a214c0c243436d131_all\.css$ - [NC,R=410]
Флаг NC
должен быть лишним.
Тем не менее, конфликт с существующими директивами является наиболее вероятной причиной. Удалите все остальные директивы. Вы все еще видите такое же поведение?
Вы можете проверить значение серверной переменной REQUEST_URI
. Вы можете либо выполнить перенаправление и передать REQUEST_URI
в качестве параметра URL-адреса, либо установить переменные среды (но вам нужно будет искать REDIRECT_<var>
для каждой перезаписи).
Например, вверху вашего .htaccess
(или там, где вы пытаетесь это сделать):
RewriteCond %{QUERY_STRING} ^$
RewriteRule ^ /test.php?var=%{REQUEST_URI} [NE,R,L]
Создан фиктивный файл test.php
, чтобы избежать внутреннего подзапроса к документу об ошибке.
Спасибо за ваше время, усилия и вдумчивый ответ. Да, у меня есть пользовательская директива ErrorDocument, и поэтому я не хочу вмешиваться в нее, особенно для этой маленькой проблемы. Да, позвольте мне проверить правило на соответствие входящего шаблона. Это, безусловно, может решить эту проблему. Позвольте мне изучить все остальное, что вы сказали, а также взглянуть на параллельный тест, который я провел с уверенностью, что request_uri соответствует. Странно, что сервер отказался от одного метода получения 410, а не от другого. Возвращайся сразу же.
Я обновил свой ответ небольшим количеством кода, чтобы проверить значение переменной Apache.
MrWhite, результаты выше. Я боюсь, что я застрял с поведением, но с другой стороны, это не так уж важно. Еще раз спасибо за ваше время и знания.
Мне не удалось определить, почему конфигурация сервера или код сайта заставляли директиву ответа «410 Gone» в htaccess быть переопределенной ответом 404, поэтому мне пришлось сделать что-то вроде это, чтобы сообщить роботу Googlebot, чтобы он прекратил поиск файлов CSS/JS, которые очищаются. периодически (и переименовывается при регенерации).
в .htaccess:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule v_(.*)_(.*)$ /410response.php [L]
в 410response.php, помещенном в корень:
<?php header($_SERVER['SERVER_PROTOCOL'].' 410 Gone');
ОБНОВЛЕНИЕ I
Ответ 404 при попытке использовать htaccess для директивы 410 был принудительно вызван сервером из-за того, что сервер, по-видимому, имел пользовательский документ 410, который, по-видимому, перенаправлялся на 404. Добавление директивы для предотвращения того, чтобы затем правильно разрешить использование htaccess для возврата 410 для совпадений с образцом в RewriteRule. (Я думал, что я уже проверил вчера, чтобы увидеть, будет ли это работать, поскольку @MrWhite сказал в своем ответе выше, чтобы контролировать сервер, возможно, имеющий пользовательский 410; сегодня, когда я делал эту проверку, он действительно работал и указывал, что сервер 410-to Перенаправление -404 переопределяло мою директиву 410.)
ErrorDocument 410 default
RewriteRule test\.txt$ - [NC,R=410]
Мистер Уайт! Я нашел это решение в один из ваших постов на Stack Exchange.
Спасибо за ответ. Небольшой момент: директива RewriteCond ... !-d
в вашем блоке правил, вероятно, излишняя, если только у вас нет каталогов, соответствующих регулярному выражению v_(.*)_(.*)$
? Хотя вы должны убедиться, что это регулярное выражение является как можно более конкретным (например, соответствует только запросам .css
или .js
- если это намерение), чтобы избежать ненужных проверок файловой системы (которые относительно дорого).
Есть ли у вас какие-либо другие директивы mod_rewrite в этом
.htaccess
файле?