Nginx 配置 location 以及 return、rewrite 和 try_files 指令

时间:2022-09-26 23:46:09

正则表达式

Nginx 使用 perl 语法的正则表达式。

正则表达式的用法可以参考 这里

Nginx 内置的全局变量

https://moonbingbing.gitbooks.io/openresty-best-practices/openresty/inline_var.html

location

在 Nginx 的配置文件中,通过 location 匹配用户请求中的 URI。格式如下:

location 前缀字符串  URL {
[ 配置 ]
}

前缀字符串及优先级

其中,前缀字符串部分支持 5 种:

  • =:精确匹配,优先级最高。如果找到了这个精确匹配,则停止查找。
  • ^~:URI 以某个常规字符串开头,不是正则匹配
  • ~:区分大小写的正则匹配
  • ~*:不区分大小写的正则匹配
  • /:通用匹配, 优先级最低。任何请求都会匹配到这个规则

优先级为: = > 完整路径 > ^~ > ~~* > 部分起始路径 > /

示例

# 精确匹配 / ,域名后面不能带任何字符串。匹配到后,停止继续匹配
location = / { } # 匹配到所有请求
location / {
if (-f $request_filename) {
expires max;
break;
}
if (!-e $request_filename) {
rewrite ^/(.*)$ /index.php/$1 break;
}
index index.php;
autoindex off;
} # 匹配任何以 /documents/ 开头的 URI。优先级低于正则表达式,匹配到后还会继续往下匹配,当后面没有正则匹配或正则匹配失败时,使用这里代码
location /documents/ {
} # 最长字符匹配到 /images/abc,继续往下,会发现 ^~ 存在
location /images/abc {
} # 匹配任何以 /images/ 开头的 URI。优先级高于正则表达式,匹配成功后,停止往下搜索正则。
location ^~ /images/ {
} # 正则匹配,区分大小写。匹配任何以 /documents/Abc 开头的地址,匹配符合以后,还要继续往下搜索
location ~ /documents/Abc {
} # 正则匹配,忽略大小写。匹配所有以 gif、jpg 或 jpeg 结尾的请求
location ~* \.(gif|jpg|jpeg)$ {
}

location 匹配原则

可以 参考这篇译文

每个请求的处理逻辑顺序如下:

  1. 用所有的前缀字符串测试 URI。
  2. 等号 = 定义了前缀字符串和 URI 的精确匹配关系。如果找到了这个精确匹配,则停止查找。
  3. 如果 ^~ 修饰符预先匹配到最长的前缀字符串,则不检查正则表达式。
  4. 存储最长的匹配前缀字符串。
  5. 用正则表达式测试 URI。
  6. 匹配到第一个正则表达式后停止查找,使用对应的 location。
  7. 如果没有匹配到正则表达式,则使用之前存储的前缀字符串对应的 location。

if 和 break 指令

可以参考 Nginx 模块 - ngx_http_rewrite_module

if

if 的可用上下文有:server、location。if 的条件可能是以下任何一种情况:

变量名;如果变量值是空字符串或“0”则为 FALSE。注意,在 1.0.1 版本之前,任何以“0”开头的字符串都会被当做 FALSE。

使用“=”和“!=”的变量跟字符串的比较

使用“~”(区分大小写匹配)和“~*”(不区分大小写匹配)运算符将变量与正则表达式匹配。正则表达式可以包含捕获,之后可以通过 $1$9 这几个变量名重复使用。“!~”和“!~*”用作不匹配运算符。如果正则表达式包含“}”或“;”字符,则整个表达式应该用单引号或双引号括起来。

用“-f”和“!-f”运算符检查文件是否存在

用“-d”和“!-d”运算符检查目录是否存在

用“-e”和“!-e”运算符检查文件、目录或符号链接的存在性

用“-x”和“!-x”运算符检查可执行文件

示例:

# 如果用户代理 User-Agent 包含"MSIE",rewrite 请求到 /msie/ 目录下。通过正则匹配的捕获可以用 $1 $2 等使用
if ($http_user_agent ~ MSIE) {
rewrite ^(.*)$ /msie/$1 break;
} # 如果 cookie 匹配正则,设置变量 $id 等于匹配到的正则部分
if ($http_cookie ~* "id=([^;]+)(?:;|$)") {
set $id $1;
} # 如果请求方法为 POST,则返回状态 405(Method not allowed)
if ($request_method = POST) {
return 405;
} # 如果通过 set 指令设置了 $slow,限速
if ($slow) {
limit_rate 10k;
} # 如果请求的文件存在,则开启缓存,并通过 break 停止后面的检查
if (-f $request_filename) {
expires max;
break;
} # 如果请求的文件、目录或符号链接都不存在,则用 rewrite 在 URI 头部添加 /index.php
if (!-e $request_filename) {
rewrite ^/(.*)$ /index.php/$1 break;
}

break

break 的可用上下文有:server、location、if。用于停止处理当前的 ngx_http_rewrite_module 指令集合。

if ($slow) {
limit_rate 10k;
break;
}

return、rewrite 和 try_files 指令

NGINX rewrite 的两个通用指令是 returnrewrite,而 try_files 指令可以将请求定向到应用程序服务器。

return 指令

return 指令手册

在重定向满足两个条件时适用:

  • 重写的 URL 适用于每个匹配的 serverlocation 的请求
  • 可以使用标准的 NGINX 变量构建重写的 URL

return 指令简单高效,建议尽量使用 return,而不是 rewrite

return 指令放在 serverlocation 上下文中。语法很简单:

return code [text];
return code URL;
return URL;

将客户重定向到一个新域名的示例:

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 指令放在 serverlocation 上下文中。语法很简单:

rewrite regex URL [flag];

第一个参数 regex 是正则表达式。

flag 标志位

