如何在 Nginx 服务器上执行不区分大小写的正则表达式?

How to do case insensitive regex on an Nginx server?

将服务器从 Ubuntu 迁移到 Debian 后出现严重问题。 Debian 不允许两个文件,例如“a.html”和“A.html”位于同一目录中。

我的服务器收到三种类型的请求,这是当前状态:

请求如/archive/2014/www.Test.com随文件一起提供:/archive/2014/blank.html

/archive/2015/Test.com/archive/2015/www.Test.com 等请求随文件一起提供 /archive/2015/T.html

/archive/2015/test.com/archive/2015/www.test.com 等请求随文件一起提供 /archive/2015/t.html

我希望最后两种类型的请求在两种情况下(以不区分大小写的方式)提供文件 /archive/2015/t.html

我怎样才能达到这个结果?

当前服务器设置为:

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/.html last; 

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

}

有很多方法可以解决这个问题。

  1. 由于您只需要将一个特定字母更改为小写,您可以将 "map" 与不区分大小写的正则表达式一起使用:

    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. 如果你安装了嵌入式 Perl 模块(sudo apt-get install nginx-extras),你可以使用 Perl 将请求行变成小写:

    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/.html last;
    
        error_page  403  /403.html;
        error_page  404  /404.html;
    }
    
  3. 如果你更喜欢 Lua 而不是 Perl,你可以用 Lua 做同样的事情(同样,你需要安装 nginx-extras):

    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/.html last;
    
        error_page  403  /403.html;
        error_page  404  /404.html;
    }
    
  4. 如果您不喜欢以上所有内容,总有一些 Nginx 的黑暗技巧可以提供帮助(但我真的不推荐它):

    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/.html last;
    
        error_page  403  /403.html;
        error_page  404  /404.html;
    }