本文由码农网 –
Dee1024原创翻译,转载请看清文末的转载要求,欢迎参与我们的付费投稿计划!

正则表达式的语法就不多说了,大家可以自己搜索查阅相关资料学习。本文所举例子是在《JavaScript语言精粹》上看到的,看完之后对正则表达式有了进一步的理解,故分享之。

一、Nginx 正则及 location 匹配

1.Nginxlocation
规则匹配

^~      
标识符匹配后面跟一个字符串。匹配字符串后将停止对后续的正则表达式进行匹配,
如 location ^~
,在匹配了这个字符串后就停止对后续的正则匹配

=         精准匹配,如 location = /,只会匹配 url 为/的请求

~         区分大小写的匹配

~*       不区分大小写的匹配

!~        对区分大小写的匹配取非

!~*      对不区分大小写的匹配取非

/          通用匹配, 如果没有其它匹配,任何请求都会被匹配到

2、正则表达式

*              重复前面的字符 0 次或多次

?              重复前面的字符 0 次或 1 次

+              重复前面的字符 1 次或多次

.               匹配除换行符以外的任意 1 个字符

(a|b)         匹配 a 或 b

^              以…开头

$              以…结尾

{n}          重复前面的字符 n 次

{n,}         重复前面的字符 n 次或更多次

{n,m}       重复前面的字符 n 到 m 次

*?            重复前面的字符 0 次或多次,但尽可能少重复

+?            重复前面的字符 1 次或更多次,但尽可能少重复

??             重复前面的字符 0 次或 1 次,但尽可能少重复

{n,m}?      重复前面的字符 n 到 m 次,但尽可能少重复

{n,}?        重复前面的字符 n 次以上,但尽可能少重复

3、正则表达式补充:

\W         匹配任意不是字母,数字,下划线,汉字的字符

\S          匹配任意不是空白符的字符

\D          匹配任意非数字的字符

\B          匹配不是单词开头或结束的位置

[a]         匹配单个字符a

[a-z]      匹配 a-z 小写字母的任意一个

[^a]       匹配除了 a 以外的任意字符

[^abc]    匹配除了 abc 这几个字母以外的任意字符

4、Nginx location 应用规则

location [=|~|~*|^~|!~|!~*] /url/{…}

默认值:no

使用字段:server

location 参数根据 URL
的不同需求来进行配置,可以使用字符串与正则表达式匹配,

location = / {

# 精确匹配 / ,主机名后面不能带任何字符串

[ configuration A ]

}

