location 配置块介绍

前面章节分别介绍了 nginx 配置文件中 event、http 和 server 配置块,本章节将介绍另一个配置块 location。location 配置块用来配置匹配的不同请求 URL 的处理方式,示例用法:

http {
    #...
    server {
        listen       8080;
        #...
        location / {
            root   html;
            index  index.html index.htm;
        }
        location /example1 {
            // 匹配请求 URL 为 /example1 的请求
            // 在这里为该请求定义配置信息
        }
        location /example2 {
            proxy_pass http://localhost:8080/demo/mng/;
            proxy_cookie_path /demo /;
            proxy_set_header Host $host:$server_port;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_redirect ~^http://localhost:8080/demo/mng/(.*) https://www.demo.com/mng/$1;
            proxy_connect_timeout 4s;
            proxy_read_timeout 60s;
            proxy_send_timeout 8s;
        }
    }
    #...
}

注意:location 配置块只能在 server 配置块中配置,下面将逐一介绍 location 指令以及 location 配置块下面的指令。

location

location 指令是 nginx 中最关键的指令之一,location 指令的功能是用来匹配不同的 URI 请求,进而对请求做不同的处理和响应,其中较难理解的是多个 location 的匹配顺序。

匹配 URI 类型

匹配 URI 类型,有四种参数可选,例如:

location [ = | ~ | ~* | ^~ ] /URI {
    # ...
}

参数说明:

  • 空:location 后没有参数直接跟着标准 URI,表示前缀匹配,代表跟请求中的 URI 从头开始匹配

  • =:用于标准 URI 前,要求请求字符串与其精准匹配,成功则立即处理,nginx 停止搜索其他匹配

  • ^~:用于标准URI前,并要求一旦匹配到就会立即处理,不再去匹配其他的那些个正则 URI,一般用来匹配目录

  • ~:用于正则 URI 前,表示 URI 包含正则表达式,区分大小写

  • ~*:用于正则 URI 前,表示 URI 包含正则表达式,不区分大小写

命名 location

@用来定义一个命名location。主要用于内部重定向,不能用来处理正常的请求。语法如下:

location @/name/ {
    # ...
}

参数说明:

  • @:@ 定义一个命名的 location,@ 定义的 location 名字一般用在内部定向,例如:error_page、try_files 命令中。

用法如下:

location / {
    try_files $uri $uri/ @custom
}

location @custom {
    # ...do something
}

上例中,当尝试访问 url 找不到对应的文件就重定向到我们自定义的命名 location(此处为 custom)。

注意:命名 location 中不能再嵌套其它的命名 location。

URI 匹配顺序

nginx 用两层指令来匹配请求 URI,如下:

第一层:使用 server 指令,通过域名、ip 和端口来做第一层级匹配,当找到匹配的 server 后就进入此 server 的 location 匹配。

第二层:location 的匹配并不完全按照其在配置文件中出现的顺序来匹配,请求 URI 会按如下规则进行匹配:

(1)先精准匹配 = ,精准匹配成功则会立即停止其他类型匹配;

(2)没有精准匹配成功时,进行前缀匹配。先查找带有 ^~ 的前缀匹配,带有 ^~ 的前缀匹配成功则立即停止其他类型匹配。再进行普通前缀匹配(不带参数 ^~ )成功则会暂存,继续查找正则匹配;

(3)= 和 ^~ 均未匹配成功前提下,查找正则匹配 ~ 和 ~* 。当同时有多个正则匹配时,按其在配置文件中出现的先后顺序优先匹配,命中则立即停止其他类型匹配;所有正则匹配均未成功时,返回步骤(2)中暂存的普通前缀匹配(不带参数 ^~ )结果;

以上规则优先级从高到低依次为:

location =    # 精准匹配,优先级最高
location ^~   # 带参前缀匹配
location ~    # 正则匹配(区分大小写)
location ~*   # 正则匹配(不区分大小写)
location /a   # 普通前缀匹配,优先级低于带参数前缀匹配。
location /    # 任何没有匹配成功的,都会匹配这里处理,优先级最低

示例

假如我们有下面的一段配置文件:

location = / {
    # 配置A
}

location / {
    # 配置B
}

location /user/ {
    # 配置C
}

