Перейти до вмісту
Пошук в
  • Детальніше...
Шукати результати, які ...
Шукати результати в ...

Nginx проблема с кириллицей в product/search


Recommended Posts

Здравствуйте! Моя голова уже вся сломалась на раздумьях о том, почему не проходит запрос в product/search на кириллице.

Opencart 2 на nginx + php-fpm.

Вбиваю русское слово в строку поиска (или прямо в адресную строку в /index.php?route=product/search&search=слово). Русское слово кодируется методом URIencode, например "погрузчик" -> "%D0%BF%D0%BE%D0%B3%D1%80%D1%83%D0%B7%D1%87%D0%B8%D0%BA"

Идет запрос 

/index.php?route=product/search&search=%D0%BF%D0%BE%D0%B3%D1%80%D1%83%D0%B7%D1%87%D0%B8%D0%BA

В этой строке почему то последовательности "%8?" подменяются на "_" (посмотрела в логах), соответственно, запрос превращается в 

/search/?search=%D0%BF%D0%BE%D0%B3%D1_%D1_%D0%B7%D1_%D0%B8%D0%BA

При раскодировании получается пустая строка, которая отправляется в базу данных, поиск ничего не находит.

 

Запросы на английском языке - работают. Запросы на русском языке - работают, если закодированное слово не содержит последовательностей "%8?", например, запрос "мини" пройдет.

Статические страницы с кириллицей (которые без route) - работают. 
На локали на http - все работает.

 

Подозрения на какие то особенности конфига. 

 

Конфиг домена:

Спойлер
server {
  charset UTF-8;
    listen      IP:443 ssl http2;
    server_name domen.ru www.domen.ru;
    root        $root-path;
    index       index.php index.html index.htm;

 

    ssl_certificate      $ssl_certificate-path;
    ssl_certificate_key  $ssl_certificate_key-path;

 

    location / {
        try_files $uri $uri/ @opencart;
        location ~* ^.+\.(jpeg|jpg|png|gif|bmp|ico|svg|css|js)$ {
            expires     max;
        }
    }
  
  location ~ \.php$ {
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            if (!-f $document_root$fastcgi_script_name) {
                return  404;
            }

 

            fastcgi_pass    127.0.0.1:9002;
            fastcgi_index   index.php;
            include         /etc/nginx/fastcgi_params;
        }

 

    location @opencart {
        rewrite ^/(.+)$ /index.php?_route_=$1 last;
    }

 

    location /vstats/ {
        alias   $home-path/web/domen.ru/stats/;
        include $home-path/conf/web/domen.ru.auth*;
    }

 

    location ~* "/\.(htaccess|htpasswd)$" {
        deny    all;
        return  404;
    }

 

    if ($http_host = www.domen.ru){
        rewrite ^(.*)$ https://domen.ru$1 permanent;
    }

 

    #Редирект на https
    if ($scheme != "https"){
        return 301 https://$host$request_uri;
    }

 

    include     /etc/nginx/conf.d/phpmyadmin.inc*;
    include     /etc/nginx/conf.d/phppgadmin.inc*;
    include     /etc/nginx/conf.d/webmail.inc*;
    include     $home-path/conf/web/snginx.domen.ru.conf*;
}

 

А это главный конфиг, предоставленный хостингом

Спойлер
# Server globals
user                    www-data;
worker_processes        auto;
worker_rlimit_nofile    65535;
error_log               /var/log/nginx/error.log;
pid                     /var/run/nginx.pid;
 
# Worker config
events {
        worker_connections  1024;
        use                 epoll;
        multi_accept        on;
}
 