location / {

# 因为所有的地址都以 / 开头,所以这条规则将匹配到所有请求

# 但是正则和最长字符串会优先匹配

[ configuration B ]

location /documents/ {

# 匹配任何以 /documents/
开头的地址,匹配符合以后,还要继续往下搜索

#
只有后面的正则表达式没有匹配到时,这一条才会采用这一条

[ configuration C ]

}

location ~ /documents/Abc {

# 匹配任何以 /documents/
开头的地址,匹配符合以后,还要继续往下搜索

#
只有后面的正则表达式没有匹配到时,这一条才会采用这一条

[ configuration CC ]

}

location ^~ {

# 匹配任何以
开头的地址,匹配符合以后,停止往下搜索正则,采用这一条。

[ configuration D ]

}

location ~* \.(gif|jpg|jpeg)$ {

# 匹配所有以 gif,jpg 或 jpeg 结尾的请求

# 然而,所有请求 下的图片会被
config D 处理,因为 ^~ 到达不了这一条正则

[ configuration E ]

}

location {

# 字符匹配到 ,继续往下,会发现
^~ 存在

[ configuration F ]

}

location {

# 最长字符匹配到 ,继续往下,会发现 ^~ 存在

# F 与 G 的放置顺序是没有关系的

[ configuration G ]

}

location ~ / {

# 只有去掉 config D 才有效:先最长匹配 config G
开头的地址,继续往下搜索,匹配到这 一条正则,采用

[ configuration H ]

}

匹配顺序优先级:

(location =) > (location 完整路径) > (location ^~ 路径) >
(location ~,~* 正则顺 序) > (location 部分起始路径) > (/)

按照上面的 location 匹配,分析以下案例:

/ ->config A

精确完全匹配,即使/index.html 也匹配不了

/downloads/download.html ->config B

匹配 B 以后,往下没有任何匹配,采用 B

 

.gif -> configuration D

匹配到 B,往下匹配到 D,停止往下

/def ->config D

最长匹配到 G,往下匹配 D,停止往下

你可以看到 任何以开头的都会匹配到 D 并停止,FG
写在这里是没有任何意义的, H 是永远轮不到的,这里只是为了说明匹配顺序

/documents/document.html ->config C

匹配到 C,往下没有任何匹配,采用 C

/documents/1.jpg -> configuration E

匹配到 C,往下正则匹配到 E

/documents/Abc.jpg ->config CC

最长匹配到 C,往下正则顺序匹配到 CC,不会往下到 E

 

实际使用建议

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

#直接匹配网站根,通过域名访问网站首页比较频繁,使用这个会加速处理。这里是直接转
发给后端应用服务器了,也可以是一个静态首页。

# 第一个必选规则

location = / {

      proxy_pass

}

# 第二个必选规则是处理静态文件请求,这是 nginx 作为 http 服务器的强项

# 有两种配置模式,目录匹配或后缀匹配,任选其一或搭配使用

location ^~ /static/ {

              root /usr/local/nginx/html/static/;

}

location ~* \.(gif|jpg|jpeg|png|css|js|ico)$ {

              root /webroot/res/;

}

#第三个规则就是通用规则,用来转发动态请求到后端应用服务器,非静态文件请求就默认
是动态请求,自己根据实际把握。

#毕竟目前的一些框架的流行,带.php,.jsp 后缀的情况很少了

location / {

             proxy_pass

}

 

二、Nginx Rewrite 规则

        rewrite 功能就是,使用 nginx
提供的全局变量或自己设置的变量,结合正则表达式和 标志位实现 url
重写以及重定向。rewrite 只能放在 server{},location{},if{}中,并且只
能对域名后边的除去传递的参数外的字符串起作用           Nginx 的 Rewrite
规则采用 PCRE(Perl compatible Regular Expressions)Perl 兼容
正则表达式的语法进行规则匹配,如果需要Ningx的Rewrite功能,在编译安装Nginx之前,
必须安装 PCRE 库。

例如: 只对 URL
中的 /a/we/index.php 等字符串起作用。

URL 是 Uniform Resource Location 的缩写,译为“统一资源定位符”。
如:

语法:

rewrite 正则表达式 更换目标 [标志位];

        rewrite 和 location 功能有点像,都能实现跳转。主要区别在于
rewrite 是在同一域名内 更改获取资源的路径,而 location
是对路径做控制访问或反向代理,可以使用 proxy_pass 到
其他机器。很多情况下 rewrite 也会写在 location 里,它们的执行顺序是:

  1. 执行 server 块的 rewrite 指令

  2. 执行 location 匹配

  3. 执行选定的 location 中的 rewrite 指令

注意:如果其中某步 URI 被重写,则重新循环执行
1-3,直到找到真实存在的文件;循环超 过 10 次,则返回 500 Internal Server
Error 错误。

 

flag 标志位

※ last : 相当于 Apache 的[L]标记,表示完成 rewrite

※ break : 本条规则匹配完成后,终止匹配,不再匹配后面的规则

※ redirect : 返回 302 临时重定向,浏览器地址栏会显示跳转后的 URL 地址

※ permanent : 返回 301 永久重定向,浏览器地址栏会显示跳转后的 URL 地址

last 一般写在 server 和 if 中,而 break 一般使用在 location 中

last 不终止重写后的 url 匹配,即新的 url 会再从 server
走一遍匹配流程,而 break 终止重写 后的匹配

break 和 last 都能组织继续执行后面的 rewrite 指令

last 和 break 用来实现 URI 重写,浏览器地址栏 URL 地址不变 redirect 和
permanent 用来实现 URL 跳转,浏览器地址栏会显示跳转后的 URL 地址

 

if 指令与全局变量

if 判断指令

语法为 if(condition){…},对给定的条件 condition
进行判断。如果为真,大括号内的 rewrite 指令将被执行,if
条件(conditon)可以是如下任何内容:

当表达式只是一个变量时,如果其值为空或任何以 0
开头的字符串时都会当作条件为 false

直接比较变量和内容时,使用=或!=

-f 和!-f 用来判断是否存在文件

-d 和!-d 用来判断是否存在目录

-e 和!-e 用来判断是否存在文件或目录

-x 和!-x 用来判断文件是否可执行

例如: if ($http_user_agent ~ MSIE) {

            rewrite ^(.*)$ /msie/$1 break;

          } //如果 UA 包含”MSIE”,rewrite 请求到/msid/目录下

         if ($request_method = POST) {

             return 405;

          } //如果提交方法为 POST,则返回状态 405(Method not
allowed)。 return 不能返回 301,302

