BoxCore

Start


  • 首页

  • 分类

  • 关于

  • 归档

  • 标签

  • 站点地图

  • 搜索

Nginx下重写规则

发表于 2018-04-07 | 分类于 正则 , nginx | | 阅读次数

我们知道apache和nginx都可以对url链接进行重写,apache主要通过.htacess文件来实现,而nginx主要是通过域名配置来实现。两者的用法区别很大,这里针对这2种链接重新工具进行对比,并给大家介绍nginx常用的一些rewrite配置。

一、Nginx Rewrite基础

二、nginx rewrite和apache rewrite区别

Nginx Rewrite规则相关指令
Nginx Rewrite规则相关指令有if、rewrite、set、return、break等,其中rewrite是最关键的指令。一个简单的Nginx Rewrite规则语法如下:

rewrite ^/b/(.*).html /play.php?video=$1 break;

如果加上if语句,示例如下:

if (!-f $request_filename)
rewrite ^/img/(.*)$ /site/$host/images/$1 last;

Nginx与Apache的Rewrite规则实例对比

简单的Nginx和Apache 重写规则区别不大,基本上能够完全兼容。例如:

Apache Rewrite 规则:

1
2
3
4
RewriteRule ^/(mianshi|xianjing)/$ /zl/index.php?name=$1 [L]
RewriteRule ^/ceshi/$ /zl/ceshi.php [L]
RewriteRule ^/(mianshi)_([a-zA-Z]+)/$ /zl/index.php?name=$1_$2 [L]
RewriteRule ^/pingce([0-9]*)/$ /zl/pingce.php?id=$1 [L]

Nginx Rewrite 规则:

1
2
3
4
rewrite ^/(mianshi|xianjing)/$ /zl/index.php?name=$1 last;
rewrite ^/ceshi/$ /zl/ceshi.php last;
rewrite ^/(mianshi)_([a-zA-Z]+)/$ /zl/index.php?name=$1_$2 last;
rewrite ^/pingce([0-9]*)/$ /zl/pingce.php?id=$1 last;

由以上示例可以看出,Apache的Rewrite规则改为Nginx的Rewrite规则,其实很简单:Apache的RewriteRule指令换成Nginx的rewrite指令,Apache的[L]标记换成Nginx的last标记,中间的内容不变。

如果Apache的Rewrite规则改为Nginx的Rewrite规则后,使用nginx -t命令检查发现nginx.conf配置文件有语法错误,那么可以尝试给条件加上引号。例如一下的Nginx Rewrite规则会报语法错误:

rewrite ^/([0-9]{5}).html$ /x.jsp?id=$1 last;

加上引号就正确了:

rewrite “^/([0-9]{5}).html$” /x.jsp?id=$1 last;

Apache与Nginx的Rewrite规则在URL跳转时有细微的区别:

Apache Rewrite 规则:

RewriteRule ^/html/tagindex/([a-zA-Z]+)/.*$ /$1/ [R=301,L]

Nginx Rewrite 规则:

rewrite ^/html/tagindex/([a-zA-Z]+)/.*$ http://$host/$1/ permanent;

以上示例中,我们注意到,Nginx Rewrite 规则的置换串中增加了“http://$host”,这是在Nginx中要求的。

另外,Apache与Nginx的Rewrite规则在变量名称方面也有区别,例如:

Apache Rewrite 规则:

RewriteRule ^/user/login/$ /user/login.php?login=1&forward=http://%{HTTP_HOST} [L]

Nginx Rewrite 规则:

rewrite ^/user/login/$ /user/login.php?login=1&forward=http://$host last;

Apache与Nginx Rewrite 规则的一些功能相同或类似的指令、标记对应关系:

Apache的RewriteCond指令对应Nginx的if指令;
Apache的RewriteRule指令对应Nginx的rewrite指令;
Apache的[R]标记对应Nginx的redirect标记;
Apache的[P]标记对应Nginx的last标记;
Apache的[R,L]标记对应Nginx的redirect标记;
Apache的[P,L]标记对应Nginx的last标记;
Apache的[PT,L]标记对应Nginx的last标记;

允许指定的域名访问本站,其他域名一律跳转到http://www.aaa.com