flag 支持以下 4 个选项:

  • last:停止处理当前的 ngx_http_rewrite_module 指令集,并开始对匹配更改后的 URI 的新 location 进行搜索(再从 server 走一遍匹配流程)。此时对于当前 serverlocation 上下文,不再处理 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 指令也放在 serverlocation 上下文中。语法很简单:

try_files file ... uri;

try_files 指令的参数是一个或多个文件或目录的列表,以及最后面的 URI 参数。

Nginx 会按顺序检查文件及目录是否存在(根据 rootalias 指令设置的参数构造完整的文件路径),并用找到的第一个文件提供服务。在元素名后面添加斜杠 / 表示这个是目录。如果文件和目录都不存在,Nginx 会执行内部重定向,跳转到命令的最后一个 uri 参数定义的 URI 中。

要想 try_files 指令工作,必须定义一个 location 块捕捉内部重定向。最后一个参数可以是命名过的 location,由初始符号(@)指示。

try_files 指令通常使用 $uri 变量,表示 URL 中域名之后的部分。

下面示例中,如果客户端请求的文件不存在,Nginx 会响应一个默认的 GIF 文件。假设客户请求“http://www.domain.com/images/image1.gif”,Nginx 会首先通过用于这个 location 的 rootalias 指令,在本地目录中查找这个文件。如果“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;
}

Nginx 配置 location 以及 return、rewrite 和 try_files 指令的更多相关文章

  1. nginx配置location总结及rewrite规则写法【转】

    转自 nginx配置location总结及rewrite规则写法 | Sean's Noteshttp://seanlook.com/2015/05/17/nginx-location-rewrite ...

  2. Nginx配置location总结及rewrite规则写法

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 32.0px "Helvetica Neue"; color: #323333 } p. ...

  3. 转:Nginx 配置 location 总结及 rewrite 规则写法

    转: http://www.linuxidc.com/Linux/2015-06/119398.htm 1. location正则写法 一个示例: location =/{ # 精确匹配 / ,主机名 ...

  4. 【转】nginx配置location总结及rewrite规则写法

    原文:http://seanlook.com/2015/05/17/nginx-location-rewrite/ 1. location正则写法 location = / { # 精确匹配 / ,主 ...

  5. nginx配置location总结及rewrite规则写法(转)

    一个示例: location = / { # 精确匹配 / ,主机名后面不能带任何字符串 [ configuration A ] } location / { # 因为所有的地址都以 / 开头,所以这 ...

  6. nginx配置location总结及rewrite规则写法 (若配置reload或restart不生效就stop start)

    location正则写法 一个示例: location = / { # 精确匹配 / ,主机名后面不能带任何字符串 [ configuration A ] } location / { # 因为所有的 ...

  7. (转)nginx配置location总结及rewrite规则写法

    注: rewrite 只能对域名后边的除去传递的参数外的字符串起作用,并且要写全域名后面的部分,如: http://i.com:9090/php/midou/admin.php/index/login ...

  8. nginx配置location总结及rewrite规则写法(2)

    2. Rewrite规则 rewrite功能就是,使用nginx提供的全局变量或自己设置的变量,结合正则表达式和标志位实现url重写以及重定向.rewrite只能放在server{},location ...

  9. nginx配置location总结及rewrite规则写法(1)

    1. location正则写法 一个示例: location = / { # 精确匹配 / ,主机名后面不能带任何字符串 [ configuration A ] } location / { # 因为 ...

随机推荐

  1. 使用命令行执行webpagetest进行测试

    背景 使用webpagetest进行性能分析,需要一个一个url的去执行,需要人为去等,比较繁琐.而api很好的解决了这个问题,可以通过命令行等执行测试,也可以写成一个常规脚本,针对每个版本的常规ur ...

  2. PHP无限分类分类导航LINK的代码

    <?php function getCatePath($cid,&$result=array()){ include("conn.php"); $sql=" ...

  3. Leetcode 102&period; Binary Tree Level Order Traversal(二叉树的层序遍历)

    Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to right, ...

  4. &lbrack;Javascript&rsqb; Gradient Fills on the HTML5 Canvas

    window.onload = function() { var canvas = document.getElementById("canvas"), context = can ...

  5. JSP引擎的工作原理

    JSP运行环境: 执行JSP代码需要在服务器上安装JSP引擎,比较常见的引擎有WebLogic和Tomcat.把这些支持JSP的web服务器配置好后.就可以再客户端通过浏览器来访问JSP页面了.默认端 ...

  6. 【数据库】数据库的锁机制,MySQL中的行级锁&comma;表级锁&comma;页级锁

    转载:http://www.hollischuang.com/archives/914 数据库的读现象浅析中介绍过,在并发访问情况下,可能会出现脏读.不可重复读和幻读等读现象,为了应对这些问题,主流数 ...

  7. php配置文件php&period;ini的详细解析&lpar;续&rpar;

    file_uploads = On                                                                                 // ...

  8. java spring属性注入

    一.创建对象时候,向类里面属性设置值:一般有三个方式 1) .有参构造, 2). set**** 3).接口注入 二. 在spring框架里面,支持前面两种方式: 1).有参构造方法  用constr ...

  9. IDEA的这八条配置你一定要改!

    一定要改的八条军规.快捷键使用idea默认的,与其他同事保存一致 自动编译开关 忽略大小写开关 智能导包开关 悬浮提示开关 取消单行显示tabs的操作 项目文件编码 滚轴修改字体大小 设置行号显示 在 ...

  10. Netbeans 8&period;1 检测不到Tomcat8&period;5&period;3以上版本已经启动的Bug

    Tomcat实际上已经启动,但是netbeans就是检测不到,只要在server.xml中,找到http/1.1的connector 添加 属性 server="Apache-Coyote/ ...