【003】Nginx学习笔记-Location详解,alias,正则表达式,if,rewrite模块
1 location 详解
文档:http://nginx.org/en/docs/http/ngx_http_rewrite_module.html#if
location用于匹配客户请求uri,如上面URL中的加粗部分
- 语法:
location [修饰符] /uri|pattern {...}
修饰符:
符号 | 含义 | 实例 | |
---|---|---|---|
= | 精确匹配 | 优先级最高 | location = /test |
^~ | 前缀匹配 | 优先级高于正则匹配 | location ^~ /test/ |
~ | 正则匹配 | 区分大小写 | location ~ \.(jpg|png|gif)${…} |
~* | 正则匹配 | 不区分大小写 | |
没有修饰符 | 优先级最低 |
无修饰符的情况也表示uri前缀匹配,但优先级低于正则匹配
若uri为/,表示匹配所有.其他location未匹配到的均能匹配到
- 优先级顺序:
1. location = /uri
2. location ^~ /uri
3. location ~ pattern location ~* pattern
4. location /uri
5. location / 可匹配所有的访问请求
注:
1). 优先级的高低与location出现的顺序无关
2). 尽量使用单一的location修饰符去完成任务。不要混合多种修饰符去作业,以免出现优先级问题。
看到一个 很好的文章 nginx 正则匹配配置 https://www.cnblogs.com/xiao-xue-di/p/15079370.html#_label0
Alias
alias指令用于定义指定路径的替换路径。
用法:
比如下面配置:
location /i/ {
alias /data/w3/images/;
}
“/i/top.gif” 将由 /data/w3/images/top.gif文件来响应。
path的值可以包含变量,但不能使用$document_root和 $realpath_root这两个变量。
如果在定义了正则表达式的路径中使用了alias,那么正则表达式中应该含有匹配组, 并且alias应该引用这些匹配组(0.7.40版)来组成一个完整的文件路径,比如:
location ~ ^/users/(.+\.(?:gif|jpe?g|png))$ {
alias /data/w3/images/$1; # $1: 引用上面第一个分组的内容
}
如果路径对应指令path值的最后一部分:
location /images/ {
alias /data/w3/images/;
}
最好换用root指令:
location /images/ {
root /data/w3;
}
nginx 正则表达式
Nginx-if
语法:
if (condition) { ... }
默认值: —
上下文: server, location
如果condition为真,执行定义在大括号中的rewrite模块指令。if指令会从上一层配置中继承配置。
condition可以是下列任意一种:
• 变量名: 如果变量值为空或者是0,则条件为假(在1.0.1版本以前,任何以0开头的值都为假);
• 使用“=”和“!=”运算符比较变量和字符串;
• 使用“”(大小写敏感)和“*”(大小写不敏感)运算符匹配变量和正则表达式。正则表达式可以包含匹配组,匹配结果后续可以使用变量$1…$9引用。如果正则表达式中包含字符“}”或者“;”,整个表达式应该被包含在单引号或双引号的引用中。
• 使用“-f”和“!-f”运算符检查文件是否存在;
• 使用“-d”和“!-d”运算符检查目录是否存在;
• 使用“-e”和“!-e”运算符检查文件、目录或符号链接是否存在;
• 使用“-x”和“!-x”运算符检查可执行文件;
举例:
if ($http_user_agent ~ MSIE) { # 一般正则不用加引号
rewrite ^(.*)$ /msie/$1 last; # ^(.*)$是匹配到的所有内容(URL)rewrite为/msie/$1,$1 是之前的 (.*) last
}
例如 http//www.server1.com/abc.html
=> http//www.server1.com/msie/abc.html
if ($http_cookie ~* "id=([^;]+)(?:;|$)") { # 当正则中包含}或;时,必须使用引号将整个正则引起来
set $id $1;
}
if ($request_method = POST) {
return 405;
} //如果提交方法为POST,则返回状态405(Method not allowed)。return不能返回301,302
if (!-f $request_filename){
break;
proxy_pass http://127.0.0.1;
} //如果请求的文件名不存在,则反向代理到localhost 。这里的break也是停止rewrite检查
if ($args ~ post=140){
rewrite ^ http://example.com/ permanent;
} //如果query string中包含"post=140",永久重定向到example.com
location ~* \.(gif|jpg|png|swf|flv)$ {
valid_referers none blocked www.jefflei.com www.leizhenfang.com;
if ($invalid_referer) {
return 404;
} //防盗链
}
if ($slow) {
limit_rate 10k;
} //限速,$slow可以通过 set 指令设置
if ($invalid_referer) {
return 403;
}
Nginx-rewrite
rewrite指令可以说是rewrite指令集中的核心指令。它通过正则表达式的使用改变URI。
可以同时存在一个或者多个指令,按照顺序依次对URL进行匹配和处理。
- 先执行server中的rewrite(如果有的话),得到新的URI, 只执行一次(无论修饰符是last还是break);
- 在location中匹配新的URI;
- 执行location中的rewrite(如果有的话), 如果修饰符是last,重写之后得到新的URI, 再在location中匹配新的URI; 如果修饰符是break,重写后得到新的URI,不再进行location匹配.
语法: rewrite regex replacement [flag];
regex - 用于匹配URI的正则表达式。使用"()"标记要截取的内容。
注意:
rewrite 接受到的URL不包含HOST地址和参数,因此regex不可能匹配到URI的HOST地址或参数。
如:
请求的URL为http://myweb.com/source?arg1=value1&arg2=value2
此时rewrite指令接受到的URI 是 "/source", 而不不包含"myweb.com",也不包含"?arg1=value1&arg2=value2"
replacement - 匹配成功后用于替换URI 中被截取内容的字符串
默认情况下,如果该字符串是由"http://" 或"https://" 开头的, 则不会继续对URI 进行处理,而是直接将重写后的URI返回给客户端。
如果replacement字符串包括新的请求参数,以往的请求参数会添加到新参数后面。
如果不希望这样,在replacement字符串末尾加一个问号“?”,就可以避免,比如: rewrite ^/users/(.*)$ /show?user=$1? last;
flag - 有break、last、permanent、redirect
last - 停止执行当前这一轮的ngx_http_rewrite_module指令集,然后查找匹配改变后URI的新location;
break - 停止执行当前这一轮的ngx_http_rewrite_module指令集;
redirect - 返回状态码为302的临时重定向;
permanent - 返回状态码为301的永久重定向。
例:
1.如果UA包含"MSIE",rewrite请求到/msid/目录下
if ($http_user_agent ~ MSIE) {
rewrite ^(.*)$ /msie/$1 break;
}
2.如果query string中包含"post=140",则永久重定向到example.com
if ($args ~ post=140) {
rewrite ^ http://example.com/ permanent;
}