zoukankan      html  css  js  c++  java
  • Nginx 配置 location 以及 return、rewrite 和 try_files 指令

    正则表达式

    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;
    }
  • 相关阅读:
    WebForm中使用MVC
    CPAN镜像使用帮助
    关于XML文档的xmlns、xmlns:xsi和xsi:schemaLocation
    XML之命名空间的作用(xmlns)
    xml相关术语说明
    .NET Core系列 : 1、.NET Core 环境搭建和命令行CLI入门
    BZOJ3734 : [Ontak2013]Miny
    BZOJ3448 : [Usaco2014 Feb]Auto-complete
    BZOJ3476 : [Usaco2014 Mar]The Lazy Cow
    BZOJ3619 : [Zjoi2014]璀灿光华
  • 原文地址:https://www.cnblogs.com/kika/p/10851587.html
Copyright © 2011-2022 走看看