Score:0

NGINX rewrite URL on wordpress but getting 404

my flag

I have a WordPress website where my URLs are currently written as follows
http://example.com/for-sale/12345-aaa-123-street-bbb-city/

and I would like to still serve the same URL, but I want the URL to look like
http://example.com/city/street/

I have created a rewrite rule of rewrite for-sale/([0-9]+)-aaa-(.*)-bbb-(.*) /$3/$2/ permanent;

This does rewrite my URL but returns a 404 error. Here is what the rewrite log returns

2021/11/04 04:48:39 [notice] 23077#23077: *4643 rewritten redirect: "/Vernon//539-Apache-County-Road-3144/", client: 108.162.215.21, server: example.com, request: "GET /for-sale/20071-aaa-539-Apache-County-Road-3144-bbb-Vernon/ HTTP/1.1", host: "example.com", referrer: "https://example.com/vernon/"
2021/11/04 04:48:40 [notice] 23077#23077: *4646 "for-sale/([0-9]+)-aaa-(.*)-bbb-(.*)" matches "/for-sale/14808-aaa-35640A-Hwy-60-bbb-Vernon/", client: 172.70.98.47, server: example.com, request: "GET /for-sale/14808-aaa-35640A-Hwy-60-bbb-Vernon/ HTTP/1.1", host: "example.com", referrer: "https://example.com/vernon/"
2021/11/04 04:48:40 [notice] 23077#23077: *4646 rewritten redirect: "/Vernon//35640A-Hwy-60/", client: 172.70.98.47, server: example.com, request: "GET /for-sale/14808-aaa-35640A-Hwy-60-bbb-Vernon/ HTTP/1.1", host: "example.com", referrer: "https://example.com/vernon/"
2021/11/04 04:48:41 [notice] 23077#23077: *4649 "for-sale/([0-9]+)-aaa-(.*)-bbb-(.*)" does not match "/for-sale/19617-2926-DEER-HILL-Road-Heber-Arizona-85928/", client: 108.162.245.49, server: example.com, request: "GET /for-sale/19617-2926-DEER-HILL-Road-Heber-Arizona-85928/ HTTP/1.1", host: "example.com"
2021/11/04 04:48:41 [notice] 23077#23077: *4651 "for-sale/([0-9]+)-aaa-(.*)-bbb-(.*)" matches "/for-sale/6944-aaa-35640-Hwy-60-bbb-Vernon/", client: 172.69.35.180, server: example.com, request: "GET /for-sale/6944-aaa-35640-Hwy-60-bbb-Vernon/ HTTP/1.1", host: "example.com", referrer: "https://example.com/vernon/"
2021/11/04 04:48:41 [notice] 23077#23077: *4651 rewritten redirect: "/Vernon//35640-Hwy-60/", client: 172.69.35.180, server: example.com, request: "GET /for-sale/6944-aaa-35640-Hwy-60-bbb-Vernon/ HTTP/1.1", host: "example.com", referrer: "https://example.com/vernon/"
2021/11/04 04:48:42 [notice] 23077#23077: *4654 "for-sale/([0-9]+)-aaa-(.*)-bbb-(.*)" matches "/for-sale/18232-aaa-72-County-Road-8144-bbb-Vernon/", client: 172.172.35.168, server: example.com, request: "GET /for-sale/18232-aaa-72-County-Road-8144-bbb-Vernon/ HTTP/1.1", host: "example.com", referrer: "https://example.com/vernon/"
2021/11/04 04:48:42 [notice] 23077#23077: *4654 rewritten redirect: "/Vernon//72-County-Road-8144/", client: 172.172.35.168, server: example.com, request: "GET /for-sale/18232-aaa-72-County-Road-8144-bbb-Vernon/ HTTP/1.1", host: "example.com", referrer: "https://example.com/vernon/"

I'm not sure if I'm headed down the right path here, or is a rewrite rule wrong to be using in this scenario? I've tried placing the rewrite rule in it's own location, and tried different flags but this is the closest I have got so far.

Here is my full config. Thanks for any help.

