Nginx Rewrite /product_category/ WordPress

d1ch0t0my asked:

I’m trying to rewrite both the following for a WordPress/Woocommerce site:

/product_category/example-category/
/product/example-product/

to…

/example-category/
/example-product/

using the following rules:

server {

listen      10.99.0.3:8080;

server_name    www.example.com;

root /home/www.example.com/public_html;
index index.html index.htm index.php;

rewrite ^/product-category/1$ /;
rewrite ^/product/1$ /;

include conf.d/whitelisted.conf;
include conf.d/wp/restrictions.conf;
include conf.d/wp/wordpress.conf;

 }

…and here is the wordpress.conf rules included from a seperate file:

location / {
  try_files $uri $uri/ /index.php?$args;
}

rewrite /wp-admin$ $scheme://$host$uri/ permanent;

location ~* ^.+.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
   access_log off; log_not_found off; expires max;
}

location ~* /(?:uploads|files)/.*.php$ {
  deny all;
}

location ~* /wp-content/.*.php$ {
  deny all;
}

location ~* /wp-includes/.*.php$ {
  deny all;
}

location ~* /(?:uploads|files|wp-content|wp-includes)/.*.php$ {
  deny all;
}

location ~ [^/].php(/|$) {
  fastcgi_split_path_info ^(.+?.php)(/.*)$;
  if (!-f $document_root$fastcgi_script_name) {
    return 404;
  }

  include fastcgi_params;
  fastcgi_pass unix:/var/run/php-fpm/php5-fpm.sock;
  fastcgi_index index.php;
  include /etc/nginx/fastcgi_params;

  fastcgi_buffer_size 128k;
  fastcgi_buffers 256 16k;
  fastcgi_busy_buffers_size 256k;
  fastcgi_temp_file_write_size 256k;
  fastcgi_read_timeout 1800;  

}

but Nginx seems to be ignoring the rewrite rules I specify for the product cat / product rewrites as if they did not exist. For example if I visit:

http://www.example.com/product-category/footwear/

instead of rewriting to:

http://www.example.com/footwear/

it just serves up:

http://www.example.com/product-category/footwear/

What am I doing wrong? Thanks!

My answer:


Your rewrites are using regular expressions, and interestingly, they are set to match only specific URLs.

rewrite ^/product-category/1$ /;
rewrite ^/product/1$ /;

So, only the URLs /product-category/1 and /product/1 would match these directives. Neither /product/2 nor /product/air-jordan-1-retro-high-og-banned-2016-release will match.

What I think you want to do instead is to capture the remainder of the URL and use that in the destination URL.

rewrite ^/product-category/(.*) /$1;
rewrite ^/product/(.*) /$1;

But wait, there’s more! You haven’t specified an optional flag for the rewrite directive. So, after rewriting the URL, nginx continues right along on its merry way through the config. It doesn’t start over processing the request, or redirect the user agent. This could cause WordPress to get confused. If you want redirection (e.g. for SEO) then you should add the appropriate flag.

rewrite ^/product-category/(.*) /$1 permanent;
rewrite ^/product/(.*) /$1 permanent;

View the full question and answer on Server Fault.

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.