注意:因为返回 301 和 302 不能只返回状态码,还必须有重定向的 URL,所以
return 指令 无法返回 301,302。 

 

if ($slow) {

limit_rate 10k;

} //限速,$slow 可以通过 set 指令设置 

if (!-f $request_filename){

break;

proxy_pass ;

} //如果请求的文件名不存在,则反向代理到 localhost 。这里的 break
也是停止 rewrite 检 查

if ($args ~ post=140){

rewrite ^ 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;

}//防盗链

}

Nginx 变量

下面是可以用作 if 判断的变量

$args:                              
 记录请求行中的参数,同$query_string

$content_length:                 记录请求头中的 Content-length 字段。

$content_type:                    记录请求头中的 Content-Type 字段。

$document_root:                 记录当前请求在 root 指令中指定的值。

$host :                              
记录请求主机头字段,否则为服务器名称。

$http_user_agent:               记录用于记录客户端浏览器的相关信息

$http_cookie:                      记录客户端 cookie 信息
$limit_rate: 记录可以限制连接速率。

$request_method:               记录客户端请求的动作,通常为 GET 或
POST。

$request_filename:              记录当前请求的文件路径,由 root 或
alias 指令与 URI 请求生成。

$scheme :                          记录 HTTP 方法(如 http,https)。

$server_protocol:                记录请求使用的协议,通常是 HTTP/1.0
或 HTTP/1.1。

$server_addr:                    
记录服务器地址,在完成一次系统调用后可以确定这个值。

$server_name:                    记录服务器名称。

$server_port:                      记录请求到达服务器的端口号。

$request_uri:                       记录包含请求参数的原始
URI,不包含主机名,如:” /foo/bar.php?arg=baz”。

$uri:                                    记录不带请求参数的当前
URI,$uri 不包含主机名,如”/foo/bar.html”。 $document_uri:            
       与$uri 相同。

$http_x_forwarded_for           记录远程客户端的 ip 地址

$remote_addr:                     记录远程客户端的 IP 地址。

$remote_port:                      记录远程客户端的端口。

$remote_user                        记录远程客户端用户名称

$time_local                            记录访问时间及时区

$request                               记录请求的 URL 与 HTTP 协议

$status                                 记录请求的状态,例如成功时为
200,页面找不到时为 404

$body_byte_sent                   记录发送给客户端的文件主体内容大小

$http_referer                         记录是从哪个页面链接访问过来的

URL 分析:

$host:localhost $server_port:88

$request_uri:

$documenturi:/test1/test2/test.php

$document_root:/var/www/html

$request_filename:/var/www/html/test1/test2/test.php

Nginx 日志案例:

log_format main ‘$remote_addr – $remote_user [$time_local]
“$request” ‘

‘$status $body_bytes_sent “$http_referer” ‘

‘”$http_user_agent” “$http_x_forwarded_for”‘;

//IP 地址-用户名 [本地时间] “请求”

//状态码主体内容大小“访问来源链接”

//”浏览器信息”“客户端 IP 地址”

192.168.200.2 – -[21/Nov/2016:10:14:57
+0800]”GET /
HTTP/1.1″3040″-“”Mozilla/4.0 (compatible; MSIE 7.0;
Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR
3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.3;
.NET4.0C; .NET4.0E)”

示例,如果访问的 URL 以”*.sh” “*.bash”结尾,则返回状态码 403

location ~ .*\.(sh|bash)?$ {

return 403;

}

将原来要访问/data 目录重写为/bbs

rewrite ^/data/?$ /bbs/ permanent;

防止盗链

localtion ~*\.(gif|jpg|png|swf|flv)${

valid_referers none blocked www.test.com *.test.com;

if($incalid_referer){

rewrite ^/(.*);

    }

}

实现域名跳转

所有对 www.360buy.com 的访问,rewrite 到 www.jd.com

