简体   繁体   English

nginx 使用 OR 设置为地图的正则表达式

[英]nginx using OR set at regex for the map

I'm trying to write a map for my website and it's working great:我正在尝试为我的网站编写地图,并且效果很好:

map $request_uri $redirect_uri {
  /en/oldname    /en/newname;
  /de/oldname    /de/newname;
  /fr/oldname    /fr/newname;
}

until I try to implement some regex, something like this:直到我尝试实现一些正则表达式,如下所示:

map $request_uri $redirect_uri {
  /(?<lang>(en|de|fr))/oldname    /$lang/newname;
}

The map above is not working, and due to the lack of debugging knowledge - I'm unable to know why.上面的地图不起作用,并且由于缺乏调试知识 - 我不知道为什么。 Even the basic regex (without using named captures) is not working for me:即使是基本的正则表达式(不使用命名捕获)也不适合我:

map $request_uri $redirect_uri {
  /(en|de|fr)/oldname    /en/newname;
}

nginx 1.10.3 nginx 1.10.3

Please help me to figure out what am I doing wrong?请帮我弄清楚我做错了什么?

Mike, you should use “~” symbol to indicate a regular expression. Mike,你应该使用“~”符号来表示正则表达式。

Look at here Module ngx_http_map_module看这里模块 ngx_http_map_module

A regular expression should either start from the “~” symbol for a case-sensitive matching, or from the “~*” symbols (1.0.4) for case-insensitive matching.正则表达式应该从“~”符号开始用于区分大小写的匹配,或者从“~*”符号(1.0.4)开始用于不区分大小写的匹配。 A regular expression can contain named and positional captures that can later be used in other directives along with the resulting variable.正则表达式可以包含命名和位置捕获,稍后可以与结果变量一起在其他指令中使用。

The right configuration should be:正确的配置应该是:

map $request_uri $redirect_uri {
  ~/(?<lang>(en|de|fr))/oldname    /$lang/newname;
}

Good luck!祝你好运!


2017.07.13 edited 2017.07.13 编辑

Here is the full configuration based on the default configuration(echo directive is provided by nginx-echo-module)这里是基于默认配置的完整配置(echo 指令由 nginx-echo-module 提供)

#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;
    map $request_uri $redirect_uri {
      ~/(?<lang>(en|de|fr))/oldname    /$lang/newname;
    }

    server {
        listen       80;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            echo $redirect_uri;
        }

        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
        #    proxy_pass   http://127.0.0.1;
        #}

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #location ~ \.php$ {
        #    root           html;
        #    fastcgi_pass   127.0.0.1:9000;
        #    fastcgi_index  index.php;
        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        #    include        fastcgi_params;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
    }


    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    #    listen       8000;
    #    listen       somename:8080;
    #    server_name  somename  alias  another.alias;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}


    # HTTPS server
    #
    #server {
    #    listen       443 ssl;
    #    server_name  localhost;

    #    ssl_certificate      cert.pem;
    #    ssl_certificate_key  cert.key;

    #    ssl_session_cache    shared:SSL:1m;
    #    ssl_session_timeout  5m;

    #    ssl_ciphers  HIGH:!aNULL:!MD5;
    #    ssl_prefer_server_ciphers  on;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}

}

And this is my test case:这是我的测试用例:

yxr nginx # curl localhost/en/oldname
/en/newname
yxr nginx # curl localhost/de/oldname
/de/newname
yxr nginx # curl localhost/fr/oldname
/fr/newname
yxr nginx # curl localhost/cn/oldname

yxr nginx #

2017.07.14 edited 2017.07.14 编辑

As @Mike pointed out, this requires at least nginx/1.11.0 .正如@Mike 指出的,这至少需要nginx/1.11.0

In regards to mononoke's answer.关于mononoke的回答。 You don't need the extra set of parentheses in the pattern matching, and that could give some unexpected results for certain pcre engines as you are technically adding another group within the lang group.您不需要在模式匹配中使用额外的一组括号,这可能会给某些 pcre 引擎带来一些意想不到的结果,因为您在技术上在 lang 组中添加了另一个组。

~/(?<lang>en|de|fr)/oldname    /$lang/newname;
map $http_user_agent $loggable {
    "~kube-probe"   0;
    default         1;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM