ngx_http_rewrite_module提供的rewrite指令

Syntax:	rewrite regex replacement [flag];
Default:	—
Context:	server, location, if

如果请求的URI匹配指定的正则表达式regex,URI会被改变为replacement字符串指定的值。rewrite指令会按照它们在配置文件中出现的顺序依次执行。可以通过使用flag标记,来终止这个指令的进一步处理,如果replacement字符串以http://https://开头,那么会终止处理,并返回重定向给客户端。
可选的flag参数是下面中的一个:

完整的重定向URL是根据请求模式($scheme)和server_name_in_redirect指令、port_in_redirect指令来形成的。
下面是一个例子:

server {
    ...
    rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 last;
    rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra  last;
    return  403;
    ...
}

但是,如果这些指令被放到了download location中,那么应该使用break标记来替换last标记,否则Nginx会循环执行10次,并返回500错误。

location /download/ {
    rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 break;
    rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra  break;
    return  403;
}

如果replacement字符串包含新的请求参数,那么之前的请求参数会被追加到它们的后面。如果不希望把之前的请求参数追加到新的请求参数的后面,那么需要在replacement字符串的结尾放一个问号。
下面是一个例子:

rewrite ^/users/(.*)$ /show?user=$1? last;

如果正则表达式中,包含右花括号(})或分号(;),那么整个正则表达式应该使用单引号或双引号括起来。


server_name指令

Syntax:	server_name name ...;
Default:	
server_name "";
Context:	server  

设置虚拟主机的名称。比如:

server {
    server_name example.com www.example.com;
}

第一个名字是主server name,可以使用星号(*)来作为server name的第一部分或最后一部分。比如:

server {
    server_name example.com *.example.com www.example.*;
}

这些名称被称为通配名称。同时:

server {
    server_name .example.com;
}

等价于:

server {
    server_name example.com *.example.com;
}

也可以在server_name中使用正则表达式,正则表达式以波浪线(~)开头:

server {
    server_name www.example.com ~^www\d+\.example\.com$;
}

正则表达式可以包含分组,捕获的分组可以在后面的其他指令中使用,比如:

server {
    server_name ~^(www\.)?(.+)$;

    location / {
        root /sites/$2;
    }
}

server {
    server_name _;

    location / {
        root /sites/default;
    }
}

可以通过在正则表达式中包含命名的分组,来创建变量,比如:

server {
    server_name ~^(www\.)?(?<domain>.+)$;

    location / {
        root /sites/$domain;
    }
}

server {
    server_name _;

    location / {
        root /sites/default;
    }
}

如果将server name设置为$hostname,那么会使用机器的主机名称。
也可以指定一个空的server name:

server {
    server_name www.example.com "";
}

它允许该虚拟主机处理不带Host头的请求。
在下面的server段例子中,可以看到奇怪的名称-下划线(_):

server {
    listen       80  default_server;
    server_name  _;
    return       444;
}

其实,下划线这个名字没有什么特别的,它仅仅是一个许多无效的server name中的一个代表,与任何真实的server name永远不会相交。其它无效的server name,如“ - ” 和“ !@# ”,也可以使用。
default_server:nginx是通过HTTP请求中的Host头来搜索虚拟主机的,如果找不到,那么nginx就会将请求发送到指定了default_server的虚拟主机来处理。
当使用名称搜索虚拟主机的时候,如果名称匹配多个虚拟主机(比如www.example.com既匹配*.example.com,又匹配~^www.(?<domain>.+)$),那么按照下面的优先级,第一个匹配的虚拟主机会被选择:


server_name_in_redirect指令

Syntax:	server_name_in_redirect on | off;
Default:	
server_name_in_redirect off;
Context:	http, server, location

用来控制:当Nginx发起重定向的时候,开启或关闭主server name的使用(server_name指令的第一个参数就是主server name)。当关闭的时候,会使用Host请求头中的名称,如果没有Host请求头,那么使用服务器的IP地址。
重定向使用的端口,是有port_in_redirect指令来控制的。


port_in_redirect指令

Syntax:	port_in_redirect on | off;
Default:	
port_in_redirect on;
Context:	http, server, location

用来控制:当Nginx发起重定向的时候,开启或关闭指定的端口。
重定向使用的主server name是由server_name_in_redirect指令控制的。


使用中常见的一些问题

在下面这个例子中,会将所有发送到9091端口的请求,转发给9090端口,通过proxy_pass这种方式解决了:浏览器或其他HTTP客户端向重定向URL发起的都是GET请求这个问题,示例配置文件如下所示:

user root;
worker_processes  4;  

events {
    worker_connections  1024;
}

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

    server {
        listen       9090;
        server_name  timd.cn;

        location = /rewrite_to{
            default_type text/plain;
            echo "request method is:$request_method, query string is:$query_string, uri is:$uri.";
        }   

        location = /rewrite_from{
            rewrite ^ /rewrite_to last;
        }   
    } 
    server {
        resolver 8.8.8.8;
        listen 9091;
        server_name timd.cn;

        location / { 
            proxy_pass http://$server_name:9090;
        }   
    }
}

参考文档