Score:1

Nginx how to make redirect by removing part of URL with regex mask?

tm flag

I need to redirect from URL like example.com/some-urltext-nav.html to example.com/some-urltext.html (remove "-nav" only). I've tried some regular expressions in server block like rewrite ^.*?-nav\.html$/, but nothing happened...

server {
    server_name example.com cdn.example.com www.example.com;
    charset off;
    index index.php index.html;
    disable_symlinks if_not_owner from=$root_path;
    include /etc/nginx/vhosts-includes/*.conf;
    include /etc/nginx/vhosts-resources/example.com/*.conf;
    access_log /var/www/httpd-logs/example.com.access.log;
    error_log /var/www/httpd-logs/example.com.error.log notice;
    ssi on;
    set $root_path /var/www/main/data/www/example.com;
    

    
    
    location / {
    
        location ~ [^/]\.ph(p\d*|tml)$ {
            try_files /does_not_exists @php;
        }
        location ~ ^/(?<capture>.+)-nav\.html$ {
        return 302 /$capture.html;
        }

        location ~* ^.+\.(jpg|jpeg|gif|png|svg|js|css|mp3|ogg|mpe?g|avi|zip|gz|bz2?|rar|swf)$ {
            expires 365d;
        }
    }
    gzip on;
    gzip_comp_level 5;
    gzip_disable "msie6";
    gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript;
    location @php {
        fastcgi_index index.php;
        fastcgi_param PHP_ADMIN_VALUE "sendmail_path = /usr/sbin/sendmail -t -i -f [email protected]";
        fastcgi_pass unix:/var/www/php-fpm/19.sock;
        fastcgi_split_path_info ^((?U).+\.ph(?:p\d*|tml))(/?.+)$;
        try_files $uri =404;
        include fastcgi_params;
    }
    root $root_path;
    listen 95.955.43.229:80;
}
server {
    server_name example.com www.example.com;
    ssl_certificate "/var/www/httpd-cert/main/example.com-to-23-10-2021.crtca";
    ssl_certificate_key "/var/www/httpd-cert/main/example.com-to-23-10-2021.key";
    ssl_ciphers EECDH:+AES256:-3DES:RSA+AES:!NULL:!RC4;
    ssl_prefer_server_ciphers on;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    add_header Strict-Transport-Security "max-age=31536000;";
    ssl_dhparam /etc/ssl/certs/dhparam4096.pem;
    charset off;
    index index.php index.html;
    disable_symlinks if_not_owner from=$root_path;
    include /etc/nginx/vhosts-includes/*.conf;
    include /etc/nginx/vhosts-resources/example.com/*.conf;
    access_log /var/www/httpd-logs/example.com.access.log;
    error_log /var/www/httpd-logs/example.com.error.log notice;
    ssi on;
    set $root_path /var/www/main/data/www/example.com;
    gzip on;
    gzip_comp_level 5;
    gzip_disable "msie6";
    gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript;
    if (!-e $request_filename) { rewrite / /index.php last; }
    
    
    
    location / {
        
        location ~ [^/]\.ph(p\d*|tml)$ {
            try_files /does_not_exists @php;
        }
        
        location ~ ^/(?<capture>.+)-nav\.html$ {
        return 302 /$capture.html;
        }
        
        location ~* ^.+\.(jpg|jpeg|gif|png|svg|js|css|mp3|ogg|mpe?g|avi|zip|gz|bz2?|rar|swf)$ {
            expires 365d;
        }
    }
    location @php {
        fastcgi_index index.php;
        fastcgi_param PHP_ADMIN_VALUE "sendmail_path = /usr/sbin/sendmail -t -i -f [email protected]";
        fastcgi_pass unix:/var/www/php-fpm/19.sock;
        fastcgi_split_path_info ^((?U).+\.ph(?:p\d*|tml))(/?.+)$;
        try_files $uri =404;
        include fastcgi_params;
    }
    root $root_path;
    listen 95.955.43.229:443 ssl http2;
}
Lex Li avatar
vn flag
To see browser address bar changes, you need to return 30x redirection responses. That's not what rewrite can achieve.
Oleksandr avatar
tm flag
@LexLi, could you provide me with an exact code please?
sv flag
@LexLi rewrites can do redirects as well. Ref: https://nginx.org/r/rewrite
Lex Li avatar
vn flag
Thanks, @PothiKalimuthu. I were referring to general rewrite/redirect, not the `rewrite` directive.
Score:0
us flag

The following snippet should match your expectations:

location ~ ^(?<prefix>/.+?)-nav(?<suffix>\.html)$ {
    return 301 https://$host$prefix$suffix;
}

The regular expression captures the parts before and after the keyword to variables, which are then used for forming the return statement URL.

Update:

Your configuration has

location ~ [^/]\.ph(p\d*|tml)$ {

before the rule above. This rule matches any path that ends with ml. Therefore nginx uses that location for any request ending with html.

You need to swap the places of the two location blocks to make sure nginx evaluates the first one.

Also, this regular expression looks quite "leaky". You might want to reconsider what exactly you want the regular expression to match and make sure it matches only those items.

Oleksandr avatar
tm flag
thank you, but it is not working - nothing changes
us flag
Please add your full nginx configuration as shown by `nginx -T` to the question.
Oleksandr avatar
tm flag
Just added the config
sv flag
The code by @TeroKilkanen works fine for me. Even though, I could've simplified it to `location ~ ^/(?<capture>.+)-nav\.html$ { return 302 /$capture.html; }`
Lex Li avatar
vn flag
@Oleksandr you should use a privacy tab of your web browser for testing. "nothing changes" is often due to the cached redirection by the normal tabs.
Oleksandr avatar
tm flag
@PothiKalimuthu Thank you, but it still not working for me. I've just edited my config in my question above with your snippet
us flag
I updated my answer with one possible cause for the behavior.
Oleksandr avatar
tm flag
I've swapped the places of the two location blocks - still no effect
I sit in a Tesla and translated this thread with Ai:

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.