nginx location配置详细解释

324 阅读7分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

location语法详解

语法规则:

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

前缀字符串包含:

@        : 内部重定向=    :精确匹配,优先级最高。如果找到了这个精确匹配,则停止查找。^~   :URI 以某个常规字符串开头,匹配到最长的前缀字符串,则不检查正则表达式。^ 表示 “非”,~ 表示 “正则”,意思是:不要继续匹配正则~    :区分大小写的正则匹配~*   :不区分大小写的正则匹配/    :通用匹配, 优先级最低。任何请求都会匹配到这个规则!~ 和!~* :分别为区分大小写不匹配及不区分大小写不匹配 的正则

优先级为:首先精确匹配 = - 》 其次以xx开头匹配^~ - 》然后是按文件中顺序的正则匹配 ~ ~* -》最后是交给 通用匹配 (不带前缀的 或 /)。

其中 “~ ” 前缀表示匹配区分大小写的正则 location,“* ” 前缀表示匹配不区分大小写的正则 location;其他前缀(包括:“=”,“^ ”和“@ ”)和 无任何前缀的都属于普通 location,= 精确匹配,^~ 不使用正则,@ 内部重定向。

图片.png

当有匹配成功时候,停止匹配,按当前匹配规则处理请求。

例子,有如下匹配规则:

location = / {   #规则A}location = /login {   #规则B}location ^~ /static/ {   #规则C}location ~ \.(gif|jpg|png|js|css)$ { #规则D,注意:是根据括号内的大小写进行匹配。括号内全是小写,只匹配小写}location ~* \.png$ {   #规则E}location !~ \.xhtml$ {   #规则F}location !~* \.xhtml$ {   #规则G}location / {   #规则H}

那么产生的效果如下:

访问根目录/, 比如http://localhost/ 将匹配规则A

访问 http://localhost/login 将匹配规则B,http://localhost/register 则匹配规则H

访问 http://localhost/static/a.html 将匹配规则C

访问 http://localhost/a.gif, http://localhost/b.jpg 将匹配规则D和规则E,但是规则D顺序优先,规则E不起作用, 而 http://localhost/static/c.png 则优先匹配到 规则C

访问 http://localhost/a.PNG 则匹配规则E, 而不会匹配规则D,因为规则E不区分大小写。

访问 http://localhost/a.xhtml 不会匹配规则F和规则G,

http://localhost/a.XHTML不会匹配规则G,(因为!)。规则F,规则G属于排除法,符合匹配规则也不会匹配到,所以想想看实际应用中哪里会用到。

访问 http://localhost/category/id/1111 则最终匹配到规则H,因为以上规则都不匹配,这个时候nginx转发请求给后端应用服务器,比如FastCGI(php),tomcat(jsp),nginx作为方向代理服务器存在。

所以实际使用中,个人觉得至少有三个匹配规则定义,如下:

#直接匹配网站根,通过域名访问网站首页比较频繁,使用这个会加速处理,官网如是说。#这里是直接转发给后端应用服务器了,也可以是一个静态首页# 第一个必选规则location = / {    proxy_pass http://tomcat:8080/index} # 第二个必选规则是处理静态文件请求,这是nginx作为http服务器的强项# 有两种配置模式,目录匹配或后缀匹配,任选其一或搭配使用location ^~ /static/ {                              //以xx开头    root /webroot/static/;}location ~* \.(gif|jpg|jpeg|png|css|js|ico)$ {     //以xx结尾    root /webroot/res/;} #第三个规则就是通用规则,用来转发动态请求到后端应用服务器#非静态文件请求就默认是动态请求,自己根据实际把握location / {    proxy_pass http://tomcat:8080/}

ReWrite语法

last – 基本上都用这个Flag。
break – 中止Rewirte,不在继续匹配
redirect – 返回临时重定向的HTTP状态302
permanent – 返回永久重定向的HTTP状态301

1、下面是可以用来判断的表达式:

-f!-f用来判断是否存在文件
-d!-d用来判断是否存在目录
-e!-e用来判断是否存在文件或目录
-x!-x用来判断文件是否可执行

2、下面是可以用作判断的全局变量

例:http://localhost:88/test1/test2/test.php

$host:localhost$server_port:88$request_uri:http://localhost:88/test1/test2/test.php$document_uri:/test1/test2/test.php$document_root:D:\nginx/html$request_filename:D:\nginx/html/test1/test2/test.php

附:一些可用的全局变量

$args$content_length$content_type$document_root$document_uri$host$http_user_agent$http_cookie$limit_rate$request_body_file$request_method$remote_addr$remote_port$remote_user$request_filename$request_uri$query

if 和 break 指令

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

变量名;如果变量值是空字符串或“0”则为 FALSE。注意,在 1.0.1 版本之前,任何以“0”开头的字符串都会被当做 FALSE。
使用“=”和“!=”的变量跟字符串的比较
使用“”(区分大小写匹配)和“*”(不区分大小写匹配)运算符将变量与正则表达式匹配。正则表达式可以包含捕获,之后可以通过 11 到 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,则返回状态 405Method not allowed)if ($request_method = POST) {    return 405;}#比如我们实现login请求返回 200,但是其他请求都302,可以用如下配置location ~ /login {        return 200 "test";        break;}if ($request_uri  !~ /login) {        return 302 https://www.phpmianshi.com$request_uri;}# 如果通过 set 指令设置了 $slow,限速if ($slow) {    limit_rate 10k;}# 如果请求的文件存在,则开启缓存,并通过 break 停止后面的检查if (-f $request_filename) {    expires max;    break;}# 如果请求的文件、目录或符号链接都不存在,则用 rewrite 在 URI 头部添加 /index.phpif (!-e $request_filename) {    rewrite ^/(.*)$ /index.php/$1 break;}

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

