nginx的详解(二)
^: 匹配字符串的开始位置; $:匹配字符串的结束位置;
.*: .匹配任意字符,*匹配数量0到正无穷; \. 斜杠用来转义,\.匹配 . 特殊使用方法,记住记性了; (值1|值2|值3|值4):或匹配模式,例:(jpg|gif|png|bmp)匹配jpg或gif或png或bmp i不区分大小写
?:重复0次或1次 +:重复一次或更多次
屏蔽爬虫 if ($http_user_agent ~* "qihoobot|Baiduspider|Googlebot|Googlebot-Mobile|Googlebot-Image|Mediapartners-Google|Adsbot-Google|Feedfetcher-Google|Yahoo! Slurp|Yahoo! Slurp China|YoudaoBot|Sosospider|Sogou spider|Sogou web spider|MSNBot|ia_archiver|Tomato Bot") { return 403; } #favicon.ico不用打日志 location = /favicon.ico { log_not_found off; access_log off; } #不允许访问隐藏文件 location ~ /\. { deny all; access_log off; log_not_found off; } #访问图片,flash文件等不用打日志 location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ { expires 7d; #文件返回的过期时间是7天 access_log off; } #访问js和css文件不用打日志 location ~ .*\.(js|css)?$ { expires 1d; #文件返回的过期时间是1天 access_log off; } #设置php-cgi location ~ [^/]\.php(/|$) { fastcgi_split_path_info ^(.+?\.php)(/.*)$; #拦截不存在的php页面请求 if (!-f $document_root$fastcgi_script_name) { return 404; } }
1.rewrite跳转规则,有以下四种flag标记:
last 基本上都用这个Flag,表示rewrite。
break 中止Rewirte,不在继续匹配。就是说本条规则匹配完成后,终止匹配,不再匹配后面的规则。
redirect 返回临时重定向的HTTP状态302;浏览器地址会显示跳转后的URL地址。
1)下面是可以用来判断的表达式:
-f和!-f用来判断是否存在文件 -d和!-d用来判断是否存在目录 -e和!-e用来判断是否存在文件或目录 -x和!-x用来判断文件是否可执行
先来看几个小例子说明
例如下面这段设定nginx将某个目录下面的文件重定向到另一个目录,$2对应第二个括号(.*)中对应的字符串:
.* :任意字符 . :代表任意字符串 * :代表前面字符的任意个数 \ :代表转译,比如\.jpg 意思是转译. 其中.不做任何解释,只是表示.jpg,不做正则解释。
另外注意:
$1表示第一个变量,即前面rewrite后第一个()内设置的变量
$2表示第二个变量,即前面rewrite后第二个()内设置的变量
location /download/ { rewrite ^(/download/.*)/m/(.*)\..*$ $1/nginx-rewrite/$2.gz break; } ----------------------------------------------------------------------------------- 例如当用户输入 www.a.com.cn 自动跳转到www.a.com 这个域名: rewrite ^/(.*)$ http://www.a.com/$1 permanent; ----------------------------------------------------------------------------------- 例如下面设定nginx在用户使用ie的使用重定向到/nginx-ie目录下: if ($http_user_agent ~ MSIE) { rewrite ^(.*)$ /nginx-ie/$1 break; } ----------------------------------------------------------------------------------- 例如当用户访问testxqsjapi.xqshijie.com域名时跳转到本机的9501端口 upstream lb-9501 { server 127.0.0.1:9501; } server { listen 80; server_name testxqsjapi.xqshijie.com; root /var/www/vhosts/testxqsjapi.xqshijie.com/; location / { proxy_pass http://lb-9501; } } ---------------------------------------------------------------------------------- 例如下面一例:nginx rewrite 实现二级域名跳转 当访问http://abc.wangshibo.com跳转到http://www.wangshibo.com/wangshibo/abc/ 方法一:这种方法浏览器地址会变www.wangshibo.com/wangshibo/abc server { listen 80; server_name www.wangshibo.com; location / { root /data/wangshibo; index index.html; } } server { listen 80; server_name *.wangshibo.com; if ( $http_host ~* "^(.*)\.wangshibo\.com$") { set $domain $1; rewrite ^(.*) http://www.wangshibo.com/wangshibo/$domain/ break; } } 方法二:当访问http://abc.wangshibo.com跳转到http://www.wangshibo.com/wangshibo/abc/ server { listen 80; server_name *.wangshibo.com; root /usr/local/www; #这是里可以加多个目录,如果不加目录,会无法访问到abc.wangshibo.com/目录下的文件,如图片目录/images location ~ ^/(wangshibo|images|styles)/ { proxy_redirect off; proxy_set_header Host www.wangshibo.com; proxy_pass http://192.168.1.2:8080; } location / { set $domain default; if ( $http_host ~* "^(.*)\.wangshibo\.com$") { set $domain $1; } rewrite ^/(.*) /wangshibo/$domain/$1 last; } access_log off; }
#直接匹配网站根,通过域名访问网站首页比较频繁,使用这个会加速处理,官网如是说。
#这里是直接转发给后端应用服务器了,也可以是一个静态首页
# 第一个必选规则
location = / {
proxy_pass http:
//tomcat
:8080
/index
}
# 第二个必选规则是处理静态文件请求,这是nginx作为http服务器的强项
# 有两种配置模式,目录匹配或后缀匹配,任选其一或搭配使用
location ^~
/static/
{
root
/webroot/static/
;
}
location ~* \.(gif|jpg|jpeg|png|css|js|ico)$ {
root
/webroot/res/
;
}
#第三个规则就是通用规则,用来转发动态请求到后端应用服务器
#非静态文件请求就默认是动态请求,自己根据实际把握
#毕竟目前的一些框架的流行,带.php,.jsp后缀的情况很少了
location / {
proxy_pass http:
//tomcat
:8080/
}
实例说明
1)访问A站跳转(重定向)到B站
server { listen 80; server_name www.wangshibo.com ; rewrite ^(.*) http://www.huanqiu.com$1 permanent; root /var/www/html; index index.html index.php index.htm; access_log /usr/local/nginx/logs/image.log; } 访问wangshibo.com跳转到www.wangshibo.com server { listen 80; server_name www.wangshibo.com wangshibo.com; index index.jsp index.html index.php index.htm; root /var/www/html; access_log /usr/local/nginx/logs/image.log; if ($host = "wangshibo.com") { rewrite ^/(.*)$ http://www.wangshibo.com permanent; } } 2)多域名绑定一个目录,并且全部301跳转到其中一个域名(注意:多域名都要解析到本机ip上) server { listen 80; server_name www.wangshibo.com web01.wangshibo.com hehe.wangshibo.com wangshibo.com; if ($host != 'www.wangshibo.com') { rewrite ^/(.*)$ http://www.wangshibo.com/$1 permanent; } root /var/www/html; index index.html index.php index.htm; access_log /usr/local/nginx/logs/image.log; } 上面说明访问http://web01.wangshibo.com、http://hehe.wangshibo.com、http://wangshibo.com的时候都会自动跳转到 http://www.wangshibo.com,并且浏览器地址会显示跳转后的URL地址。 如果是上面多域名访问后都重定向跳转到http://hehe.wangshibo.com,则配置修改如下: server { listen 80; server_name www.wangshibo.com web01.wangshibo.com hehe.wangshibo.com wangshibo.com; if ($host != 'hehe.wangshibo.com') { rewrite ^/(.*)$ http://hehe.wangshibo.com/$1 permanent; } root /var/www/html; index index.html index.php index.htm; access_log /usr/local/nginx/logs/image.log; } 如下配置:多域名中的某个域名访问时发生跳转,其他域名访问时不跳转 server { listen 80; server_name www.wangshibo.com web01.wangshibo.com hehe.wangshibo.com wangshibo.com; if ($host = 'hehe.wangshibo.com') { rewrite ^/(.*)$ http://www.huanqiu.com/$1 permanent; } root /var/www/html; index index.html index.php index.htm; access_log /usr/local/nginx/logs/image.log; } 3)将多级目录下的文件转成一个文件,增强seo效果 比如将/wang-123-456-789.html指向wang/123/456/wangshow_789.html [root@test-huanqiu ~]# cat /usr/local/nginx/conf/vhosts/test.conf server { listen 80; server_name www.wangshibo.com; rewrite ^/wang-([0-9]+)-([0-9]+)-([0-9]+)\.html$ http://www.wangshibo.com/wang/$1/$2/wangshow_$3.html last; root /var/www/html; index index.html index.php index.htm; access_log /usr/local/nginx/logs/image.log; } 这样访问http://www.wangshibo.com/wang-123-456-789.html就会跳转到http://www.wangshibo.com/wang/123/456/wangshow_789.html 4)访问的目标文件和目录资源不存在的时候重定向跳转 如下配置,当访问http://www.wangshibo.com/后面的访问资源(文件或目录)不存在时,统统跳转到http://www.wangshibo.com/sorry.html页面 server { listen 80; server_name www.wangshibo.com; if (!-e $request_filename) { rewrite ^/ http://www.wangshibo.com/sorry.html ; } root /var/www/html; index index.html index.php index.htm; access_log /usr/local/nginx/logs/image.log; } 5)将站点根目录下某个目录指向二级目录 例如将/huanqiupc/指向/ops/huanqiu/,配置如下: server { listen 80; server_name www.wangshibo.com; rewrite ^/([0-9a-z]+)pc/(.*)$ http://www.wangshibo.com/ops/$1/$2 last; root /var/www/html; index index.html index.php index.htm; access_log /usr/local/nginx/logs/image.log; } 这样,访问http://www.wangshibo.com/huanqiupc的时候就会跳转到http://www.wangshibo.com/ops/huanqiu/ 注意:上面的配置中的last修改为permanent或redirect都可以 以上的配置也适用于:(前提是这些目录要真是存在于站点目录/var/www/html/中,并且权限要正确) 将/wangshibopc/指向/ops/wangshibo/ 将/guohuihuipc/指向/ops/guohuihui/ 将/hahapc/指向/ops/haha/ ...... 6)其他的rewrite跳转规则的例子: server { listen 80; server_name www.wangshibo.com; root /var/www/html; index index.html index.htm; rewrite ^/site/resource/(.*)$ https://www.wangshibo.com/resource/$1 last; rewrite ^/active/Ymf.html$ https://www.wangshibo.com/project/detail.html?project_id=1 last; rewrite ^/active/Ysyg.html$ https://www.wangshibo.com/project/detail.html?project_id=7 last; if ($host ~* "^wangshibo.com$") { rewrite ^/(.*)$ https://www.wangshibo.com/ permanent; } location / { rewrite /abc http://www.huanqiu.com break; #本机站点目录下并不需要真实存在abc这个目录,对虚拟目录的访问都重写到http://www.huanqiu.com } #即访问http://www.wangshibo.com/abc,跳转到http://www.huanqiu.com location /text { rewrite / http://china.huanqiu.com break; #本机站点目录下需要真实存在text目录,对其的访问都重写到http://china.huanqiu.com } #即访问http://www.wangshibo.com/text,跳转到http://china.huanqiu.com } 面一例:访问http://www.wangshibo.com/g/4HG45SkZ 实际访问地址跳转为 http://110.10.88.99:8081/qun/share/view?code=4HG45SkZ upstream g_server { keepalive 64; server 110.10.88.99:8081 max_fails=2 fail_timeout=5 weight=100; } server { listen 80; server_name www.wangshibo.com; rewrite ^/bcloud.(swf|html|js)(.*)$ http://hehe.wangshibo.com/bcloud.$1$2 last; root /home/web/www; location ~ \.apk$ { max_ranges 0; } location ^~ /g { proxy_redirect off; proxy_set_header Host $host; # proxy_set_header Host $host:$remote_port; # proxy_set_header REMOTE_PORT $remote_port; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; client_max_body_size 1G; client_body_buffer_size 256k; proxy_connect_timeout 30; proxy_send_timeout 30; proxy_read_timeout 600; proxy_buffer_size 16k; proxy_buffers 4 32k; proxy_temp_file_write_size 64k; proxy_pass http://g_server; #rewrite "/g/(.*$)" www.wangshibo.com/qun/share/view?code=$1 break; rewrite "/g/(.*$)" /qun/share/view?code=$1 break; } } 再看一例: 访问http://www.wangshibo.com/thumb/transcode 实际访问地址为 http://120.170.190.99:28080/transcode/thumb/transcode upstream thumb { keepalive 64; server 120.170.190.99:28080 max_fails=2 fail_timeout=5 weight=100; } server { listen 80; server_name www.wangshibo.com ; root /home/web/www; location ^~ /thumb { proxy_pass http://thumb; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded_For $proxy_add_x_forwarded_for; client_max_body_size 1G; client_body_buffer_size 256k; proxy_connect_timeout 30; proxy_send_timeout 30; proxy_read_timeout 60; proxy_buffer_size 16k; proxy_buffers 4 32k; proxy_temp_file_write_size 64k; rewrite "^/(.*)$" /transcode/$1 break; } }
需要特别注意的是:
proxy_pass 反向代理,可以实现只改变跳转后的内容,而跳转后的原url保持不变!
rewrite 重写跳转后会进行重定向,很难实现跳转后的原url不变的需求。
看看之前踩过的坑;
要求访问http:
//wx2
.xqshijie.com
/apiwx2/xqsj
.php?r=houseGroup%2FgetToken,内容跳转到http:
//m
.xqshijie.com
/xqsj
.php?r=houseGroup%2FgetToken,但是跳转后的url保持不变!
这是根据path路径进行反向代理的配置,即要求访问http:
//wx2
.xqshijie.com
/apiwx2/
$1 跳转到http:
//m
.xqshijie.com/$1,跳转后的url不变!
配置如下:
cat wx2.xqshijie.com.conf server { listen 80; server_name wx2.xqshijie.com; root /Data/app/xqsj_wx2/dist; index index.html; #if ($http_x_forwarded_for !~ ^(124.65.197.154|103.10.86.28|103.10.86.8)) { # rewrite ^.*$ /maintence.php last; #} location /apiwx2/ { proxy_pass https://m.xqshijie.com/; } access_log /var/log/betawx2.log main; location / { try_files $uri $uri/ @router; index index.html; } #rewrite ^(.+)$ /index.html last; location @router { rewrite ^.*$ /index.html last; } } 根据上面配置后,就可以实现访问http://wx2.xqshijie.com/apiwx2/xqsj.php?r=houseGroup%2FgetToken,实际显示的是https://m.xqshijie.com/xqsj.php?r=houseGroup%2FgetToken的内容,但是跳转后的原来的url不变! 如果采用rewrite重写规则,即将: location /apiwx2/ { proxy_pass https://m.xqshijie.com/; } 改为 location /apiwx2/ { rewrite ^/apiwx2(.*)$ https://m.xqshijie.com.$1 last; } 那么,访问http://wx2.xqshijie.com/apiwx2/xqsj.php?r=houseGroup%2FgetToken,实际显示的是https://m.xqshijie.com/xqsj.php?r=houseGroup%2FgetToken的内容,但是跳转后的url已经变了! 上面碰到过的坑: 由于访问http://m.xqshijie.com就会自动跳转到https://m.xqshijie.com,所以如果将上面的配置改为(即将https://m.xqshijie.com改为http://m.xqshijie.com): location /apiwx2/ { proxy_pass http://m.xqshijie.com/; } 这样,访问http://wx2.xqshijie.com/apiwx2/xqsj.php?r=houseGroup%2FgetToken,实际显示的是https://m.xqshijie.com/xqsj.php?r=houseGroup%2FgetToken的内容,但是跳转后的原来的url已经变了! 原因是因为这里经过了两次跳转,即rewrite->http->https,所以跳转后的url变了。 解决办法:就是直接rewrite跳转到https,即proxy_pass https://m.xqshijie.com/; 下面的跳转规则表示 访问http://www.wangshibo.com/wangshibo/ops就会跳转到http://www.wangshibo.com/ops/wangshibo 访问http://www.wangshibo.com/wangshibo/beijing就会跳转到http://www.wangshibo.com/beijing/wangshibo ...... 即由"wangshibo/变量"-->"变量/wangshibo" server { listen 80; server_name www.wangshibo.com; rewrite ^/wangshibo/(.*)$ http://www.wangshibo.com/$1/wangshibo last; root /var/www/html; index index.html index.php index.htm; access_log /usr/local/nginx/logs/image.log; } 访问http://www.wangshibo.com/ops/web 跳转到 http://www.wangshibo.com/web/ops/web/ server { listen 80; server_name www.wangshibo.com; rewrite ^/ops/(.*)$ http://www.wangshibo.com/$1/ops/$1 break; root /var/www/html; index index.html index.php index.htm; access_log /usr/local/nginx/logs/image.log; } 访问http://www.wangshibo.com/wang/123 实际访问地址跳转为 http://www.hehe.com/qun/share/view?code=123 server { listen 80; server_name www.wangshibo.com; rewrite ^/wang/(.*)$ http://www.hehe.com/qun/share/view?code=$1 last; root /var/www/html; index index.html index.php index.htm; access_log /usr/local/nginx/logs/image.log; } 其他配置实例 如果nginx在用户使用IE浏览器访问情况下,则重定向到/nginx-ie目录下 配置如下: if ($http_user_agent ~ MSIE) { rewrite ^(.*)$ /nginx-ie/$1 break; } 多目录转成参数 abc.domian.com/sort/2 => abc.domian.com/index.php?act=sort&name=abc&id=2 配置如下: if ($host ~* (.*)\.domain\.com) { set $sub_name $1; rewrite ^/sort\/(\d+)\/?$ /index.php?act=sort&cid=$sub_name&id=$1 last; } 目录自动加"/",前提是访问目录存在 配置如下: if (-d $request_filename){ rewrite ^/(.*)([^/])$ http://$host/$1$2/ permanent; } 三级域名跳转 配置如下: if ($http_host ~* “^(.*)\.i\.beijing\.com$”) { rewrite ^(.*) http://www.wangshibo.com$1/; break; } 针对站点根目录下的某个子目录作镜向 配置如下:就会把http://www.huanqiu.com的内容(即首页)镜像到/var/www/html下的ops目录下了 server { listen 80; server_name www.wangshibo.com; root /var/www/html; location ^~ /ops { rewrite ^.+ http://www.huanqiu.com/ last; break; } index index.html index.php index.htm; access_log /usr/local/nginx/logs/image.log; } 域名镜像(其实就是域名跳转) server { listen 80; server_name www.wangshibo.com; root /var/www/html; rewrite ^/(.*) http://www.huanqiu.com/$1 last; index index.html index.php index.htm; access_log /usr/local/nginx/logs/image.log; } 其他: rewrite ^/(space|network)-(.+)\.html$ /$1.php?rewrite=$2 last; rewrite ^/(space|network)\.html$ /$1.php last; rewrite ^/([0-9]+)$ /space.php?uid=$1 last; rewrite ^(.*)/archiver/((fid|tid)-[\w\-]+\.html)$ $1/archiver/index.php?$2 last; rewrite ^(.*)/forum-([0-9]+)-([0-9]+)\.html$ $1/forumdisplay.php?fid=$2&page=$3 last; rewrite ^(.*)/thread-([0-9]+)-([0-9]+)-([0-9]+)\.html$ $1/viewthread.php?tid=$2&extra=page\%3D$4&page=$3 last; rewrite ^(.*)/profile-(username|uid)-(.+)\.html$ $1/viewpro.php?$2=$3 last; rewrite ^(.*)/space-(username|uid)-(.+)\.html$ $1/space.php?$2=$3 last; rewrite ^(.*)/tag-(.+)\.html$ $1/tag.php?name=$2 last; 目录对换:/1234/xxx ----->xxx?id=1234 vim /usr/local/nginx/conf/vhosts/test.conf server { listen 80; server_name www.wangshibo.com; root /var/www/html; rewrite ^/(\d+)/(.+)/ /$2?id=$1 last; index index.html index.php index.htm; access_log /usr/local/nginx/logs/image.log; } [root@test-huanqiu ~]# cat /var/www/html/ops/index.html nginx的目录对换的跳转测试 如上配置后,那么: 访问http://www.wangshibo.com/?id=567567567567567 的结果就是http://www.wangshibo.com/的结果 访问http://www.wangshibo.com/ops/?id=wangshibo 的结果就是http://www.wangshibo.com/ops的结果 访问http://www.wangshibo.com/wang/?id=123111 的结果就是http://www.wangshibo.com/wang的结果
2.反向代理(proxy_pass)
简单测试nginx反向代理和负载均衡功能的操作记录(1)-----http代理
简单测试nginx反向代理和负载均衡功能的操作记录(2)-----https代理
4.防盗链。关于Nginx防盗链具体设置,可参考:Nginx中防盗链(下载防盗链和图片防盗链)的操作记录
location ~* \.(gif|jpg|swf)$ { valid_referers none blocked start.igrow.cn sta.igrow.cn; if ($invalid_referer) { rewrite ^/ http://$host/logo.png; } } 下面设置文件反盗链并设置过期时间: location ~*^.+\.(jpg|jpeg|gif|png|swf|rar|zip|css|js)$ { valid_referers none blocked *.wangshibo.com*.wangshibo.net localhost 218.197.67.14; if ($invalid_referer) { rewrite ^/ http://img.wangshibo.net/leech.gif; return 412; break; } access_log off; root /opt/lampp/htdocs/web; expires 3d; break; }
这里的return 412 是自定义的http状态码,默认为403,方便找出正确的盗链的请求
“rewrite ^/ http://img.wangshibo.net/leech.gif;”显示一张防盗链图片
“access_log off;”不记录访问日志,减轻压力
“expires 3d”所有文件3天的浏览器缓存
5.根据文件类型设置过期时间
1)expires起到控制页面缓存的作用,合理的配置expires可以减少很多服务器的请求;
2)对于站点中不经常修改的静态内容(如图片,JS,CSS),可以在服务器中设置expires过期时间,控制浏览器缓存,达到有效减小带宽流量,降低服务器压力的目的。
3)Expires是Web服务器响应消息头字段,在响应http请求时告诉浏览器在过期时间前浏览器可以直接从浏览器缓存取数据,而无需再次请求。
要配置expires,可以在http段中或者server段中或者location段中加入;
如下:控制图片等过期时间为30天,如果图片文件不怎么更新,过期可以设大一点;如果频繁更新,则可以设置得小一点,具体视情况而定
location ~ \.(gif|jpg|jpeg|png|bmp|swf|ico)$ { root /var/www/img/; expires 30d; } location ~ .*\.(js|css)$ { expires 10d; } location ~* \.(js|css|jpg|jpeg|gif|png|swf)$ { if (-f $request_filename) { expires 1h; break; } } location ~ \.(wma|wmv|asf|mp3|mmf|zip|rar|swf|flv)$ { root /var/www/upload/; expires max; }
expires 指令可以控制 HTTP 应答中的“ Expires ”和“ Cache-Control ”的头标(起到控制页面缓存的作用)
语法:expires [time|epoch|max|off]
默认值:off
expires指令控制HTTP应答中的“Expires”和“Cache-Control”Header头部信息,启动控制页面缓存的作用
time:可以使用正数或负数。“Expires”头标的值将通过当前系统时间加上设定time值来设定。
time值还控制"Cache-Control"的值:
负数表示no-cache
正数或零表示max-age=time
epoch:指定“Expires”的值为 1 January,1970,00:00:01 GMT
max:指定“Expires”的值为31 December2037 23:59:59GMT,"Cache-Control"的值为10年。(即设置过期时间最最长)
-1:指定“Expires”的值为当前服务器时间-1s,即永远过期。
off:不修改“Expires”和"Cache-Control"的值
expires使用了特定的时间,并且要求服务器和客户端的是中严格同步。
而Cache-Control是用max-age指令指定组件被缓存多久。
对于不支持http1.1的浏览器,还是需要expires来控制。所以最好能指定两个响应头。但HTTP规范规定max-age指令将重写expires头。