Недавно выкатил очередные доработки на продакшен-сайт (версия Drupal 8.6.2), и через некоторое время случайно заметил в консоли хрома целую кучу сообщений такого вида при отображении галерей картинок:
GET http://***/sites/default/files/styles/gallery_thumbnail/public/*.jpg 404 (Not Found)
При этом сами стилизованные картинки в галерее отображаются совершенно нормально, на закладке Network видно, что они отдаются нормального размера, только почему-то с кодом 404. Выявил, что не все картинки в галерее отдаются с кодом 404, а только часть, остальные с кодом 200. Далее выявил, что с кодом 404 отдаются те картинки, для которых нужный стиль еще не сгенерен на момент запроса. То есть веб-сервер действительно не находит нужную картинку в папке styles, далее запускает друпал для обработки ошибки 404, друпал исправно генерит стилизованную картинку, кладет ее куда надо и отдает клиенту, но почему-то с кодом 404.
Самое смешное, что другие браузеры (IE11, Firefox) все эти ошибки даже на консоль не выводят, просто показывают картинки и всё, то есть эти ошибки видно только в консоли хрома, ну и в логах веб-сервера если их под микроскопом разглядывать.
В связи с этим я даже не уверен, что это появилось только сейчас - просто сейчас появился новый стиль галереи и к нему новый стиль картинок, и естественно для десятков тысяч картинок, уже имеющихся на сайте, стилизованных картинок в этом стиле нет, поэтому при отображении новых галерей идет массовая генерация стилизованных картинок. Раньше сайт был так устроен, что при добавлении новой картинки, практически сразу генерились и все стили к ней, то есть если ошибки 404 и возникали, то я их мог просто не замечать.
При этом на дев-сайте (версия 8.5.2, хостинг тот же) ничего подобного не наблюдается - вновь генерируемые картинки отдаются с кодом 200, как и ранее сгенеренные.
Поломав немножко над этим голову, я вспомнил, что год назад уже воевал со стилями картинок, правда немножко в другой ситуации:
http://dru.io/question/8905
Тогда я так и не понял, в чем было дело, просто нашел затычку и успокоился. Не знаю связано ли тогдашняя проблема с сегодняшней или нет. Попробовал убрать затычку из settings.php - стилизованные картинки вообще не генерируются, причем даже если убрать из .htaccess защиту от хотлинкинга!
Собственно вопрос: может быть кто-нибудь сталкивался с подобным, или интимно знаком с той частью потрохов Друпала, которая отвечает за image styles? Куда копать-то? Или забить?
Стилизованные картинки нормально генерятся и отдаются, но с кодом 404
Главные вкладки
Лучший ответ
В общем, перетащил все нужные мне директивы (явно прописав пути) в корневой .htaccess, всё работает как надо и без ошибок. А почему оно так было - пусть останется загадкой
Комментарии
"Далее выявил, что с кодом 404 отдаются те картинки, для которых нужный стиль еще не сгенерен на момент запроса."
Ну да. Пока на страницу не зайдешь, миниатюра в папке стиля не сгенерируется. Как варинт указать стиль изображения используемый при редактирвании ноды. Это в настройках поля картинки.
Всё верно, но зачем свежесгенерированная картинка отдается с кодом 404? Причем на одном сайте из двух?
Как вариант чего? Какую проблему это решает?
скорее всего что-то с настройками вэб-сервера..
Настройки вэб-сервера на обоих сайтах сильно отличаются?
Вероятнее всего проблема в конфигурации веб сервера всё же. Особенно, если там есть что-то нестандартное. Возможно, не правильно интерпретируется отсутствие файла на месте, и отдаётся 404 в случае передачи запроса к обработчику php, вне зависимости от его ответа.
Давайте её посмотрим.
Да.. обычно в такой конфигурации:
и никаких проблем с картинками не бывает.. совсем..
(задумчиво) а стоит ли панель управления хостингом и если да - случаем не virtualmin?
не, там cPanel и я бы не спешил с выводами
Отвечу на все вопросы сразу:
Панель управления хостингом - cPanel, хостинг один и тот же, сервер - Apache.
Вот - весь /sites/default/files/.htaccess от прод-сервера, где проблема есть:
Options -Indexes -ExecCGI -Includes -MultiViews
# Set the catch-all handler to prevent scripts from being executed.
SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006
<Files *>
# Override the handler again if we're run later in the evaluation list.
SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003
</Files>
# If we know how to do it safely, disable the PHP engine entirely.
<IfModule mod_php5.c>
php_flag engine off
</IfModule>
RewriteEngine on
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http(s)?://([^.]+\.)?nouveau\.world [NC]
RewriteCond %{HTTP_REFERER} !^http(s)?://([^.]+\.)?google\. [NC]
RewriteCond %{HTTP_REFERER} !^http(s)?://([^.]+\.)?yandex\. [NC]
RewriteCond %{HTTP_REFERER} !^http(s)?://([^.]+\.)?facebook\. [NC]
RewriteRule \.(jpg|jpeg|png|gif)$ http://art.nouveau.world/nohotlinking.jpg [R,L]
RewriteCond %{HTTP_USER_AGENT} ^(.*)bingbot(.*)$ [NC]
RewriteRule .* - [R=403,L]
Вот весь /sites/default/files/.htaccess от дев-сервера, где проблемы нет:
Options -Indexes -ExecCGI -Includes -MultiViews
# Set the catch-all handler to prevent scripts from being executed.
SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006
<Files *>
# Override the handler again if we're run later in the evaluation list.
SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003
</Files>
# If we know how to do it safely, disable the PHP engine entirely.
<IfModule mod_php5.c>
php_flag engine off
</IfModule>
"Верхние" файлы .htaccess из корня довольно большие, чуть-чуть отредактированные из дистрибутива Друпал и почти одинаковые. Выложу только их разницу, но если надо могу выложить и файлы целиком:
***** .htaccess
RewriteCond %{REQUEST_URI} !^/[A-F0-9]{32}\.txt(?:\ Comodo\ DCV)?$
RewriteRule ^/?$ "http\:\/\/art\.nouveau\.world\/" [R=301,L]
RewriteCond %{HTTP_HOST} ^art\-nouveau\.org$ [OR]
***** DEV\.HTACCESS
RewriteCond %{REQUEST_URI} !^/[A-F0-9]{32}\.txt(?:\ Comodo\ DCV)?$
RewriteRule ^/?$ "http\:\/\/dev\.nouveau\.world\/" [R=301,L]
RewriteCond %{HTTP_HOST} ^art\-nouveau\.org$ [OR]
*****
***** .htaccess
RewriteCond %{REQUEST_URI} !^/[A-F0-9]{32}\.txt(?:\ Comodo\ DCV)?$
RewriteRule ^/?$ "http\:\/\/art\.nouveau\.world\/" [R=301,L]
***** DEV\.HTACCESS
RewriteCond %{REQUEST_URI} !^/[A-F0-9]{32}\.txt(?:\ Comodo\ DCV)?$
RewriteRule ^/?$ "http\:\/\/dev\.nouveau\.world\/" [R=301,L]
*****
***** .htaccess
Redirect 301 /user/login /FAQ
Redirect 301 /ru/user/register /FAQ
Redirect 301 /ru/user/login /FAQ
RewriteBase /
RewriteCond %{THE_REQUEST} ^GET.*index\.php [NC]
RewriteRule (.*?)index\.php/*(.*) /$1$2 [R=301,NE,L]
RewriteCond %{HTTPS} =on
RewriteRule ^robots.txt$ robots-https.txt [L]
RewriteCond %{HTTP_USER_AGENT} bingbot [NC]
RewriteRule !^robots\.txt - [R=403,L]
***** DEV\.HTACCESS
*****
А если убрать?
RewriteRule \.(jpg|jpeg|png|gif)$ http://art.nouveau.world/nohotlinking.jpg [R,L]
Убрал (вместе с соответствующими RewriteCond), ничего не изменилось. Картинки все отдаются, но свежесгенерированные с кодом 404.
Там apache или apache+nginx? Что в логах веб-сервера пишет?
Apache. В логах сервера вот так:
95.165.139.254 - - [18/Dec/2018:21:46:04 +0300] "GET /sites/default/files/styles/gallery_thumbnail/public/ArtefactPictures/Spain/Madrid/20616981_401111413624788_9073456660031060747_o.jpg HTTP/1.1" 404 35507 "http://art.nouveau.world/railing" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36"
95.165.139.254 - - [18/Dec/2018:21:46:05 +0300] "GET /sites/default/files/styles/gallery_thumbnail/public/ArtefactPictures/Russia/Samara/z3vu8717rcukvzn31f.jpg HTTP/1.1" 404 15253 "http://art.nouveau.world/railing" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36"
95.165.139.254 - - [18/Dec/2018:21:46:05 +0300] "GET /sites/default/files/styles/gallery_thumbnail/public/ArtefactPictures/Austria/Vienna/DSC00241-01.jpeg HTTP/1.1" 200 30287 "http://art.nouveau.world/railing" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36"
95.165.139.254 - - [18/Dec/2018:21:46:05 +0300] "GET /sites/default/files/styles/gallery_thumbnail/public/ArtefactPictures/Belgium/Brussels/5919752980_1c371af726_b.jpg HTTP/1.1" 200 23986 "http://art.nouveau.world/railing" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36"
95.165.139.254 - - [18/Dec/2018:21:46:05 +0300] "GET /sites/default/files/styles/gallery_thumbnail/public/ArtefactPictures/Germany/Hagen/keom08.jpg HTTP/1.1" 200 25332 "http://art.nouveau.world/railing" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36"
95.165.139.254 - - [18/Dec/2018:21:46:04 +0300] "GET /sites/default/files/styles/gallery_thumbnail/public/ArtefactPictures/Russia/St%20Petersburg/14589584_646887538807505_6804595714876752813_o.jpg HTTP/1.1" 404 27980 "http://art.nouveau.world/railing" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36"
95.165.139.254 - - [18/Dec/2018:21:46:05 +0300] "GET /sites/default/files/styles/gallery_thumbnail/public/ArtefactPictures/Russia/Moscow/P4290317-X3.jpg HTTP/1.1" 404 23026 "http://art.nouveau.world/railing" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36"
То есть вперемешку 200 и 404. Все картинки в броузере отображаются нормально, независимо от кода.
А в error.log что-нибудь есть?
Нету ничего.
Доступ к конфигу apache для этого vhost есть? Показать можете?
Боюсь что нет (или я просто не умею его искать
В конфиге апача выставить LogLevel debug, правда там мусора в логах будет... но должно что-то проясниться.
Может опять глупость скажу: а если gallery_formatter отключить, тогда эффект сохраняется?
Попробую попозже, если это возможно сделать на уровне .htaccess, без доступа к общей конфигурации апача.
Я пробовал с другой галереей и другим стилем (просто снёс часть давно сгенерированных "миниатюр"): результат такой же, куча 404 при первом обращении, при этом все картинки генерируются и показываются.
Попробовал вставить LogLevel debug в .htaccess , получил довольно неожиданный результат: все картинки отдались с кодом 500, но при этом отдались и отрисовались как ни в чем ни бывало
Никаких других подробностей в логе нет - по прежнему одна запись на один запрос.
Я так понял, цель данного топика - превратиться в вечный "пятничный" топик?-)
Ну извините, если обломал.
Есть такой старый сисадминский(и не только) прием быстро и эффективно решать почти любые проблемы.
Если все варианты решений уже перепробованы, надо просто взять и прочитать наконец-то инструкцию(документацию).
В данном случае надо выяснить конфигурацию вэб-сервера:
1.Apache
2. Nginx + Apache
3. Другие варианты
И посмотреть логи вэб-сервера.
В 99% случаев эти действия помогут получить всю необходимую для решения проблемы информацию.
Так выяснили и посмотрели давно.
А в оставшемся 1% что делать?
На самом деле "проблема" конечно из разряда курьезов - если не пялиться праздно в консоль хрома, то ее и не видно никому. Думал вдруг кто сталкивался и сразу ответит, ну а нет так нет, действительно не тот вопрос, на который есть смысл тратить много времени.
Меня даже больше волнует та прошлогодняя проблема, которую я тогда заткнул отключением itok, так и не поняв "что это было" и почему отключение itok сработало. Отключение itok в settings.php грозятся убрать в одном из будущих релизов восьмерки (https://www.drupal.org/project/drupal/issues/2568517), и что я тогда буду делать?
Не выяснили..
Одни из самых распространенных конфигураций вэб-сервера:
1.Apache
2. Nginx + apllication server (обычно Apache)
3. Nginx + php-fpm
1.Apache
http-запросы принимает-отдает: Apache
обрабатывает: Apache
2. Nginx + apllication server (обычно Apache)
http-запросы принимает-отдает: Nginx
обрабатывает: Apache
3. Nginx + php-fpm
http-запросы принимает-отдает: Nginx
обрабатывает: php-fpm
У Вас скорее всего или 1 или 2
если 2 - то коды ответов отдает Nginx, и тогда разбираться надо с его конфигом.
Кстати, проблема с itok скорее всего с этим же связана.
В nginx для Drupal немного специфичный конфиг, как раз часть его "специфики" связана с обработкой запросов картинок.
Минуточку. Миниатюры не генерятся в момент запроса картинки. Миниатюры генерятся во время рендера форматтеров и всего такого. То есть, сервер перед тем, как "выплюнуть" ссылку на миниатюру в атрибуте src, должен её предварительно сгенерировать, если в папке со стилями этой картинки ещё нет.
Не знаю только, как это поможет в решении проблемы))
Довольно важное уточнение, но действительно ли это так? Чисто эмпирически при запросе галереи с несгенерированными картинками сначала открывается галерея с пустыми местами под картинки, а потом, довольно медленно и в случайном порядке в ней "проявляются" картинки по мере их генерации сервером. Простая перезагрузка страницы со всеми картинками после сброса браузерного кэша выглядит совсем не так - готовые картинки прилетают с сервера пулей.
И еще: если миниатюры не генерируются автоматически при прямом их запросе, то к чему тогда весь этот сыр-бор с введением itok'ов и последующим введением опции для их отключения?
PS Да вот прям щас попробовал загрузить несуществующую миниатюру прям из адресной строки браузера: сгенерировалась на ходу как ни в чем ни бывало. С кодом 404, что характерно
Интересно, у меня тоже так. Удаляю картинку - она восстанавливается. Но если в пути написать папку другого стиля, который к этой картинке не применяется, то картинка не сгенерится. Непонятно))
Конфиг nginx для drupal: https://www.nginx.com/resources/wiki/start/topics/recipes/drupal/
<?php
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
location @rewrite {
rewrite ^/(.*)$ /index.php?q=$1;
}
try_files $uri @rewrite;
expires max;
log_not_found off;
}
?>
Как раз тут: location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
try_files $uri @rewrite;
nginx пробует отдать картинку по ее пути $uri,
например /sites/default/files/styles/my-style/image-name.jpg
если картинка не найдена
запрос обрабатывается секцией конфига @rewrite
которая преобразует запрос
/sites/default/files/styles/my-style/image-name.jpg
в
index.php?q=/sites/default/files/styles/my-style/image-name.jpg
и отдает его drupal
далее вызывается обработчик для пути :
<?php
// Generate image derivatives of publicly available files.
/**
* Implements hook_menu().
*/
function image_menu() {
$items = array();
// If clean URLs are disabled, image derivatives will always be served
// through the menu system.
// If clean URLs are enabled and the image derivative already exists,
// PHP will be bypassed.
$directory_path = file_stream_wrapper_get_instance_by_scheme('public')->getDirectoryPath();
$items[$directory_path . '/styles/%image_style'] = array(
'title' => 'Generate image style',
'page callback' => 'image_style_deliver',
'page arguments' => array(count(explode('/', $directory_path)) + 1),
'access callback' => TRUE,
'type' => MENU_CALLBACK,
);
.........
?>
который создает нужный стиль картинки и отдает вэб-серверу
Ну нет у меня никаких следов и упоминаний nginx'а и его конфигурации на радоновском хостинге. Лежит в корне нетронутый web.config от друпаловского дистрибутива, сейчас снес его вообще для прикола - ничего не изменилось.
Самое время поставить )
В принципе, Orion76 уже описал физику процесса:
если вебсервер (в данном случае - апач) не находит файла по указанному пути, от переадресует запрос на /index.php
далее, срабатывает hook_menu модуля image, и необходимый пресет генерится и кладется на свое место.
При следующем запросе - апач находит файл по указанному пути и отдает его.
Непонятно, почему возвращается 404 при передаче запроса на /index.php
Похожим образом работает модуль robotstxt - если в корне сайта нет файла robots.txt, то запрос идет на index.php и через hook_menu обрабатывается модулем, который возвращает содержимое файла.
А если файл есть - то модуль не может обработать запрос, о чем и сообщает в отчете о состоянии сайта.
Попробуйте поставить robotstxt и переименовать файл в robots.txt.bak - с каким кодом будет отдаваться содержимое файла?
Если 200 - то проблема где-то в модуле image, а если - 404, то в настройках вебсервера.
web.config не имеет никакого отношения к nginx.
Спасибо, кэп! Только я эту самую физику описал чуть раньше, прямо в самом первом посте
И еще раз спасибо, кэп! ;)
Это мысль, щас попробую.
Поставил модуль robotsttxt, снёс файл robots.txt, при запросе отдаётся динамический robots от модуля с кодом 200!
Значит, похоже косячит именно Друпал 8.6 в цепочке обработки запроса к несуществующей миниатюре. Попробую порыться в коде ядра.
Вставил $this->logger->notice() непосредственно перед
return new BinaryFileResponse($uri, 200, $headers, $scheme !== 'private');
в ImageStyleDownloadController.php. Действительно для всех вновь генерируемых картинок вызывается этот код и передается код 200.
Вопрос: что, как и зачем может поменять код ответа (и больше ничего) у уже сформированного друпалом ответа?
Код ответа может поменять либо веб-сервер, либо кеширующий сервер. Только они как бы таким не занимаются в стандарте.
Loglevel выставляется в конфиге апача, но не в htaccess, то что произошло это... гммм... it's a magic!^_^ В смысле там что-то не то и не так отработало, смутно догадываюсь что там есть похожая директива.
И да, скорее всего на серваке стоит nginx.
Вообще хостер радон, здесь есть их представители, надо бы их пригласить в тему.
Ну они формально с пользовательским кодом не обязаны разбираться, я не хотел их грузить пока достоверно не выяснится, что проблема в настройках, мне недоступных, а не в моем коде или в моих настройках. Тем более, что на другом-то сервере, который у них же хостится, всё нормально.
Можно Бориса https://drupal.ru/username/bsyomov попросить, очень отзывчивый профессионал по настройке серверного ПО.
Спасибо за лестную оценку, и я бы даже помог, вот только настроить ПО на шеред хостинге, это определённо проблема.
Да Борис уже помог чем мог на основании той скудной информации, которую я был в состоянии предоставить
Теперь попробую в техподдержку Радона написать, раз все эксперты склоняются к тому, что дело в настройках сервера.
А обязательно оставаться на шареде?
Не вижу пока ни одного повода съезжать с Радона. Работает всё надёжно и быстро, техподдержка отличная (если задаешь внятные вопросы по существу), а обсуждаемый в данной теме курьёз вообще ни на что не влияет, даже если так и не удастся с ним разобраться
PS А лавры сам-себе-сисадмина меня никогда не прельщали, мне гораздо проще платить (смешные) деньги специально обученным профессионалам.
На самом деле, это чаще всего, правильная позиция. Нормальный шаред это вполне хорошо и удобно, если соответствует нуждам проекта. А желание переехать на VPS, без знаний и навыков, прочитав пару статеек, обычно ведёт к серьёзным проблемам.
+100500
Ну раз проблема не вопрос, то отлично.
Выявил одну любопытную закономерность: если из файла sites/default/files/.htaccess убрать или закомментировать ВСЕ директивы после
php_flag engine off
</IfModule>
то есть сделать этот файл как из дистрибутива или как на dev-сайте, то ошибка 404 сразу пропадает. При вводе туда ЛЮБОЙ директивы, даже просто "RewriteEngine on" без единого условия или правила, сразу появляется код 404 на генерируемых картинках.
В общем, перетащил все нужные мне директивы (явно прописав пути) в корневой .htaccess, всё работает как надо и без ошибок. А почему оно так было - пусть останется загадкой
ССЗБ, кароч)))
Ну типа того Но почему, Карл?! ;)))
Кстати, и прошлогодняя проблема со стилями, из-за которой тогда пришлось вставлять костыли в settings.php, тоже прошла! Костыли убрал, пациент пляшет без посторонней поддержки.
Всё-таки правильно я чувствовал что эти две проблемы как-то взаимосвязаны.
Вот что значит хороший мозговой штурм..
И помогать не пришлось, только мешались-)
Да МШ удался на славу, хороший треш.