REQUEST_URI не соответствует явному пути и имени файла

Действительно в тупике, потому что форма и синтаксис кажутся прекрасными.

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

пытаясь получить окончательный тест. Испытательная установка:

  • testmee.txt не существует
  • запрос для testmee.txt в корне
  • проверил, что request_uri соответствует, перенаправив на google
  • не может получить 410 при использовании только первого Cond
  • (при использовании только первого Cond сервер обслуживает 404, а не 410)
  • (используя оба Conds, сервер обслуживает 404, а не 410)
  • МОЖЕТ получить 410 при использовании только второго Cond
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 в зависимости от типа файла, но другого объяснения я не вижу. Я мог бы покопаться в этом и, возможно, найти место в контроллерах, которое это делает. Однако надо сделать перерыв.

Есть ли у вас какие-либо другие директивы mod_rewrite в этом .htaccess файле?

MrWhite 31.05.2019 01:14

Да много. Казалось, что если я поставлю это вверху, то флаг Last завершит обработку для этого прохода, вернет 410 и не сделает дополнительный проход через htaccess, потому что не было сделано подстановки. Если REQUEST_FILENAME совпало нормально и сразу же сработало таким образом, то REQUEST_URI (сам по себе с RewriteRule) тоже должен совпасть, 410, стоп, не так ли? Даже в такой изоляции REQUEST_URI не будет совпадать. Одна вещь: если я попаду в совершенно пустой обычный файл (например, testme.txt в корне), сервер направит его на результат 404. Это может быть связано с этим?

zzzaaabbb 31.05.2019 02:06

@MrWhite хорошо, я думаю, что сервер может быть неправильно настроен. Не делать поспешных выводов опрометчиво или без тестирования. Я сделал несколько тестов с текстовым файлом в корне сайта, и я могу заставить его соответствовать REQUEST_URI. Происходят странные вещи. При совпадении я могу перенаправить, скажем, на google.com. Затем я меняю результат на «бросок 410», и он выдает 404. Bluehost недавно обновился до apache 2.4.39. У нас может быть какая-то неправильная конфигурация там.

zzzaaabbb 31.05.2019 02:23
"throw a 301" it throws a 304 - Когда вы делаете это, вы устанавливаете строку замена (которая в данном случае будет обязательной) - вы сказали, что она перенаправляет на google.com, в этом случае она должна возвращать 301/2/3? Я дам ответ ... не совсем основательный ответ, но есть что попробовать (слишком много для комментария).
MrWhite 31.05.2019 02:28

да, я понимаю, что вы имеете в виду, говоря о том, что 301 нужна строка подстановки, а не просто флаг. Я также хотел удалить этот комментарий, потому что это мог быть просто правильный неизмененный результат. Я МОГУ заставить его выдать 410, если я использую только второй Cond с несуществующим именем файла, но не могу получить 410 с первым Cond, когда я знаю, что он соответствует (потому что получил его для перенаправления в Google только с совпавшим первое условие). Сервер буквально не хочет выдавать 410 только с совпавшим первым Cond. Сервер, кажется, настаивает на 404 в этом случае.

zzzaaabbb 31.05.2019 02:35
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
5
2 857
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

На самом деле это не надежный ответ, это скорее попытка помочь отладить это и развеять некоторые мифы...

I have verified using phpinfo() that REQUEST_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, а не от другого. Возвращайся сразу же.

zzzaaabbb 31.05.2019 03:11

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

MrWhite 31.05.2019 03:11

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

zzzaaabbb 31.05.2019 03:50

Мне не удалось определить, почему конфигурация сервера или код сайта заставляли директиву ответа «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 - если это намерение), чтобы избежать ненужных проверок файловой системы (которые относительно дорого).

MrWhite 07.06.2019 01:06

Другие вопросы по теме