server {

listen 80;

server_name www.jd.com;

charset utf-8;

root html;

index index.html index.htm;

if ($host = “www.360buy.com”) {

rewrite ^/(.*)$ permanent;

}

}

三、Nginx 静动分离

实验环境:两台服务器

192.168.200.102         Nginx 服务器

192.168.200.101         LAMP 服务器

实验时注意观察是在哪台服务器上进行的配置!看清主机名!

LAMP rpm 方式搭建

图片 1图片 2

[root@LAMP ~]# yum -y install httpd mysql mysql-server php php-mysql

[root@LAMP ~]# vim /etc/httpd/conf/httpd.conf

276 ServerName www.example.com:80

402 DirectoryIndex index.php index.html index.html.var

[root@LAMP ~]# httpd -t

Syntax OK

[root@LAMP ~]# /etc/init.d/httpd start

正在启动 httpd:                                                               [确定]

[root@LAMP ~]# /etc/init.d/mysqld start

正在启动mysqld:                                                              [确定]

[root@LAMP ~]# mysqladmin -uroot password '123123'

[root@LAMP ~]# mysql -uroot -p123123

[root@LAMP ~]# vim /var/www/html/mysql.php

<?php

$link=mysql_connect('localhost','root','123123');

if($link) echo "恭喜你,数据库连接成功啦!!";

mysql_close();

?>

View Code

 

 

宿主机测试: 

图片 3

 

搭建 Nginx,配置动静分离

1、源码包编译安装 Nginx

图片 4图片 5

[root@nginx ~]# yum -y install pcre-devel zlib-devel gcc gcc-c++ make

[root@nginx ~]# useradd -M -s /sbin/nologin nginx

[root@nginx ~]# tar xf nginx-1.6.2.tar.gz -C /usr/src/

[root@nginx ~]#cd /usr/local/nginx-1.6.2/

[root@nginx ~]#./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_stub_status_module&& make && make install

[root@nginx ~]# ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/

[root@nginx ~]# nginx

[root@nginx ~]# netstat -napt | grep :80

tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 57200/nginx

View Code

 

2、修改 nginx.conf 主配置文件

图片 6图片 7

[root@nginx ~]# cat /usr/local/nginx/conf/nginx.conf

user nginx nginx;

worker_processes 2;

error_log logs/error.log;

pid logs/nginx.pid;



events { use epoll;

worker_connections 10240;

} 

http {

includemime.types;

default_type application/octet-stream; 

log_format main '$remote_addr - $remote_user [$time_local] "$request" '

                                                '$status $body_bytes_sent "$http_referer" '

                                               '"$http_user_agent" "$http_x_forwarded_for"'; 

access_log logs/access.log  main; 

sendfile on;

keepalive_timeout 65;

gzip on; 

server {

listen 80;

server_name localhost;

charset utf-8; 

location / {

root html;

index index.html index.htm;

                }

error_page 500 502 503 504 /50x.html;

location = /50x.html {

root html;

         } 


              location ~ \.php$ {                                       //区分大小写匹配,以 php 结尾的的网页

                    proxy_pass http://192.168.200.101;       //反向代理给 LAMP 服务器处理

               }

              location ~ \.(gif|jpg|jpeg|bmp|png|swf) {       //区分大小写匹配,以 gif、jpg、swf 等结尾的文件

                          root html/images;                        //指定图片存放路径

                    }

             }

} 


[root@nginx ~]# echo "<h1>www.crushlinux.com</h1>" >/usr/local/nginx/html/index.html 
[root@nginx ~]# ulimit -n 65000       //调整打开最大连接数

[root@nginx ~]# echo "ulimit -n 65000" >>/etc/profile 

[root@nginx ~]# nginx -t

nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful

[root@nginx ~]# killall -HUP nginx

View Code

 

 

3、浏览器访问 html 及 php
文件进行测试:

图片 8

 

4、浏览器访问测试图片文件:

图片 9图片 10

[root@nginx ~]# cd /usr/local/nginx/html/

[root@nginx html]# tree

.

├── 50x.html

├── images

│?? └── linux.png

└── index.html 

1 directory, 3 files 

[root@LAMP ~]# cd /usr/local/httpd/htdocs/

[root@LAMPhtdocs]# catmysql.php

<?php

$link=mysql_connect('localhost','root','123456');