http {
    # Main settings
    charset UTF-8;
    sendfile                        on;
    tcp_nopush                      on;
    tcp_nodelay                     on;
    client_header_timeout           60s;
    client_body_timeout             60s;
    client_header_buffer_size       2k;
    client_body_buffer_size         256k;
    client_max_body_size            256m;
    large_client_header_buffers     4 8k;
    send_timeout                    60s;
    keepalive_timeout               30s;
    reset_timedout_connection       on;
    server_tokens                   off;
    server_name_in_redirect         off;
    server_names_hash_max_size      512;
    server_names_hash_bucket_size   512;
 
    # Log format
    log_format  main    '$remote_addr - $remote_user [$time_local] $request '
                        '"$status" $body_bytes_sent "$http_referer" '
                        '"$http_user_agent" "$http_x_forwarded_for"';
    log_format  bytes   '$body_bytes_sent';
    #access_log          /var/log/nginx/access.log main;
    access_log off;
 
    # Mime settings
    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;
 
    # Compression
    gzip                on;
    gzip_static         on;
    gzip_vary           on;
    gzip_comp_level     6;
    gzip_min_length     1024;
    gzip_buffers        16 8k;
    gzip_types          text/plain text/css text/javascript text/js text/xml application/json application/javascript application/x-javascript application/xml application/xml+rss application/x-font-ttf image/svg+xml font/opentype;
    gzip_proxied        any;
    gzip_disable        "MSIE [1-6]\.";
 
    # Proxy settings
    proxy_redirect      off;
    proxy_set_header    Host            $host;
    proxy_set_header    X-Real-IP       $remote_addr;
    proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass_header   Set-Cookie;
    proxy_buffers       32 4k;
    proxy_connect_timeout   30s;
    proxy_send_timeout  90s;
    proxy_read_timeout  90s;
 
        
    # Cloudflare https://www.cloudflare.com/ips
    set_real_ip_from   103.21.244.0/22;
    set_real_ip_from   103.22.200.0/22;
    set_real_ip_from   103.31.4.0/22;
    set_real_ip_from   104.16.0.0/12;
    set_real_ip_from   108.162.192.0/18;
    set_real_ip_from   131.0.72.0/22;
    set_real_ip_from   141.101.64.0/18;
    set_real_ip_from   162.158.0.0/15;
    set_real_ip_from   172.64.0.0/13;
    set_real_ip_from   173.245.48.0/20;
    set_real_ip_from   188.114.96.0/20;
    set_real_ip_from   190.93.240.0/20;
    set_real_ip_from   197.234.240.0/22;
    set_real_ip_from   198.41.128.0/17;
    #set_real_ip_from   2400:cb00::/32;
    #set_real_ip_from   2606:4700::/32;
    #set_real_ip_from   2803:f800::/32;
    #set_real_ip_from   2405:b500::/32;
    #set_real_ip_from   2405:8100::/32;
    #set_real_ip_from   2c0f:f248::/32;
    #set_real_ip_from   2a06:98c0::/29;
    real_ip_header     CF-Connecting-IP;
 
    # SSL PCI Compliance
    ssl_session_cache   shared:SSL:10m;
    ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    ssl_ciphers        "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
 
    # Error pages
    error_page          403          /error/403.html;
    error_page          404          /error/404.html;
    error_page          502 503 504  /error/50x.html;
 
    # Cache settings
    proxy_cache_path /var/cache/nginx levels=2 keys_zone=cache:10m inactive=60m max_size=1024m;
    proxy_cache_key "$host$request_uri $cookie_user";
    proxy_temp_path  /var/cache/nginx/temp;
    proxy_ignore_headers Expires Cache-Control;
    proxy_cache_use_stale error timeout invalid_header http_502;
    proxy_cache_valid any 1d;
 
    # Cache bypass
    map $http_cookie $no_cache {
        default 0;
        ~SESS 1;
        ~wordpress_logged_in 1;
    }
 
    # File cache settings
    open_file_cache          max=10000 inactive=30s;
    open_file_cache_valid    60s;
    open_file_cache_min_uses 2;
    open_file_cache_errors   off;
 
    # Wildcard include
    include             /etc/nginx/conf.d/*.conf;
}


В чем же заключается эта магия?..
Старший программист предлагает русское слово перевести в транслит, а перед отправкой в базу расшифровать обратно. Но я не оставляю надежды понять, почему адресная строка себя так ведет :-?

Надіслати
Поділитися на інших сайтах


25 minutes ago, HtwwtH said:

Но я не оставляю надежды понять, почему адресная строка себя так ведет 

 

попробуйте для начала в этот локейшн добавить упущенную инструкцию

25 minutes ago, HtwwtH said:
  location ~ \.php$ {
#            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
 
            if (!-f $document_root$fastcgi_script_name) {
                return  404;
            }
        try_files $uri =404;

fastcgi_split_path_info ^((?U).+\.ph(?:p\d*|tml))(/?.+)$;

            fastcgi_pass    127.0.0.1:9002;
            fastcgi_index   index.php;
            include         /etc/nginx/fastcgi_params;
        }

далее, если не поможет, стоит покурить в сторону наличия модификаций seo_pro.php и ради теста, убрать все сторонние ocmod'ы, например.

 

Змінено користувачем 100napb
зелененьким добавил более правильную альтернативу
  • +1 1
Надіслати
Поділитися на інших сайтах

В 05.03.2021 в 16:27, 100napb сказал:

 

попробуйте для начала в этот локейшн добавить упущенную инструкцию

далее, если не поможет, стоит покурить в сторону наличия модификаций seo_pro.php и ради теста, убрать все сторонние ocmod'ы, например.

 

 

Эх, не помогает ничего. Спасибо за ответ! Модификаций правда присутствует куча от предыдущих разработчиков. Пробовала отключать, кстати, пара связаны с поиском. Обновила модификаторы, очистила папку с кэшем - поиск все равно остался сломан. Также изменила конфиг и перезапустила nginx.
Явной подмены "%8" нигде по коду не происходит.


Есть пара плагинов, которые в system/storage/modification/catalog/controller/startup переписали seo_pro.php и seo_url.php: NewsBlog для новостей (но он установлен уже после того, как поиск был сломан), и OcFilter (v4.7.5) для фильтров в категории с ползунками. Вот на OcFilter есть подозрение, но если его отключить, а потом включить, там слетают настройки.

 

По ходу, придется делать транслит, думаю воспользоваться "ГОСТ 7.79-2000 (ИСО 9-95) СИБИД. Правила транслитерации кирилловского письма латинским алфавитом" - если в поиск вбили русское слово, добавить какой-нибудь ключ в начало строки, транслитить в англ русское слово, чтобы оно дошло в таком виде до функции отправки в базу, а перед отправкой расшифровать в русский, вроде этот алгоритм позволяет точно расшифровывать.

Правда, не понимаю пока, в куче разных файлов с вызовами БД, какой именно вызов БД мне нужен, буду потом как нибудь экспериментировать на локалке.

 

Вот нашла пример транслит на js, вдруг кому пригодится

Спойлер
transliterate = (
03     function() {
04         var
05             rus = "щ   ш  ч  ц  ю  я  ё  ж  ъ  ы  э  а б в г д е з и й к л м н о п р с т у ф х ь".split(/ +/g),
06             eng = "shh sh ch cz yu ya yo zh `` y' e` a b v g d e z i j k l m n o p r s t u f x `".split(/ +/g)
07         ;
08         return function(text, engToRus) {
09             var x;
10             for(x = 0; x < rus.length; x++) {
11                 text = text.split(engToRus ? eng[x] : rus[x]).join(engToRus ? rus[x] : eng[x]);
12                 text = text.split(engToRus ? eng[x].toUpperCase() : rus[x].toUpperCase()).join(engToRus ? rus[x].toUpperCase() : eng[x].toUpperCase());
13             }
14             return text;
15         }
16     }
17 )();
18 var txt = "Съешь ещё этих мягких французских булок, да выпей же чаю!";
19 alert(transliterate(txt));
20 alert(transliterate(transliterate(txt), true));

 

А вообще интересный баг, что он принимает %8+еще символ за разделитель, может, это пошло откуда-то, где делят url на категория_подкатегория_продукт, но мне не удается найти этого причину(

P.S. Я нанималась на junior frontend, а не вот это вот все :grin: 

Змінено користувачем HtwwtH
Надіслати
Поділитися на інших сайтах


В 09.03.2021 в 16:05, AlexDW сказал:

в настройках магазина в админке пробуйте отключить "использовать seourl" и проверьте

 

Оу, так не стирает символы, теперь понятно, что проблема в SEO URL

Надіслати
Поділитися на інших сайтах


смотрите код того файла, что у вас используется в качестве обработчика seourl

 

либо в нем напрямую внесены правки для обработки

В 05.03.2021 в 14:16, HtwwtH сказал:

почему то последовательности "%8?" подменяются на "_"

либо в каком-то из работающих с ним модификаторов

Надіслати
Поділитися на інших сайтах

Пишу итоговое решение. 

Не удалось найти, где происходит подмена символов, уже ушло много времени на исследование вопроса, решили отключить ЧПУ-ссылки именно на странице поиска. Страницы, связанные с поиском, все равно перекрыты в robots.txt и не влияют на сео сайта:

Disallow: /*route=product/search
Disallow: /search/

 

В файле\catalog\controller\startup\seo_pro.php в функции validate():

if (rawurldecode($url) != rawurldecode($seo) && isset($this->request->server['SERVER_PROTOCOL'])) {
	header($this->request->server['SERVER_PROTOCOL'] . ' 301 Moved Permanently');
	$this->response->redirect($seo, 301);
}

замена на:

if (strripos($url, '/search')){	//со страниц поиска не редиректить на чпу, то есть ничего не делать
}

elseif ( rawurldecode($url) != rawurldecode($seo) && isset($this->request->server['SERVER_PROTOCOL'])) {
	header($this->request->server['SERVER_PROTOCOL'] . ' 301 Moved Permanently');
	$this->response->redirect($seo, 301);
}

Примечание, досюда $url и $seo доходят еще нормальные и даже правильно расшифрованы, но во время редиректа с ними что-то происходит. Возможно, в WINDOWS-1251 перекодирует (хотя все страницы сайта, все таблицы базы данных, сама база, в настройке nginx установлено utf-8), такое предположение, потому что после редиректа были похожие на то закорючки в запросах (смотрела цепочку редиректов в network).

 

Спасибо за советы, они помогли понять, в чем проблема! Жаль, пока не хватает ума полностью раскопать настройки, но какое-никакое решение есть)

Змінено користувачем HtwwtH
ошибка в ссылке
  • +1 2
Надіслати
Поділитися на інших сайтах


Створіть аккаунт або увійдіть для коментування

Ви повинні бути користувачем, щоб залишити коментар

Створити обліковий запис

Зареєструйтеся для отримання облікового запису. Це просто!

Зареєструвати аккаунт

Вхід

Уже зареєстровані? Увійдіть тут.

Вхід зараз
  • Зараз на сторінці   0 користувачів

    • Ні користувачів, які переглядиють цю сторінку
×
×
  • Створити...

Important Information

На нашому сайті використовуються файли cookie і відбувається обробка деяких персональних даних користувачів, щоб поліпшити користувальницький інтерфейс. Щоб дізнатися для чого і які персональні дані ми обробляємо перейдіть за посиланням . Якщо Ви натиснете «Я даю згоду», це означає, що Ви розумієте і приймаєте всі умови, зазначені в цьому Повідомленні про конфіденційність.