Apache Rewrite 规则:
RewriteCond %{HTTP_HOST} ^(.*?).domain.com$
RewriteCond %{HTTP_HOST} !^qita.domain.com$
RewriteCond %{DOCUMENT_ROOT}/market/%1/index.htm -f
RewriteRule ^/wu/$ /market/%1/index.htm [L]

Nginx的if指令不支持嵌套,也不支持AND、OR等多条件匹配,相比于Apache的RewriteCond,显得麻烦一些,但是,我们可以通过下一页的Nginx配置写法来实现这个示例:

Nginx Rewrite 规则:
if ($host ~ ^(.?).domain.com$) set $var_wupin_city $1;
set $var_wupin ‘1′;

if ($host ~* ^qita.domain.com$)

set $var_wupin ‘0′;

if (!-f $document_root/market/$var_wupin_city/index.htm)

set $var_wupin ‘0′;

if ($var_wupin ~ ‘1′)

rewrite ^/wu/$ /market/$var_wupin_city/index.htm last;
}

 

rewrite 的语法

 

语法: rewrite regex replacement flag

默认: none

作用域: server, location, if

This directive changes URI in accordance with the regular expression and the replacement string. Directives are carried out in order of appearance in the configuration file.

这个指令根据表达式来更改URI,或者修改字符串。指令根据配置文件中的顺序来执行。

Be aware that the rewrite regex only matches the relative path instead of the absolute URL. If you want to match the hostname, you should use an if condition, like so:

注意重写表达式只对相对路径有效。如果你想配对主机名,你应该使用if语句。

rewrite只是会改写路径部分的东东,不会改动用户的输入参数,因此这里的if规则里面,你无需关心用户在浏览器里输入的参数,rewrite后会自动添加的,因此,我们只是加上了一个?号和后面我们想要的一个小小的参数 *https=1就可以了。

nginx的rewrite规则参考:

~ 为区分大小写匹配
~ 为不区分大小写匹配
!~和!~
分别为区分大小写不匹配及不区分大小写不匹
-f和!-f用来判断是否存在文件
-d和!-d用来判断是否存在目录
-e和!-e用来判断是否存在文件或目录
-x和!-x用来判断文件是否可执行
last 相当于Apache里的[L]标记,表示完成rewrite,呵呵这应该是最常用的
break 终止匹配, 不再匹配后面的规则
redirect 返回302临时重定向 地址栏会显示跳转后的地址
permanent 返回301永久重定向 地址栏会显示跳转后的地址
$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_string
$scheme
$server_protocol
$server_addr
$server_name
$server_port
$uri
结合QeePHP的例子

if (!-d $request_filename) {
rewrite ^/([a-z-A-Z]+)/([a-z-A-Z]+)/?(.*)$ /index.php?namespace=user&controller=$1&action=$2&$3 last;
rewrite ^/([a-z-A-Z]+)/?$ /index.php?namespace=user&controller=$1 last;
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;
}
目录对换
/123456/xxxx -> /xxxx?id=123456

rewrite ^/(d+)/(.+)/ /$2?id=$1 last;
例如下面设定nginx在用户使用ie的使用重定向到/nginx-ie目录下:

if ($http_user_agent ~ MSIE) {
rewrite ^(.*)$ /nginx-ie/$1 break;
}
目录自动加“/”

if (-d $request_filename){
rewrite ^/(.*)([^/])$ http://$host/$1$2/ permanent;
}
禁止htaccess

location ~/.ht {
deny all;
}
禁止多个目录

location ~ ^/(cron|templates)/ {
deny all;
break;
}
禁止以/data开头的文件
可以禁止/data/下多级目录下.log.txt等请求;

location ~ ^/data {
deny all;
}
禁止单个目录
不能禁止.log.txt能请求

location /searchword/cron/ {
deny all;
}
禁止单个文件

location ~ /data/sql/data.sql {
deny all;
}
给favicon.ico和robots.txt设置过期时间;
这里为favicon.ico为99天,robots.txt为7天并不记录404错误日志

location ~(favicon.ico) {
log_not_found off;
expires 99d;
break;
}