if($link) echo "恭喜你,数据库连接成功啦!!";

mysql_close();

?>

<br />

<img src="http://192.168.200.102/linux.png" /> 

View Code

 

图片 11

 图片 12

       
右键点击图片可以查看文件路径是“
动态 PHP 语言由 LAMP 服务器提供解析(192.168.200.101),静态图片由 Nginx
服务器提供 解析(192.168.200.102)

        抓包测试查看:

    图片 13

 

这是一个可以检测并规范化文本中的URL地址的Java库。

例子

图片 14

//这是一个用来匹配URL的正则表达式,分组获取不同部分的信息
var parse_url = /^(?:([A-Za-z]+):)?(\/{0,3})([0-9.\-A-Za-z]+)(?::(\d+))?(?:\/([^?#]*))?(?:\?([^#]*))?(?:#(.*))?$/;
var url = “”;
var result = parse_url.exec(url);
var names = [“url”, “scheme”, “slash”, “host”, “port”, “path”, “query”, “hash”];var i;
for (i = 0; i < names.length; i++) {
 document.writeln(names[i] + “: ” + result[i] + ” “); }
//这段代码的输出结果如下:
url:  scheme: http slash: //
host: www.ora.com port: 80 path: goodparts query: q hash: fragment

今天,我们很高兴做一个分享,因为我所在的 Linkedin
公司 开源了我们做的一个ULR探测工具:URL-Detector  Java
库。

解析
下面让我们分解parse_url的各个部分,看看它是如何工作的:

Linkedin 在每一秒钟,会检查数十万数量级的 URLs 。这些 URL
可能是来自恶意软件或者钓鱼网站的,为了保障我们每一个用户有一个安全的浏览体验,同时防止潜在的危险,我们后端的内容检查服务程序会检查所有由用户产生的内容。为了在这每秒数十万规模的用户内容上检测不良的
URL,我们要有能够在快速此规模上提取文本中URL 的方法。

^

我们的服务器中的 URL地址有两种形式:

^字符表示此字符串的开始,它是一个锚,指引exec不要跳过那些不像URL的前缀,只匹配那些从开头就像URL一样的字符串。

  • 一种是单一的 URL
  • 一种是在一大块的文本内容中

(?:([A-Za-z]+):)?

如果发送过来的是单一的 URL,我们可以通过我们的内容检查服务直接验证;

这个因子匹配一个协议名,但仅当它后面跟随一个 :(冒号)的时候才匹配。(?:
. . .)表示一个非捕获型分组(noncapturing group)。后缀 ?
表示这个分组是可选的,它表示重复0次或1次。( . .
.)表示一个捕获型分组。一个捕获型分组会复制它所匹配的文本,并把其放到result数组里。每个捕获型分组都会被指定一个编号。第一个捕获型分组的编号是1,所以该分组所匹配的文本副本会出现在result[1]中。
[ . .
.]表示一个字符类。A-Za-z这个字符类包含26个大写字母和26个小写字母。连接字符

如果发送过来的是大块的文本内容,我们会先通过我们的URL探测器 ,经过搜索算法来验证这个文本是否有潜在危险的URL地址;

  • 表示范围从A-Z。后缀 +
    表示这个字符类会被匹配一次或多次。这个组后面跟着字符 :
    ,它会按字面进行匹配。 

在我介绍URL探测器是如何工作的和它所能提供给的功能之前,让我们先来了解一下我们做这个项目的动机。

(\/{0,3})

我们的目标是:检测出尽可能多的恶意链接,但是我们不希望紧紧局限于检测在 RFC
1738 中定义的URL地址,而是希望可以检测出任何能够在真正的浏览器地址栏中输入并且可以访问到的URL地址。因为,一个浏览器的地址栏中对
URL 的定义比起 在 RFC
1738 定义的来说,是非常松散的。同时,很多浏览器有不同的行为,所以,我们要找到一种URL文本规则能够被大部分流行的浏览器解析,它不是像RFC中定义语法那样简单。

这个因子是捕获型分组2,匹配//。\ /表示应,该匹配 / (斜杠)。它用 \
(反斜杠)来进行转义,这样它就不会被错误地解释为这个正则表达式的结束符。后缀
{0,3} 表示 / 会匹配0~3次。

Author

发表评论

电子邮件地址不会被公开。 必填项已用*标注