nginx server配置正则表达式资料
字符 |
说明 |
^ |
匹配输入字符串的开始位置。要匹配 “^” 字符本身,请使用 “\^” |
$ |
匹配输入字符串的结尾位置。要匹配 “$” 字符本身,请使用 “\$” |
( ) |
标记一个子表达式的开始和结束位置。要匹配小括号,请使用 “\(” 和 “\)” |
[ ] |
用来自定义能够匹配 ‘多种字符’ 的表达式。要匹配中括号,请使用 “\[” 和 “\]” |
{ } |
修饰匹配次数的符号。要匹配大括号,请使用 “\{” 和 “\}” |
. |
匹配除了换行符(\n)以外的任意一个字符。要匹配小数点本身,请使用 “\.” |
? |
修饰匹配次数为 0 次或 1 次。要匹配 “?” 字符本身,请使用 “\?” |
+ |
修饰匹配次数为至少 1 次。要匹配 “+” 字符本身,请使用 “\+” |
* |
修饰匹配次数为 0 次或任意次。要匹配 “*” 字符本身,请使用 “\*” |
| |
左右两边表达式之间 “或” 关系。匹配 “|” 本身,请使用 “\|” |
例:
location = /
#匹配任何查询,因为所有请求都已 / 开头。但是正则表达式规则和长的块规则将被优先和查询匹配
location ^~ /images/ {
# 匹配任何已/images/开头的任何查询并且停止搜索。任何正则表达式将不会被测试。
location ~* .(gif|jpg|jpeg)$ {
# 匹配任何已.gif、.jpg 或 .jpeg 结尾的请求
-f和!-f用来判断是否存在文件
-d和!-d用来判断是否存在目录
-e和!-e用来判断是否存在文件或目录
-x和!-x用来判断文件是否可执行
所有的Nginx内置变量都可以通过if指令和正则表达式来进行匹配,并且根据匹配结果进行一些操作,如下:
代码如下 | |
if ($http_user_agent ~ MSIE) { rewrite ^(.*)$ /msie/$1 break; } if ($http_cookie ~* “id=([^;] +)(?:;|$)” ) { set $id $1; } |
Nginx在很多模块中都有内置的变量,常用的内置变量在HTTP核心模块中,这些变量都可以使用正则表达式进行匹配。
Nginx 一些内置的变量
HTTP核心模块支持一些内置变量,变量名与apache里的对应。比如 $http_user_agent,$http_cookie等表示HTTP请求信息的变量。
更多变量:
$args, 请求中的参数;
$content_length, HTTP请求信息里的”Content-Length”;
$content_type, 请求信息里的”Content-Type”;
$document_root, 针对当前请求的根路径设置值;
$document_uri, 与$uri相同;
$host, 请求信息中的”Host”,如果请求中没有Host行,则等于设置的服务器名;
$limit_rate, 对连接速率的限制;
$request_method, 请求的方法,比如”GET”、”POST”等;
$remote_addr, 客户端地址;
$remote_port, 客户端端口号;
$remote_user, 客户端用户名,认证用;
$request_filename, 当前请求的文件路径名
$request_body_file, ??
$request_uri, 请求的URI,带参数;
$query_string, 与$args相同;
$scheme, 所用的协议,比如http或者是https,比如rewrite ^(.+)$ $scheme://example.com$1 redirect;
$server_protocol, 请求的协议版本,”HTTP/1.0″或”HTTP/1.1″;
$server_addr, 服务器地址,如果没有用listen指明服务器地址,使用这个变量将发起一次系统调用以取得地址(造成资源浪费);
$server_name, 请求到达的服务器名;
$server_port, 请求到达的服务器端口号;
$uri, 请求的URI,可能和最初的值有不同,比如经过重定向之类的。
location
可能这个指令是我们平时使用正则匹配用的最多的指令:
代码如下 | |
location ~ .*.PHP?$ { |
几乎每个基于LEMP的主机都会有如上一段代码。他的匹配规则类似于if指令,不过他多了三个标识符,^~、=、@。并且它没有取反运算符!,这三个标识符的作用分别是:
1.^~ 标识符后面跟一个字符串。
Nginx将在这个字符串匹配后停止进行正则表达式的匹配(location指令中正则表达式的匹配的结果优先使用),如:location ^~ /images/.
你希望对/images/这个目录进行一些特别的操作,如增加expires头,防盗链等,但是你又想把除了这个目录的图片外的所有图片只进行增加expires头的操作,
这个操作可能会用到另外一个location,例如:location ~* .(gif|jpg|jpeg)$,这样,如果有请求/images/1.jpg,nginx如何决定去进行哪个location中的操作呢?
结果取决于标识符^~,如果你这样写:location /images/,这样nginx会将1.jpg匹配到location ~* .(gif|jpg|jpeg)$这个location中,这并不是你需要的结果,
而增加了^~这个标识符后,它在匹配了/images/这个字符串后就停止搜索其它带正则的location。
2.= 表示精确的查找地址,如location = /它只会匹配uri为/的请求,如果请求为/index.html,将查找另外的location,而不会匹配这个,
当然可以写两个location,location = /和location /,这样/index.html将匹配到后者,如果你的站点对/的请求量较大,可以使用这个方法来加快请求的响应速度。
3.@ 表示为一个location进行命名,即自定义一个location,这个location不能被外界所访问,只能用于Nginx产生的子请求,主要为error_page和try_files。
@示例代码如下 | |
error_page 404 = @fetch; location @fetch { proxy_pass https://目标网站; proxy_redirect off; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header REMOTE-HOST $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } |
注意,这3个标识符后面不能跟正则表达式,虽然配置文件检查会通过,而且没有任何警告,但是他们并不会进行匹配。
综上所述,location指令对于后面值的匹配顺序为:
1.标识符“=”的location会最先进行匹配,如果请求uri匹配这个location,将对请求使用这个location的配置。
2.进行字符串匹配,如果匹配到的location有^~这个标识符,匹配停止返回这个location的配置。
3.按照配置文件中定义的顺序进行正则表达式匹配。最早匹配的location将返回里面的配置。
4.如果正则表达式能够匹配到请求的uri,将使用这个正则对应的location,如果没有,则使用第二条匹配的结果。
server_name
server_name用于配置基于域名或IP的虚拟主机,这个指令也是可以使用正则表达式的,但是注意,这个指令中的正则
表达式不用带任何的标识符,但是必须以~开头:
代码如下 | |
server { server_name www.example.com ~^wwwd+.example.com$; } |
server_name指令中的正则表达式可以使用引用,高级的应用可以查看这篇文章:在server_name中使用正则表达式
fastcgi_split_path_info
这个指令按照CGI标准来设置SCRIPT_FILENAME (SCRIPT_NAME)和PATH_INFO变量,它是一个被分割成两部分(两个引用)的正则表达式。如下:
代码如下 | |
location ~ ^.+.php { (…) fastcgi_split_path_info ^(.+.php)(.*)$; fastcgi_param SCRIPT_FILENAME /path/to/php$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info; (…) } |
第一个引用(.+.php)加上/path/to/php将作为SCRIPT_FILENAME,第二个引用(.*)为PATH_INFO,例如请求的完整URI为show.php/article/0001,
则上例中SCRIPT_FILENAME的值为/path/to/php/show.php,PATH_INFO则为/article/0001。
这个指令通常用于一些通过PATH_INFO美化URI的框架(例如CodeIgniter)。
gzip_disable
通过正则表达式来指定在哪些浏览器中禁用gzip压缩。
gzip_disable “msie6”;
rewrite
这个指令应该也是用的比较多的,它需要使用完整的包含引用的正则表达式:
代码如下 | |
rewrite “/photos/([0-9] {2})([0-9] {2})([0-9] {2})” /path/to/photos/$1/$1$2/$1$2$3.png; |
通常环境下我们会把它和if结合来使用:
代码如下 | |
if ($host ~* www.(.*)) { |
Nginx中的正则如何匹配中文
首先确定在编译pcre时加了enable-utf8参数,如果没有,请重新编译pcre,然后就可以在Nginx的配置文件中使用这样的正则:”(*UTF8)^/[x{4e00}-x{9fbf}]+)$”
注意引号和前面的(*UTF8),(*UTF8)将告诉这个正则切换为UTF8模式。
代码如下 | |
[root@backup conf]# pcretest re> /^[x{4e00}-x{9fbf}]+/8 |
location顺序错误导致下载.php源码而不执行php程序的问题
看下面的例子片断(server段、wordpress安装到多个目录):
代码如下 | |
location / { location /user1/ { location ~* ^/(user2|user3)/ { location ~ .php$ { |
nginx.conf的配置代码看上去没有任何问题,而事实上:
访问 /user1/会正常执行php程序。
访问 /user2/ 或 /user3/ 都不会执行程序,而是直接下载程序的源代码。
原因在哪里?看到他们的区别了吗?
/user1/是普通location写法
而/user2/ 或 /user3/ 是正则表达式匹配的location
问题就出在了/user2/ 或 /user3/匹配location指令使用了正则表达式,所以必须注意代码段的先后顺序,必须把location ~ .php$ {…}段上移、放到它的前面去。
正确的代码举例:
=====================================
代码如下 | |
location / { location /user1/ { location ~ .php$ { location ~* ^/(user2|user3)/ { |
=====================================
【注意】对于普通location指令行,是没有任何顺序的要求的。如果你也遇到了类似的问题,可以尝试调整使用正则表达式的location指令片断的顺序来调试
噢!评论已关闭。