location ~(robots.txt) {
log_not_found off;
expires 7d;
break;
}
设定某个文件的过期时间;这里为600秒,并不记录访问日志

location ^~ /html/scripts/loadhead_1.js {
access_log off;
root /opt/lampp/htdocs/web;
expires 600;
break;
}
文件反盗链并设置过期时间
这里的return 412 为自定义的http状态码,默认为403,方便找出正确的盗链的请求
“rewrite ^/ http://leech.divmy.com/leech.gif;”显示一张防盗链图片
“access_log off;”不记录访问日志,减轻压力
“expires 3d”所有文件3天的浏览器缓存

location ~ ^.+.(jpg|jpeg|gif|png|swf|rar|zip|css|js)$ {
valid_referers none blocked
.c1gstudio.com *.c1gstudio.net localhost 208.97.167.194;
if ($invalid_referer) {
rewrite ^/ http://leech.divmy.com/leech.gif;
return 412;
break;
}
access_log off;
root /opt/lampp/htdocs/web;
expires 3d;
break;
}
只充许固定ip访问网站,并加上密码

root /opt/htdocs/www;
allow 208.97.167.194;
allow 222.33.1.2;
allow 231.152.49.4;
deny all;
auth_basic “C1G_ADMIN”;
auth_basic_user_file htpasswd;
将多级目录下的文件转成一个文件,增强seo效果
/job-123-456-789.html 指向/job/123/456/789.html

rewrite ^/job-([0-9]+)-([0-9]+)-([0-9]+).html$ /job/$1/$2/jobshow_$3.html last;
将根目录下某个文件夹指向2级目录
如/shanghaijob/ 指向 /area/shanghai/
如果你将last改成permanent,那么浏览器地址栏显是/location/shanghai/

rewrite ^/([0-9a-z]+)job/(.*)$ /area/$1/$2 last;
上面例子有个问题是访问/shanghai 时将不会匹配

rewrite ^/([0-9a-z]+)job$ /area/$1/ last;
rewrite ^/([0-9a-z]+)job/(.*)$ /area/$1/$2 last;
这样/shanghai 也可以访问了,但页面中的相对链接无法使用,
如./list_1.html真实地址是/area/shanghia/list_1.html会变成/list_1.html,导至无法访问。

那我加上自动跳转也是不行咯
(-d $request_filename)它有个条件是必需为真实目录,而我的rewrite不是的,所以没有效果

if (-d $request_filename){
rewrite ^/(.*)([^/])$ http://$host/$1$2/ permanent;
}
知道原因后就好办了,让我手动跳转吧

rewrite ^/([0-9a-z]+)job$ /$1job/ permanent;
rewrite ^/([0-9a-z]+)job/(.*)$ /area/$1/$2 last;
文件和目录不存在的时候重定向:

if (!-e $request_filename) {
proxy_pass http://127.0.0.1;
}
域名跳转

server
{
listen 80;
server_name jump.88dgw.com;
index index.html index.htm index.php;
root /opt/lampp/htdocs/www;
rewrite ^/ http://www.88dgw.com/;
access_log off;
}
多域名转向

server_name www.7oom.com/ www.divmy.com/;
index index.html index.htm index.php;
root /opt/lampp/htdocs;
if ($host ~ “c1gstudio.net”) {
rewrite ^(.*) http://www.7oom.com$1/ permanent;
}
三级域名跳转

if ($http_host ~ “^(.).i.c1gstudio.com$”) {
rewrite ^(.*) http://top.88dgw.com$1/;
break;
}
域名镜向

server
{
listen 80;
server_name mirror.c1gstudio.com;
index index.html index.htm index.php;
root /opt/lampp/htdocs/www;
rewrite ^/(.*) http://www.divmy.com/$1 last;
access_log off;
}
某个子目录作镜向

location ^~ /zhaopinhui {
rewrite ^.+ http://zph.divmy.com/ last;
break;
}
discuz ucenter home (uchome) rewrite

rewrite ^/(space|network)-(.+).html$ /$1.php?rewrite=$2 last;
rewrite ^/(space|network).html$ /$1.php last;
rewrite ^/([0-9]+)$ /space.php?uid=$1 last;
discuz 7 rewrite

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;
给discuz某版块单独配置域名