server {

  server_name example.com www.example.com;

    access_log /var/www/example.com/logs/access.log;
    error_log /var/www/example.com/logs/error.log;
    rewrite_log on;
    root /var/www/example.com/public;
    index index.php;


    listen 443 ssl http2; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot


location / {

rewrite for-sale/([0-9]+)-aaa-(.*)-bbb-(.*) /$3/$2/ permanent;
        try_files $uri $uri/ /index.php?$args;

        }


        # fastcgi
        location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/run/php/php7.4-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param HTTPS on;
        fastcgi_param HTTP_SCHEME https;
        fastcgi_read_timeout 150;
        }

        #Cache static files for as long as possible
        location ~*.(ogg|ogv|svg|svgz|eot|otf|woff|woff2|mp4|ttf|css|rss|atom|js|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz)$ {       expires 365d;
        }
        location ~ ^/(wp-admin|wp-login|ngx_pagespeed_statistics|ngx_pagespeed_global_statistics|ngx_pagespeed_message)$ {       #auth_basic "Private";
        auth_basic_user_file /usr/local/nginx/conf/.htpasswd;
        }

        location ~* /wp-includes/.*.php$ {
        deny all;
        access_log off;
        log_not_found off;
        }
        location ~* /wp-content/.*.php$ {
        deny all;
        access_log off;
        log_not_found off;
        }



}

server {
    if ($host = www.example.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    if ($host = example.com) {
        return 301 https://$host$request_uri;
   } # managed by Certbot


    server_name example.com www.example.com;


    listen 80;
    return 404; # managed by Certbot


}
Ivan Shatsky avatar
gr flag
Did you get a WordPress customized 404 page or raw nginx one? Looks like it is a WP who didn't understand your rewritten URI. You can manually check it entering `https://example.com/Vernon//72-County-Road-8144/` at your browser address bar.
David avatar
my flag
Yes, it's a 404 from WordPress. "Page not found". The original page in question would have been https://example.com/for-sale/12356-aaa-72-County-Road-8144-bbb-Vernon/ and I'm trying to still serve that page but with the URL displayed as https://example.com/vernon/72-County-Road-8144/ and it looks like WordPress is expecting that page to exist in the latter location? Any ideas what I need to look into? Thanks for your help.
Ivan Shatsky avatar
gr flag
Yes, WordPress is expecting that page to exists. While in theory it is possible to do a vice versa thing, to rewrite internally `/vernon/72-County-Road-8144` URI to `/for-sale/12356-aaa-72-County-Road-8144-bbb-Vernon` (if you have an algorithm to do a reverse rewrite) and ask WP core to serve a rewritten page while your browser address bar will display an original URL, it seems to me that whatever you are trying to do, you choose a wrong way to do it.
David avatar
my flag
Yeah, I was afraid that I was perhaps going about it the wrong way. Unfortunately it's a real estate plugin that is generating the URL structure that I'm trying to change, and it's not possible to change the permalink structure in the plugin settings to have it display the city first, then address etc. When I contacted the developer they suggested I look into server-side rewrite of the URL. But now I see that with WordPress I can't simply have Nginx rewrite it like I thought.
djdomi avatar
za flag
https://www.cyberciti.biz/faq/how-to-configure-nginx-for-wordpress-permalinks/ might a chance for this permalink solution
Score:0
gr flag

This is not an answer, but it is too long to be a comment, so I'm writing this as an answer.

What you are trying to achieve is possible. However to implement it, you'd need a more complex software stack. You'd need some key-value storage (e.g. Redis), and a web server able to use it while serving a request (e.g. nginx with lua-nginx-module and lua-resty-redis).

Here is (one of the) possible algorithm.

  • After receiving a request, check if the storage contains some value using request URI as a key.
    • If it is, get the value from the storage and use it as an URI for WordPress.
    • If it isn't, check if the URI match our regex pattern.
      • If it is, do the following:
        • generate rewritten URI;
        • store original and rewritten URIs as key/value in the storage;
        • return a redirect with a new URI.
      • If it isn't, serve our request URI usual way.

A complete recipe on implementing this stack is definitely outside the scope for regular ServerFault answer, but you can take this as an idea.

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.