Tom
Tom

Reputation: 9643

How to do case insensitive regex on an Nginx server?

A serious problem happened after migrating a server from Ubuntu to Debian. Debian won't allow two files, for example "a.html" and "A.html" to be in the same directory.

My server gets three types of requests and this is the current status:

requests such as /archive/2014/www.Test.com are supplied with the file: /archive/2014/blank.html

requests such as /archive/2015/Test.com and /archive/2015/www.Test.com are supplied with the file /archive/2015/T.html

requests such as /archive/2015/test.com and /archive/2015/www.test.com are supplied with the file /archive/2015/t.html

I want the last two types of requests to supply the file /archive/2015/t.html in both cases (in an case insensitive way).

How could I achieve this outcome?

The current server settings are:

server {
    listen   127.0.0.1:80;
    server_name 127.0.0.1;

    access_log /srv/siteone/logs/access.log;
    error_log /srv/siteone/logs/error.log error;

    location / {
        root   /srv/siteone/html;
        index  index.html index.htm;
        expires 1d;
    }

    rewrite ^/archive/2014/(.+)$ /archive/2014/blank.html last;
    rewrite ^/archive/2015/(www\.)*(.)(.+)$ /archive/2015/$2.html last; 

    error_page  403  /403.html;
    error_page  404  /404.html;

}

Upvotes: 3

Views: 1713

Answers (1)

Ivan Tsirulev
Ivan Tsirulev

Reputation: 2811

There are plenty of ways you can go about this problem.

  1. Since you need to change only one specific letter to lowercase, you could use "map" with case insensitive regular expression:

    map $request $letter {
        "~*^/archive/[0-9]{4}/(www\.)?a(.*)?$"  a;
        "~*^/archive/[0-9]{4}/(www\.)?b(.*)?$"  b;
        "~*^/archive/[0-9]{4}/(www\.)?c(.*)?$"  c;
        "~*^/archive/[0-9]{4}/(www\.)?d(.*)?$"  d;
        "~*^/archive/[0-9]{4}/(www\.)?e(.*)?$"  e;
        "~*^/archive/[0-9]{4}/(www\.)?f(.*)?$"  f;
        "~*^/archive/[0-9]{4}/(www\.)?g(.*)?$"  g;
        "~*^/archive/[0-9]{4}/(www\.)?h(.*)?$"  h;
        "~*^/archive/[0-9]{4}/(www\.)?i(.*)?$"  i;
        "~*^/archive/[0-9]{4}/(www\.)?j(.*)?$"  j;
        "~*^/archive/[0-9]{4}/(www\.)?k(.*)?$"  k;
        "~*^/archive/[0-9]{4}/(www\.)?l(.*)?$"  l;
        "~*^/archive/[0-9]{4}/(www\.)?m(.*)?$"  m;
        "~*^/archive/[0-9]{4}/(www\.)?n(.*)?$"  n;
        "~*^/archive/[0-9]{4}/(www\.)?o(.*)?$"  o;
        "~*^/archive/[0-9]{4}/(www\.)?p(.*)?$"  p;
        "~*^/archive/[0-9]{4}/(www\.)?q(.*)?$"  q;
        "~*^/archive/[0-9]{4}/(www\.)?r(.*)?$"  r;
        "~*^/archive/[0-9]{4}/(www\.)?s(.*)?$"  s;
        "~*^/archive/[0-9]{4}/(www\.)?t(.*)?$"  t;
        "~*^/archive/[0-9]{4}/(www\.)?u(.*)?$"  u;
        "~*^/archive/[0-9]{4}/(www\.)?v(.*)?$"  v;
        "~*^/archive/[0-9]{4}/(www\.)?w(.*)?$"  w;
        "~*^/archive/[0-9]{4}/(www\.)?x(.*)?$"  x;
        "~*^/archive/[0-9]{4}/(www\.)?y(.*)?$"  y;
        "~*^/archive/[0-9]{4}/(www\.)?z(.*)?$"  z;
    }
    
    server {
        listen   127.0.0.1:80;
        server_name 127.0.0.1;
    
        access_log /srv/siteone/logs/access.log;
        error_log /srv/siteone/logs/error.log error;
    
        root   /srv/siteone/html;
    
        location / {
            index  index.html index.htm;
            expires 1d;
        }
    
        rewrite ^/archive/2014/(.+)$ /archive/2014/blank.html last;
        rewrite ^/archive/2015/(www\.)?(.)(.+)$ /archive/2015/$letter.html last; 
    
        error_page  403  /403.html;
        error_page  404  /404.html;
    }
    
  2. If you have Embedded Perl module installed (sudo apt-get install nginx-extras), you could use Perl to get the request line into lowercase:

    perl_set $uri_lowercase 'sub {
        my $r = shift;
        return lc($r->uri);
    }';
    
    server {
        listen   127.0.0.1:80;
        server_name 127.0.0.1;
    
        access_log /srv/siteone/logs/access.log;
        error_log /srv/siteone/logs/error.log error;
    
        root   /srv/siteone/html;
    
        location / {
            index  index.html index.htm;
            expires 1d;
        }
    
        rewrite ^/archive/2014/(.+)$ /archive/2014/blank.html last;
        rewrite ^/archive/2015/(www\.)?(.)(.+)$ $uri_lowercase;
        rewrite ^/archive/2015/(www\.)?(.)(.+)$ /archive/2015/$2.html last;
    
        error_page  403  /403.html;
        error_page  404  /404.html;
    }
    
  3. If you prefer Lua before Perl, you could do the same with Lua (again, you will need nginx-extras installed):

    server {
        listen   127.0.0.1:80;
        server_name 127.0.0.1;
    
        access_log /srv/siteone/logs/access.log;
        error_log /srv/siteone/logs/error.log error;
    
        root   /srv/siteone/html;
    
        location / {
            index  index.html index.htm;
            expires 1d;
        }
    
        rewrite ^/archive/2014/(.+)$ /archive/2014/blank.html last;
        rewrite_by_lua 'ngx.req.set_uri(string.lower(ngx.var.uri), false)';
        rewrite ^/archive/2015/(www\.)?(.)(.+)$ /archive/2015/$2.html last;
    
        error_page  403  /403.html;
        error_page  404  /404.html;
    }
    
  4. If you don't like all of the above, there is always some dark Nginx trickery that could help (but I really don't recommend it):

    server {
        listen   127.0.0.1:8484;
    
        access_log off;
    
        rewrite ^.*$ /archive/2015/$host.html;
    
        root /srv/siteone/html;
    
        location / {
            index  index.html index.htm;
            expires 1d;
        }
    }
    
    server {
        listen   127.0.0.1:80;
        server_name 127.0.0.1;
    
        access_log /srv/siteone/logs/access.log;
        error_log /srv/siteone/logs/error.log error;
    
        root   /srv/siteone/html;
    
        location / {
            index  index.html index.htm;
            expires 1d;
        }
    
        location ~* ^/archive/2015/(?<letter>[A-Z])\.html$ {
            proxy_set_header Host $letter;
            proxy_pass http://127.0.0.1:8484;
        }
    
        rewrite ^/archive/2014/(.+)$ /archive/2014/blank.html last;
        rewrite ^/archive/2015/(www\.)?(.)(.+)$ /archive/2015/$2.html last;
    
        error_page  403  /403.html;
        error_page  404  /404.html;
    }
    

Upvotes: 1

Related Questions