server_name bbs.c1gstudio.com news.c1gstudio.com;

location = / {
if ($http_host ~ news.divmy.com$) {
rewrite ^.+ http://news.divmy.com/forum-831-1.html last;
break;
}
}
discuz ucenter 头像 rewrite 优化

location ^~ /ucenter {
location ~ .*.php?$
{

#fastcgi_pass unix:/tmp/php-cgi.sock;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fcgi.conf;
}

location /ucenter/data/avatar {
log_not_found off;
access_log off;
location ~ /(.)_big.jpg$ {
error_page 404 /ucenter/images/noavatar_big.gif;
}
location ~ /(.
)_middle.jpg$ {
error_page 404 /ucenter/images/noavatar_middle.gif;
}
location ~ /(.*)_small.jpg$ {
error_page 404 /ucenter/images/noavatar_small.gif;
}
expires 300;
break;
}
}
jspace rewrite

location ~ .*.php?$
{

#fastcgi_pass unix:/tmp/php-cgi.sock;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fcgi.conf;
}

location ~ ^/index.php/
{
rewrite ^/index.php/(.
) /index.php?$1 break;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fcgi.conf;
}

三、常用配置

Nginx强制使用https访问(http跳转到https)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
## 方法一:80、443单独进行配置
server {
listen 80;
server_name test.com;
... ...
rewrite ^(.*)$ https://$host$1 permanent;
}
## 方法二:同时配置80&443端口的访问,当访问80时强制调整到443
server {
listen 443; #ssl端口
listen 80; #用户习惯用http访问,加上80,后面通过497状态码让它自动跳到443端口
server_name test.com;
#为一个server{......}开启ssl支持
ssl on;
#指定PEM格式的证书文件
ssl_certificate /etc/nginx/test.pem;
#指定PEM格式的私钥文件
ssl_certificate_key /etc/nginx/test.key;
#让http请求重定向到https请求
error_page 497 https://$host$uri?$args;
}

###

参考

  • http://wiki.nginx.org/NginxChsHttpRewriteModule
  • http://blog.csdn.net/cnbird2008/archive/2009/08/04/4409620.aspx
  • http://www.divmy.com/
  • 推荐阅读:https://xuexb.com/post/nginx-url-rewrite.html#rewrite

工具类

  • nginx规则转换工具:
    • http://www.anilcetin.com/convert-apache-htaccess-to-nginx/
    • http://winginx.com/htaccess

代理模式

发表于 2018-04-04 | 分类于 php | | 阅读次数
  1. 在客户端与实体之间建立一个代理对象(proxy),客户端对实体进行的操作全部委派给代理对象,隐藏实体的具体实现细节。
  2. Proxy还可以与业务代码分离,部署到另外的服务器,业务代码中通过RPC来委派任务。

原型模式

发表于 2018-04-04 | 分类于 php | | 阅读次数

原型模式

  1. 与工厂模式作用类似,都是用来创建对象
  2. 与工厂模式的实现不懂,原型模式是首先创建好一个原型对象,然后通过clone原型对象来创建新的对象。这样就免去了类创建是重复的初始化操作
  3. 原型模式适用于大对象的创建。创建一个大对象需要很大的开销,如果每次new就会消耗很大,原型模式仅需内存拷贝即可

先建立一个对象原型,其后的每次操作先去clone原型对象,然后进行操作,减少对象初始化的开销。

观察者模式

发表于 2018-04-04 | 分类于 php | | 阅读次数

数据对象映射模式

发表于 2018-04-04 | 分类于 php | | 阅读次数
  1. 数据对象映射模式,是将对象和数据存储映射起来,对一个对象的操作会映射为对数据存储的操作。
  2. 在代码中实现数据对象映射模式,我们将实现一个 ORM 类,将复杂的 SQL 语句映射成对象属性的操作。
    1. 结合使用数据对象映射模式,工厂模式,注册器模式

策略模式

发表于 2018-04-04 | 分类于 php | | 阅读次数
  1. 策略模式,将一组特定的行为和算法封装成类,以适应某些特定的上下文环境,这种模式就是策略模式
  2. 实际应用举例,假如一个电商网站系统,针对男性女性用户要各自跳转到不同的商品类目,并且所有广告位展示不同的广告
  3. 使用策略模式可以实现 Ioc,依赖倒置、控制反转