return、rewrite 和 try_files 指令

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

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

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

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;}

对于 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";

rewrite 规则会改变部分或整个用户请求中的 URL,主要有两个用途:

通知客户端,请求的资源已经换地方了。例如网站改版后添加了 www 前缀,通过 rewrite 规则可以将所有请求导向新站点。
控制 Nginx 中的处理流程。例如当需要动态生成内容时,将请求转发到应用程序服务器。try_files 指令经常用于这个目的。

但是,如果需要测试 URL 之间更复杂的区别,或者要从原始 URL 中捕获的元素没有对应的 NGINX 变量,或者更改或添加路径中的元素(例如各大 PHP 框架常用的 index.php 入口文件),该怎么办? 可以使用 rewrite 指令。

rewrite 指令放在 server 或 location 上下文中。语法很简单:

rewrite regex URL [flag];

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

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。11 和 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 文件。假设客户请求“www.domain.com/images/imag… 会首先通过用于这个 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;}

一些常用的配置

1、Redirect(重定向)语法

server {    listen 80;    server_name start.igrow.cn;    index index.html index.php;    root html;    if ($http_host !~ "^star\.phpmianshi\.com$" {        rewrite ^(.*) http://star.phpmianshi.com$1 redirect;    }}

2、防盗链

location ~* \.(gif|jpg|png|bmp)$ {    valid_referers none blocked *.ttlsa.com server_names ~\.google\. ~\.baidu\.;    if ($invalid_referer) {        return 403;        #rewrite ^/ http://www.ttlsa.com/403.jpg;    }}

3、动静分离

思路:动、静态的文件,请求时匹配不同的目录

当访问gif,jpeg时 直接访问e:wwwroot;,正则自行配置

server {    listen       80;    server_name  localhost;    location / {        root   /data/wwwroot;        index  index.html;    }    # 所有静态请求都由nginx处理,存放目录为html    location ~ .(gif|jpg|jpeg|png|bmp|swf|css|js)$ {        root    /data/static;    }    # 所有动态请求都转发给tomcat处理    location ~ .(jsp|do)$ {        proxy_pass  http://test;    }    error_page   500 502 503 504  /50x.html;    location = /50x.html {        root   /data/wwwroot;    }  }