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
参数是下面中的一个:
last
ngx_http_rewrite_module
指令集,开始搜索匹配改变后的URI location
(也就是会在当前server标签中使用改变后的URI重新发起匹配)
break
ngx_http_rewrite_module
指令集
redirect
replacement
字符串不以http://
或https://
开头时使用
permanent
完整的重定向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>.+)$
),那么按照下面的优先级,第一个匹配的虚拟主机会被选择:
*.example.com
mail.*
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
指令控制的。
rewrite regex replacement [flag]
,当replacement字符串以http://
或https://
开头,那么rewrite会终止处理,并返回重定向给客户端。所以此时不应该使用last
和break
修饰符。
permanent
和redirect
修饰符的时候,浏览器地址栏的地址会改变,因为使用这两个修饰符的时候,服务器给浏览器返回重定向(301或302),在Location
响应头中包含了重定向URL,最后是由浏览器自动的向重定向URL发起请求。last
和break
修饰符,表示纯粹的内部重定向,浏览器地址栏地址不会发生变化。
permanent
或redirect
修饰符的时候,浏览器或其它HTTP客户端向重定向URL发起的请求都是GET请求。
在下面这个例子中,会将所有发送到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; } } }