代码实现和使用

控制反转

策略模式 依赖到置。 解耦。
[ 查看全文 ]

适配器模式

发表于 2018-04-04 | 分类于 php | | 阅读次数

新建一个IDatabase

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
interface IDatabase{
function connect($host,$user,$password,$dbname);
function query($sql);
function close();
}
Database下面的 mysql mysqli pdo
namespace IMooc\Database;
use IMooc\IDatabase;
class Mysql implements IDatabase{
protected $conn;
function connect($host, $user, $password, $dbname){
$conn = mysql_connect($host,$user,$password);
mysql_db_name($dbname,$conn);
$this->conn = $conn;
}
function query($sql){
$res = mysql_query($sql,$this->conn);
return $res;
}
function close(){
mysql_close($this->conn);
}
}
namespace IMooc\Database;
use IMooc\IDatabase;
class PDO implements IDatabase{
protected $conn;
function connect($host,$user,$password,$dbname){
$conn = new \PDO("mysql:host=$host;dbname=$dbname",$user,$password);
$this->conn = $conn;
}
function query($sql){
return $this->conn->query($sql);
}
function close(){
unset($this->conn);
}
}

装饰器模式

发表于 2018-04-02 | 分类于 php | | 阅读次数

定义一个装饰器的接口,声明两个方法,beforXXX() afterXXX(), 然后在类里定义一个方法 addDecorator 添加一个装饰器,保存到一个内部数组,再定义一个beforXXX() afterXXX(); 分别循环每个装饰器,执行装饰器里定义的beforXXX afterXXX方法, 最后在执行代码之前和之后添加$this->beforXXX() 和 $this->afterXXX()

迭代器模式

发表于 2018-04-02 | 分类于 php | | 阅读次数

迭代器模式

  1. 迭代器模式,在不需要了解内部实现的前提下,遍历一个聚合对象的内部元素
  2. 相比传统的编程模式,迭代器模式可以隐藏遍历元素所需的操作

应用场景
遍历数据库表,拿到所有的user对象,然后用佛 foreach 循环,在循环的过程中修改某些字段的值。

如果一个对象是一个集合,比如数据结果集。
我们通常需要逐个取出每一个元素,如果想用foreach逐个取出的话,集合类需要继承迭代器接口,实现接口中的方法,才可以被foreach迭代。
迭代器模式其实就是可使用foreach模式.

迭代器需要实现的方法:

  1. rewind,将索引重置到数组第一个元素;
  2. valid,验证数据有效性;
  3. current,获取当前数据;
  4. next,将索引值向下移动;
  5. key,获取当前索引

参考资料

  • Iterator(迭代器)接口 :http://php.net/manual/zh/class.iterator.php
  • http://designpatternsphp.readthedocs.io/zh_CN/latest/Behavioral/Iterator/README.html
  • http://laravelacademy.org/post/2882.html
  • https://segmentfault.com/a/1190000007547513

PHP魔术方法

发表于 2018-04-02 | 分类于 php | | 阅读次数

php中的魔术方法有construct(), destruct(), call(), callStatic(), get(), set(), isset(), unset(), sleep(), wakeup(), toString(), invoke(), set_state(), clone() 和 __debugInfo() 等方法在 PHP 中被称为”魔术方法”(Magic methods)。在命名自己的类方法时不能使用这些方法名,除非是想使用其魔术功能。

__get/__set 类的属性魔术方法,当外部访问私有或者未定义属性时自动调用
__call/__callStatic 类的方法魔术方法,当外部访问私有或者未定义方法以及静态方法的时候自动调用 __callStatic也必须声明为static
__toString 将类的对象当成字符串使用时自动调用
__invoke 将类的对象当成函数使用时自动调用

1…567…26
Zack Hwang

Zack Hwang

Go

257 日志
42 分类
76 标签
RSS
Links
  • 小白博客
  • 我的书单
© 2018 Zack Hwang
由 Hexo 强力驱动
主题 - NexT.Muse
又拍云