How to only redirect urls located in a nginx Map

11,060

I found a solution for your problem on serverfault:

This is probably failing because you're trying to redirect all requests, whether they matched something in the map or not.

To prevent this, check to see if there was a match first.

if ($new) {
    return 301 $new;
}

So replace

rewrite ^ $new redirect;

with

if ($new) {
    return 301 $new;
}

And you should be good to go

Share:
11,060
askmike
Author by

askmike

I'm Mike, a student and webdeveloper based in Amsterdam.

Updated on June 29, 2022

Comments

  • askmike
    askmike almost 2 years

    I am in the process of moving my blog from a.com to b.com. Now I want to tell Google /bookmarks that all blogposts (around 100) have been moved to b.com. I only want to redirect the blogposts and nothing else.

    After reading about the map module in nginx I tried the following:

    map_hash_bucket_size 128;
    map $uri $new {
      /post http://b.com/post
      # (repeated for all 100 posts)
    }
    

    And when I put the following line inside the server block:

    rewrite ^ $new redirect;
    

    It will redirect all 100 posts but all the other pages on my domain will error with: 302 Found.

    Here is my whole server block inside the config:

    server {
    
        listen 80;
        server_name b.com;
        root /my/old/path/;
        index index.html;
    
        location = /favicon.ico {
                log_not_found off;
                access_log off;
        }
    
        location = /robots.txt {
                allow all;
                log_not_found off;
                access_log off;
        }
    
        # Deny all attempts to access hidden files such as .htaccess, .htpasswd, .DS_Store (Mac).
        location ~ /\. {
            deny all;
            access_log off;
            log_not_found off;
        }
    
        location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
               expires max;
               log_not_found off;
        }
    
        # example.com/index gets redirected to example.com/
    
        location ~* ^(.*)/index$ {
            return 301 $scheme://$host$1/;
        }
    
        # example.com/foo/ loads example.com/foo/index.html
    
        location ~* ^(.*)/$ {
            try_files $1/index.html @backend;
        }
    
        # example.com/a.html gets redirected to example.com/a
    
        location ~* \.html$ {
            rewrite ^(.+)\.html$ $scheme://$host$1 permanent;
        }
    
        # anything else not processed by the above rules:
        # * example.com/a will load example.com/a.html
        # * or if that fails, example.com/a/index.html
    
        location / {
            try_files $uri.html $uri/index.html $uri @backend;
        }
    
        # default handler
        # * return error or redirect to base index.html page, etc.
        location @backend {
            try_files /404.html 404;
        }
    
        location ~ \.php$ {
                expires off;
                try_files $uri =404;
                fastcgi_split_path_info ^(.+\.php)(/.+)$;
                #NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
    
                include fastcgi_params;
                fastcgi_index index.php;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                fastcgi_intercept_errors on;
                fastcgi_pass php;
        }
    
        # apply the rewrite map
        rewrite ^ $new redirect;
    }
    

    I am thinking the map interferes with the try_files call for location \ (which I need).