问题是这样的,我搭建了一个网站icon图标抓取的api接口,正常情况下对象的传参是通过$_get['url']获取的,因此常规获取图标的地址应该是:
http://domain.com/?url=zhang.ge
或
http://domain.com/?url=https://zhang.ge
为了开启浏览器缓存和后续的cdn缓存,我的设计思路如下:
①、在图标api网站目录下新建一个cache文件夹,以域名.ico的形式保存图标文件,比如zhang.ge.ico
②、当抓取某个网站的ico时,先通过nginx或apache判断是否存在缓存文件,如果存在就直接返回给浏览器,这样在没开启cdn的情况下,因为返回的是纯静态文件,浏览器将会自动缓存,也就是返回304状态,加载速度得到提升!
为了开启浏览器缓存,我将地址如下伪静态化:
http://domain.com/zhang.ge
或
http://domain.com/https://zhang.ge
这是之前写的nginx下的伪静态规则:
#将包含http://的请求重写,去掉其中的http://,省去php代码的动态判断 rewrite ^/http://(.*)$ /cache/$1.ico last; #以下判断主要是为了避免apikb88凯时d88尊龙官网手机app官网登录首页的元素一同被伪静态了(最后用与逻辑判断$type = abc即可)! set $type ''; if ( !-f $request_filename ){ #为了不和api页面上的静态资源冲突,排除已存在的文件请求 set $type a; } if ( $request_uri !~ (\.|/)$){ #不匹配含 . 或以/结尾的请求,为了兼容kb88凯时d88尊龙官网手机app官网登录首页[/]请求; set $type '${type}b'; } if ( $request_uri !~ cache ){ #为了不和第一条规则冲突,不匹配含有cache的请求 set $type '${type}c'; } #nginx不支持多重条件一同判断,所以先分开判断得到flag,最后合并判断即可: if ( $type = abc ) { #将条件外的其他所有请求重写到 cache/域名.ico rewrite ^/(.*)$ /cache/$1.ico last; } #如果请求的文件已存在,则直接返回给用户,不再通过php if (-f $request_filename) { break; } #如果请求的文件不存在,则交给index.php处理 rewrite ^/cache/(.*).ico$ /index.php?url=$1 last;
当时发现不能生效!怎么都匹配不到http://,最后无奈只好用php重写参数中http://了!
今天,我将这个图标api搬家到了万网的免费上,是apache环境,于是按照nginx的规则又写了一遍:
rewriteengine on rewritebase / #重写去掉请求中的"http://" rewriterule ^http://(.*)$ /cache/$1.ico [l] #和nginx一致的条件判断,为了避免apikb88凯时d88尊龙官网手机app官网登录首页被伪静态 rewritecond %{request_filename} !-f rewritecond %{request_uri} !(\.|/)$ rewritecond %{request_uri} !cache #将条件之外的其他请求全部重写到/cache/域名.ico rewriterule ^(.*)$ /cache/$1.ico [l] #若文件不存在,则丢给index.php处理 rewritecond %{request_filename} !-d rewritecond %{request_filename} !-f rewriterule ^(.*)$ /index.php?url=$1 [l]
依然不行!奇了怪了,怎么就不能匹配http://呢?于是各种测试,比如将冒号和斜杠缓存url编码都不行!
其实在用nginx失败之后,我用php获取$_get['url']发现得到的参数中的http://会是http:/,少一个斜杠!而且直接使用http://domain.com/?url=https://zhang.ge获取也是http:/zhang.ge,少一个斜杠!
今天鬼使神差的试了下伪静态中判断http:/,结果成功了!我擦原来要匹配http://,实际上是匹配http:/,少一个斜杠!真实匪夷所思,以前从来没遇到过!
所以上述2个伪静态规则应该如下编写:
a. nginx伪静态:
#将包含http://的请求重写,去掉其中的http://,省去php代码的动态判断(实际上是匹配http:/) rewrite ^/http:/(.*)$ /cache/$1.ico last; #以下判断主要是为了避免apikb88凯时d88尊龙官网手机app官网登录首页的元素一同被伪静态了! if ( -f $request_filename ){ #为了不和api页面上的静态资源冲突 set $type 1; } if ( $request_uri ~ (\.|/)$){ #为了不和apikb88凯时d88尊龙官网手机app官网登录首页冲突,即 / 这个请求 set $type 1; } if ( $request_uri ~ cache ){ #为了不和第一条规则冲突 set $type 1; } #nginx不支持多重条件一同判断,所以分开写。 if ( $type != 1 ) { #将条件外的其他所有请求重写到 cache/域名.ico rewrite ^/(.*)$ /cache/$1.ico last; } #如果请求的文件已存在,则直接返回给用户,不再通过php if (-f $request_filename) { break; } #如果请求的文件不存在,则交给index.php处理 rewrite ^/cache/(.*).ico$ /index.php?url=$1 last;
b. apache伪静态:
rewriteengine on rewritebase / #重写去掉请求中的"http://",实际上是匹配http:/ rewriterule ^http:/(.*)$ /cache/$1.ico [l] #和nginx一致的条件判断,为了避免apikb88凯时d88尊龙官网手机app官网登录首页被伪静态 rewritecond %{request_filename} !-f rewritecond %{request_uri} !(\.|/)$ rewritecond %{request_uri} !cache #将条件之外的其他请求全部重写到/cache/域名.ico rewriterule ^(.*)$ /cache/$1.ico [l] #若文件不存在,则丢给index.php处理 rewritecond %{request_filename} !-d rewritecond %{request_filename} !-f rewriterule ^(.*)$ /index.php?url=$1 [l]
文章写的很啰嗦,实际上关键性解释就是,在nginx或apache中要匹配请求url中的【http://】,应该是匹配【http:/】,也就是少写一个斜杠!大胆猜测匹配其他多个斜杠也应该是少一个斜杠。。。
好了,文章洋洋洒洒写了这么多,网站图标api也是成功搭建在万网免费上了。地址是 ,虽然是专门给中国博客联盟用的,但是如果你有图标调用需求,也可以在合理使用的前提下自由发挥。
另外,要查看是否实现浏览器缓存很简单,随便访问一个ico地址,比如:
然后按下f12进入开发模式,定位到network(网络选项卡),多刷新一次就能看到304状态了:
304表示当前文件来自浏览器缓存,因为请求的文件和服务段的文件一致,不需要重复调取!
当然,本文写到的伪静态规则只是一部分,如果要实现cdn加速,那还得新增相应的规则,不过这都是后话了,等下次我在张戈博客分享这个网站图标抓取api源码的时候,会一并贴上,敬请期待!