本文介绍百度云主机BCH多域名分别绑定不同子目录实现一机部署多站的nginx配置文件写法之一。

BCH上原有一个example.com绑定在webroot根目录,最近想增加一个newdomain.com,与原来的网站分别放入两个子目录中。阿里云主机可以通过修改Apache.htaccess文件中的rewrite规则实现,想必BCH也能通过修改nginx配置文件实现,于是一番学习nginx配置文件的语法规则。

反复修改webroot目录下的bcloud_nginx_user.conf,怎么都无法实现想要的效果,百思不得其解。怀疑是不是BCH限制了一机多站,于是发工单询问百度技术支持,确认没有做特别限制后,继续探索。根据HTTP响应情况和log文件记录情况逐步调试,最终成功写出了完整的配置文件,实现了预期效果。下面将配置文件内容分享给大家参考。

if ($host ~* (www.)?(example|newdomain).com) {
    set $subsite $2;
}

首先匹配绑定的两个域名example.comnewdomain.com,设置子站标识。同时在webroot目录中创建两个子目录examplenewdomain分别放置两个网站的文件。

location = / {
    root /home/bae/app/$subsite;
    if (-f $request_filename/index.html) {
        rewrite (.*) /$subsite/index.html break;
    }
    if (-f $request_filename/index.php) {
        rewrite (.*) /index.php last;
    }
}

将最常用的首页path=/匹配出来,设置文档根目录为上一步创建的子目录。如果子目录中存在index.html则重定向到子目录,中止匹配;如果子目录中存在index.php则重定向到index.php,继续匹配。

location ~* \.(html|htm|js|css|jpg|jpeg|png|gif|svg|ico) {
    rewrite ^/(.*) /$subsite/$1 break;
}

处理静态文件,全部重定向进入子目录,中止匹配。

location ~* \.php {
    root /home/bae/app/$subsite;
    if (!-f $request_filename) {
        rewrite (.*) /index.php last;
    }
    set $path_info "";
    set $real_script_name $fastcgi_script_name;
    if ($fastcgi_script_name ~ "^(.+?\.php)(/.+)$") {
        set $real_script_name $1;
        set $path_info $2;
    }
    fastcgi_pass 127.0.0.1:9000;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$real_script_name;
    fastcgi_param SCRIPT_NAME $real_script_name;
    fastcgi_param PATH_INFO $path_info;
    fastcgi_param SERVER_PORT 80;
    include fastcgi_params;
}

处理php脚本文件,把官方文档中关于server级配置中对php文件的处理,直接复制过来进行修改覆盖。增加第2~5行,设置新的文档根目录为子目录,如果脚本不存在,重定向到首页,重新匹配本规则;如果脚本存在,则转交给fastcgi处理。

location ~* ^\/[^\.]*$ {
    root /home/bae/app/$subsite;
    # index index.html index.php;
    if (-f $request_filename/index.html) {
        rewrite (.*) /$subsite$1/index.html break;
    }
    if (-f $request_filename/index.php) {
        rewrite (.*) $1/index.php last;
    }
    if (!-f $request_filename) {
        rewrite (.*) /index.php last;
    }
}

匹配path为二级或多级目录的情形,寻找目录中的index.htmlindex.php,如果找不到也重定向到首页。注意这里不能使用index指令(第3行)设置默认首页文件,会产生循环重定向问题。

将上述代码块组合到一起,就是完整的bcloud_nginx_user.conf文件,放入webroot根目录,重载站点即可。注意要清空控制面板中的默认首页配置,也就是bcloud_nginx_gen.conf中不能有重复的location匹配,不然会产生冲突。

大学时期刚开始玩单反就有一个梦想,将来有一天凑齐佳能大三元镜头,尤其那只小白(EF70-200F2.8)。可是当我毕业工作后,一是觉得钱难赚,花这么大一笔钱很犹豫,二是工作忙对摄影并不上心,搁置了很长一段时间。所以时至今日,时隔12年,才终于实现了这个梦想。

卖掉了17年购入的6D、10年首批购入的EF24-105F4,保留了EF50F1.4EF16-35F2.8,新购入R6mark2以及RF24-70F2.8RF70-200F2.8,如下图是我现在所有的器材。

这次贵州游的第四天晚上,我俩驾车到达了西江收费站。出高速查贵州健康码是例行操作,然而当他们发现我俩的行程码有北京字样后,试图劝返我们,说苗寨这几天在过鼓藏节,不接待外省游客,这可真是晴天霹雳呀。

我要求他们先放行,到苗寨进不去再说。于是在最后不到十公里的山路上,我不断打电话给景区和当地防疫部门沟通,得到的答复都是不能进。我仔细想了想,并没有因为鼓藏节活动拒绝所有外族游客,而是仅仅限制行程码有外省字样的游客,那这性质不就成了过度防疫嘛。毕竟我们已经按照贵州省的政策,实行了三天三检,绿码可自由通行。于是拨打贵州12345反映这个事,但是12345时效性慢,远水不解近渴呀,还是得想别的办法。

这个时候媳妇已经把车开到了景区停车场,跟民宿管家沟通退房,并且在看景区外的酒店了。我不想重新规划所有后续的行程,也不想放弃这次进寨的机会,留下遗憾,那还是继续想办法吧。这时我发现线上已经买不了门票了,应该是系统对身份证号加了校验,那就只能尝试现场购票。然而我们到了售票大厅门口又一次被劝返,反复商量后,才进去在自助机上买到了票,好在自助机并没有限制身份证号。

有票就好办了,停车场取行李,尝试过检票口这最后一关。幸运的是,检票口保安检查并不严格,我说了句“刚买票的时候查过了”,就放行进去了。惊心动魄,气愤又刺激。差一点就进不来,幸亏没有放弃。

幸运的是赶上了十三年一次的鼓藏节,可气的是被他们搞这么一出。层层加码、过度防疫,但却又没能力落实、执行不到位。当时售票厅门口的人从手机里翻出一个相关通知的图片给我看,落款是景区运营公司,并不是防疫部门,差点就被唬住了。

当然,进来是进来了,还是要严格做好防疫措施,及时做核酸,尽量避免聚集。

- 阅读剩余部分 -

在React或Vue中使用前端路由的history模式时,由于服务端会配合使用URL Rewrite技术,产生的效果就是,SPA页面多个path的请求实际返回的是同一个入口文件。

GET https://idealecho.cn/spa/apath
GET https://idealecho.cn/spa/bpath

Response https://idealecho.cn/spa/index.html

在页面采用强缓存策略的情况下,当服务端文件更新后,用户需要手动刷新页面强行使用协商缓存机制获取最新版本,并更新本地缓存副本。而浏览器对页面进行缓存,使用的key是请求中的path值,这就导致本地会产生多份入口文件的缓存副本,并且版本可能并不一致。

在上例中,浏览器为/spa/apath/spa/bpath两个path分别缓存index.html文件副本,last-modifiedetag可能不同。

除非用户对多个path分别手动刷新,否则很容易造成通过链接在多个path间跳转时,页面在新旧版本间变换。

尤其当开发者对某个path做了自动重定向redirect,让用户很难对原始path手动刷新,也就没法更新对应的缓存。这样即便对其他所有path都进行了刷新,但只要通过前述path进入页面,都会得到页面的旧版本。

解决办法:

第一种,对入口文件index.html设置Cache-Control: no-cache以禁用本地缓存;

第二种,服务端保存一个前端最新产出的版本号,页面定时拉取这个版本号与自身版本号对比,发现过期即刷新页面。