Назад | Перейти на главную страницу

Правило перезаписи для nginx (Opencart)

Opencart имеет такую ​​структуру URL:

http://example.com/index.php?route=common/home
http://example.com/index.php?route=account/register
http://example.com/index.php?route=checkout/cart
http://example.com/index.php?route=checkout/checkout

... и я хочу избавиться от строки из index.php?route= до первого /, регулярное выражение для этого index.php\?route\=[^\/]*\/, поэтому желаемый URL-адрес будет, например, http://example.com/checkout.

Я попытался:

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

а также пробовал:

location / {
  if ($query_string ~ "^route=common/home$"){
    rewrite ^/index\.php$ http://www.example.com? redirect;
  }
}

... но пока не повезло, я все еще вижу route=common/home в URL-адресах.

Это моя текущая конфигурация Nginx:

location / {
  try_files $uri @opencart;
}
location @opencart {
    rewrite ^/(.+)$ /index.php?_route_=$1 last;
}
location ~ \.php$ {
  include snippets/fastcgi-php.conf;
  fastcgi_pass unix:/run/php/php7.0-fpm.sock;
}
location ~* \.(engine|inc|info|install|make|module|profile|test|po|sh|.*sql|theme|tpl(\.php)?|xtmpl)$|^(\..*|Entries.*|Repository|Root|Tag|Template)$|\.php_ {
    deny all;
}
location ~ /\.ht {
  deny all;
}
location /image/data {
    autoindex on;
}
location = /favicon.ico {
  log_not_found off;
  access_log off;
}
location = /robots.txt {
  allow all;
  log_not_found off;
  access_log off;
}
location ~* \.(?:jpg|jpeg|gif|bmp|ico|png|css|js|swf)$ {
  expires max;
  access_log off;
}

В try_files Директива должна обрабатывать большую часть работы. У меня не установлен OpenCart, поэтому следующее не проверено. Хотя это может быть хорошей отправной точкой. В $uri переменная будет включать ведущую /, который исключен правилами .htaccess, которые я видел. Если это проблема, ее можно исключить, приложив еще немного усилий.

location = /sitemap.xml {
    try_files /index.php?route=feed/google_sitemap =404;
}

location = /googlebase.xml {
    try_files /index.php?route=feed/google_base =404;
}

try_files $uri $uri/ /index.php?_route_=$uri;

Правила перезаписи могут переводить маршруты во входящих запросах из хорошей версии в версию с соответствующим заклинанием на основе index.php, но похоже, что это вопрос о сгенерированном HTML, отправленном в ответах, который по-прежнему создается с помощью заклинания index.php ? Чтобы изменить маршруты на основе index.php в ответах, отправленных браузеру, попробуйте nginx 'ngx_http_sub_module:

http://nginx.org/en/docs/http/ngx_http_sub_module.html

Что-то вроде:

sub_filter '/index.php?route=' '';
sub_filter_once on;

в сочетании с перезаписью может хватить.

URL-адреса веб-страниц, которые вы получаете от OpenCart, генерируются программным обеспечением OpenCart. Вам нужно найти удобные URL-адреса в его конфигурации и включить их.

Затем вы можете применить соответствующий rewrite rules в nginx, чтобы входящие запросы правильно направлялись в OpenCart.

Следующее выглядит хорошо?

map $arg_route $_dest { default "/"; "~*^(?:[^/]*)(?<dest>/.*)" $dest; }
server {
  location / {
    try_files $uri @opencart;
  }
  location @opencart {
    rewrite ^(?i)/index.php$    $_dest? last;
  }
}

Это может работать, а может и не работать, в зависимости от того, насколько «умным» ваш апстрим Opencart считает это.

Идея, согласно https://stackoverflow.com/questions/21687288/nginx-redirect-loop-remove-index-php-from-url/21813759#21813759, выдавать редиректы только если index.php появляется в исходном запросе от пользователя (в $request_uri), но не если он просто присутствует как часть внутренней маршрутизации (в $uri). Например, может показаться, что приведенный ниже фрагмент приведет к возникновению цикла, но этого не должно быть.

rewrite ^/([a-z]+/[a-z]+)$ /index.php?route=$1 last;
if ($request_uri ~ ^/index.php?route=([a-z]+/[a-z]+)$) {  return 301 /$1;  }

В качестве альтернативы, если ваша обработка через try_files уже могу поймать 404, и перенаправить его на Opencart (например, если URL-адреса без index.php?route= часть уже работает так, как задумано), то все, что вам нужно, это следующее:

if ($request_uri ~ ^/index.php?route=(.*)$) {  return 301 $1;  }