4

Opencart has this URL structure:

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

... and I want to get rid of the string from index.php?route= until the first /, the regex for that is index.php\?route\=[^\/]*\/, so the desired URL would be, for example, http://example.com/checkout.

I tried:

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

and also tried:

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

... but no luck so far, I still see route=common/home in the URLs.

This is my current Nginx configuration:

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;
}
MrWhite
  • 12,647
  • 4
  • 29
  • 41
3br4him
  • 91
  • 2
  • 4

5 Answers5

0

The URLs in the web pages you receive from OpenCart are generated by OpenCart software. You need to look up for friendly URLs in its configuration, and enable those.

Then you can apply corresponding rewrite rules in nginx, so that the incoming requests are routed to OpenCart properly.

Tero Kilkanen
  • 36,796
  • 3
  • 41
  • 63
  • SEO URLs is already enabled and it works on product pages, not these, thats the problem. Others have fixed this issue with htaccess on Apache, but I couldn't find anything for nginx. An answer here will hopefully help everyone on nginx using opencart. – 3br4him Aug 26 '16 at 12:17
  • @3br4him, perhaps that's because these are "internal" pages, that aren't supposed to be indexed? I still agree with you that "index.php" is "ugly", and shouldn't show up in the browser even for the pages that aren't meant to be shared. – cnst Sep 03 '16 at 23:07
0

Rewrite rules can translate routes in incoming requests from a nice version to a version with the appropriate index.php based incantation, but it sounds like this is a question about the generated HTML sent in responses, which is still produced with the index.php incantation? To change index.php-based routes in responses sent to the browser, try nginx' ngx_http_sub_module:

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

Something along the lines of:

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

in conjunction with the rewrite may be sufficient.

Jonah Benton
  • 1,252
  • 7
  • 13
0

The try_files directive should handle most of the work. I don't have OpenCart installed, so the following is not tested. It might be a good starting point though. The $uri variable will include a leading /, which is excluded by the .htaccess rules I've seen. If it's problem, it can be excluded with a little more work.

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;
Cole Tierney
  • 101
  • 1
0

Does the following look good?

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

This may or may not work, depending on how "smart" your upstream Opencart thinks that it is.

The idea is, as per https://stackoverflow.com/questions/21687288/nginx-redirect-loop-remove-index-php-from-url/21813759#21813759, to issue redirects only if index.php appears in the original request from the user (in $request_uri), but not if it's merely present as part of the internal routing (in $uri). E.g., it may seem like the below snippet would result in a loop, but it should not.

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

Alternatively, if your processing through try_files can already catch 404, and redirect it to Opencart (e.g., if URLs without the index.php?route= part already work as you intend), then all you need is the following:

if ($request_uri ~ ^/index.php?route=(.*)$) {  return 301 $1;  }
cnst
  • 13,848
  • 9
  • 54
  • 76
  • where should it go? I just tried, no luck still :( – Nimbuz Sep 04 '16 at 22:55
  • @Nimbuz, you should put it somewhere at the top level of your server config; also, give more details of what's the issue that you're having (e.g., whether you get errors from nginx or upstream etc) – cnst Sep 04 '16 at 23:41
  • Sure, this is my config (http://pastebin.com/jqvySERx) and this is what the log shows: http://pastebin.com/qvTYm1mE – Nimbuz Sep 05 '16 at 01:18
  • @Nimbuz, Are you sure it's the error you're getting from the config? What happens without this config if you issue a request for `/common/home`? What if you only use the `$request_uri` line, without the `rewrite` one? – cnst Sep 05 '16 at 06:04
  • Tried that, doesn't affect anything .. product and category pages continue to have SEO url .. home and others dont, just the same. – Nimbuz Sep 05 '16 at 08:57
  • @Nimbuz, I noticed the nginx config has `_route_`, yet in the examples of the sample non-SEO URLs, you give it without underscores -- why the discrepancy? That'd be the only reason why the `request_uri` code above wouldn't be working; else, what's your full request URL? – cnst Sep 05 '16 at 15:27
  • How do you mean? Can you share the full config on pastebin please, I'll try and see if it works. thanks! – Nimbuz Sep 05 '16 at 15:50
  • @Nimbuz, how does the request look in the browser? What's the full URL that you see that you want changed to a SEO one? If you try the SEO one manually (e.g., type it manually), would it already work with the default configuration, or would it result in an error? – cnst Sep 05 '16 at 16:40