server {
listen 80;
listen 443 ssl;
server_name www.old-name.com;
return 301 $scheme://www.new-name.com$request_uri;
上面代码中,listen 指令表明 server 块同时用于 HTTP 和 HTTPS 流量。server_name
指令匹配包含域名 ‘www.old-name.com’ 的请求。return
指令告诉 Nginx 停止处理请求,直接返回 301 (Moved Permanently)
代码和指定的重写过的 URL 到客户端。$scheme
是协议(HTTP 或 HTTPS),$request_uri
是包含参数的完整的 URI。
对于 3xx 系列响应码,url
参数定义了新的(重写过的)URL:
return (301 | 302 | 303 | 307) url;
对于其他响应码,可以选择定义一个出现在响应正文中的文本字符串(HTTP 代码的标准文本,例如 404 的 Not Found,仍包含在标题中)。文本可以包含 NGINX 变量。
return (1xx | 2xx | 4xx | 5xx) ["text"];
例如,在拒绝没有有效身份验证令牌的请求时,此指令可能适用:
return 401 "Access denied because token is expired or invalid";
通过 error_page 指令,可以为每个 HTTP 代码返回一个完整的自定义 HTML 页面,也可以更改响应代码或执行重定向。
rewrite 指令
NGINX Rewrite 规则官方文档
Rewrite 模块手册
HTTP 响应码
rewrite 规则会改变部分或整个用户请求中的 URL,主要有两个用途:
通知客户端,请求的资源已经换地方了。例如网站改版后添加了 www 前缀,通过 rewrite 规则可以将所有请求导向新站点。
控制 Nginx 中的处理流程。例如当需要动态生成内容时,将请求转发到应用程序服务器。try_files
指令经常用于这个目的。
但是,如果需要测试 URL 之间更复杂的区别,或者要从原始 URL 中捕获的元素没有对应的 NGINX 变量,或者更改或添加路径中的元素(例如各大 PHP 框架常用的 index.php
入口文件),该怎么办? 可以使用 rewrite
指令。
rewrite
指令放在 server
或 location
上下文中。语法很简单:
rewrite regex URL [flag];
第一个参数 regex 是正则表达式。
flag 标志位
flag 支持以下 4 个选项:
last:停止处理当前的 ngx_http_rewrite_module 指令集,并开始对匹配更改后的 URI 的新 location 进行搜索(再从 server 走一遍匹配流程)。此时对于当前 server
或 location
上下文,不再处理 ngx_http_rewrite_module 重写模块的指令。
break:停止处理当前的 ngx_http_rewrite_module 指令集
redirect:返回包含 302 代码的临时重定向,在替换字符串不以“http://”,“https://”或“$scheme”开头时使用
permanent:返回包含 301 代码的永久重定向。
last 和 break 的区别及共同处:
last 重写 url 后,会再从 server 走一遍匹配流程,而 break 终止重写后的匹配
break 和 last 都能阻止后面的 rewrite 指令再次执行
rewrite
指令只能返回代码 301 或 302。要返回其他代码,需要在 rewrite
指令后面包含 return
指令。
rewrite
指令不一定会暂停 NGINX 对请求的处理,因为它不一定会发送重定向到客户端。除非明确指出(使用 flag 或 URL 的语法)你希望 NGINX 停止处理或发送重定向,否则它将在整个配置中运行,查找在重写模块中定义的指令(break、if、return、rewrite 和 set),并按顺序处理。如果重写的 URL 与 Rewrite 模块中的后续指令匹配,NGINX 会对重写的 URL 执行指定的操作(通常会重新写入)。
这是复杂的地方,必须仔细计划指令顺序以获得期望的结果。例如,如果原始 location 块和其中的 NGINX 重写规则与重写的 URL 匹配,NGINX 可以进入一个循环,Nginx 默认限制循序最大 10 次。
下面是使用 rewrite
指令的 NGINX 重写规则的示例。它匹配以字符串 /download
开头的 URL,然后用 /mp3/
替换在路径稍后的某个位置包含的 /media/
或 /audio/
目录,并添加适当的文件扩展名 .mp3
或 .ra
。$1
和 $2
变量捕获不变的路径元素。例如,/download/cdn-west/media/file1
变为 /download/cdn-west/mp3/file1.mp3
。如果文件名上有扩展名(例如.flv),表达式会将其剥离并用.mp3替换。
server {
rewrite ^(/download/.*)/media/(\w+)\.?.*$ $1/mp3/$2.mp3 last;
rewrite ^(/download/.*)/audio/(\w+)\.?.*$ $1/mp3/$2.ra last;
return 403;
可以将 flag 添加到重写指令来控制处理流程。示例中的 last 告诉 NGINX 跳过当前服务器或位置块中的任何后续 ngx_http_rewrite_module 重写模块的指令,并开始搜索与重写的 URL 匹配的新位置。
这个例子中的最后一个 return
指令意味着如果 URL 不匹配任何一个 rewrite
指令,将返回给客户端 403 代码。
try_files 指令
try_files
指令也放在 server
或 location
上下文中。语法很简单:
try_files file ... uri;
try_files
指令的参数是一个或多个文件或目录的列表,以及最后面的 URI 参数。
Nginx 会按顺序检查文件及目录是否存在(根据 root
和 alias
指令设置的参数构造完整的文件路径),并用找到的第一个文件提供服务。在元素名后面添加斜杠 /
表示这个是目录。如果文件和目录都不存在,Nginx 会执行内部重定向,跳转到命令的最后一个 uri 参数定义的 URI 中。
要想 try_files
指令工作,必须定义一个 location 块捕捉内部重定向。最后一个参数可以是命名过的 location,由初始符号(@)指示。
try_files
指令通常使用 $uri
变量,表示 URL 中域名之后的部分。
下面示例中,如果客户端请求的文件不存在,Nginx 会响应一个默认的 GIF 文件。假设客户请求“http://www.domain.com/images/image1.gif”,Nginx 会首先通过用于这个 location 的 root
和 alias
指令,在本地目录中查找这个文件。如果“image1.gif”文件不存在,Nginx 会查找“image1.gif/”目录,如果都不存在,会重定向到“/images/default.gif”。这个值精确匹配后面的 location 指令,因此处理过程停止,Nginx 返回这个文件,并标注其缓存 30 秒。
location /images/ {
try_files $uri $uri/ /images/default.gif;
location = /images/default.gif {
expires 30s;