location ^~ /images/ {
    # 配置D
}

location ~* .(gif|jpg|jpeg|png)$ {
    # 配置E
}

匹配实例:

(1)请求 / 精准匹配 A,不再往下查找。

(2)请求 /index.html 匹配 B。首先查找匹配的前缀字符,找到最长匹配是配置 B,接着又按照顺序查找匹配的正则。结果没有找到,因此使用先前标记的最长匹配,即配置 B。

(3)请求 /user/index.html 匹配 C。首先找到最长匹配 C,由于后面没有匹配的正则,所以使用最长匹配C。

(4)请求 /user/1.jpg 匹配 E。首先进行前缀字符的查找,找到最长匹配项 C,继续进行正则查找,找到匹配项 E,因此使用 E。

(5)请求 /images/1.jpg 匹配 D。首先进行前缀字符的查找,找到最长匹配 D。但是,特殊的是它使用了 ^~ 修饰符,不再进行接下来的正则的匹配查找,因此使用 D。这里,如果没有前面的修饰符,其实最终的匹配是 E。大家可以想一想为什么。

(6)请求 /documents/about.html 匹配 B。因为 B 表示任何以 / 开头的 URL 都匹配。在上面的配置中,只有B能满足,所以匹配 B。

proxy_pass

该指令用来设置代理服务器的映射地址,映射地址可以使用 http 或 https 协议,而且地址可以使用域名、IP,以及可选的端口。例如:

proxy_pass http://localhost:8080/demo/mng/;

或者在单词 “unix” 之后指定并用冒号括起来的 UNIX 域套接字路径:

proxy_pass http://unix:/tmp/backend.socket:/uri/;

proxy_cookie_path

该指令的作用是用来改变 cookie 的路径,语法:

proxy_cookie_path path replacement;

参数说明:

  • path:就是你要替换的路径

  • replacement:就是要替换的值

用法示例:

location /example2 {
    proxy_pass http://localhost:8080/demo/mng/;
    proxy_cookie_path /demo /;
}

proxy_set_header

该指令允许重新定义或添加字段到传递给代理服务器的请求头。该值可以包含文本、变量及其组合。当且仅当当前级别上没有定义 proxy_set_header 指令时,这些指令才从先前的配置级别继承。默认情况下,只重新定义了两个字段:

proxy_set_header Host $proxy_host;
proxy_set_header Connection close;

如果启用缓存,来自之前请求的头字段 “If-Modified-Since”, “If-Unmodified-Since”, “If-None-Match”, “If-Match”, “Range”, 和 “If-Range” 将不会被代理服务器传递。

一个不会变化的“Host”头请求字段可通过如下方式被传递:

proxy_set_header Host    $http_host;

然后,当字段不在请求头中就无法传递了,在这种情况下,可通过设置Host变量,将需传递值赋给Host变量。如下:

proxy_set_header Host    $host;

此外,服务器名称和端口一起通过代理服务器传递

proxy_set_header Host    $host:$proxy_port;

proxy_redirect

nginx 的 proxy_redirect 功能比较强大,其作用是对发送给客户端的 URL 进行修改。如果需要修改从被代理服务器传来的应答头中的“Location”和“Refresh”字段,可以用这个指令进行设置。假如被代理服务器返回 Location 字段为:

http://localhost:8000/two/some/uri/

下面指令:

proxy_redirect http://localhost:8000/two/ http://frontend/one/;

将 Location 字段重写为 http://frontend/one/some/uri/。 

在代替的字段中可以不写服务器名: 

proxy_redirect http://localhost:8000/two/ /;

这样就使用服务器的基本名称和端口,即使它来自非 80 端口。 

proxy_connect_timeout

定义与代理服务器建立连接的超时时间,注意:这个超时时间通常不能超过 75 秒。

proxy_read_timeout

定义从代理服务器读取响应的超时时间。超时仅在两次连续读取操作之间设置,而不是针对整个响应的传输。如果代理服务器在此时间内未传输任何内容,则连接将关闭。

proxy_send_timeout

设置将请求传输到代理服务器的超时时间。超时仅设置在两次连续的写操作之间,而不是针对整个请求的传输。如果代理服务器在此时间内没有收到任何信息,则连接将关闭。

说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号