之前有个带权限验证的CDN服务,没有同步开通海外CDN,一直用一台香港的服务器提供文件服务。为了实现和CDN一样的权限算法,是用Node做的服务器。JS做权限验证逻辑当然是非常轻松的,但是Node做文件服务就有点力不从心了,读文件流,写http流,零拷贝不知道怎么实现,似乎还有定位不出来的内存泄漏之类的问题,服务过几天就莫名其妙的会死一下,还要写个监控把它拉起来。
其实一直知道Nginx+Lua可能是最佳解决方案了,不过想想专门去学习一个在其他场合好像也没啥用处的语言……还是让Node服务去重启吧。
直到发现了NginScript(NJS),这就很适合用javascript写着这种无状态的计算服务嵌入到文件分发流程中了。
安装最新的Nginx+NJS,服务器是CentOS 8.2,选择了相应的rpm包:
rpm -Uvh https://nginx.org/packages/centos/8/x86_64/RPMS/nginx-1.20.1-1.el8.ngx.x86_64.rpm
rpm -Uvh https://nginx.org/packages/centos/8/x86_64/RPMS/nginx-module-njs-1.20.1%2B0.7.0-1.el8.ngx.x86_64.rpm
文件一直是在COS里面管理,通过COS分发到CDN的,最简单的让Nginx分发COS的方式是用COSFS把bucket挂载到/mnt目录下。不过8.0+的CentOS系统用yum安装COSFS的时候不兼容,要下载编译:
yum install automake gcc-c++ git libcurl-devel libxml2-devel fuse-devel make openssl-devel fuse
git clone https://github.com.cnpmjs.org/tencentyun/cosfs /usr/cosfs
cd /usr/cosfs
./autogen.sh
./configure
make
sudo make install
cosfs --version
github访问经常连不上,换了加速站点 github.com.cnpmjs.org 才顺利下载到。
因为要对文件访问做权限,所以挂载了COS的目录somewhere不能直接在Nginx里对外开放,要对内开放,只允许经过验证的请求用内部重定向的方式下载:
load_module modules/ngx_http_js_module.so;
......
http {
......
js_import http.js;
......
location /somewhere{
internal;
root /mnt/somewhere/;
}
location / {
js_content http.redirect;
}
这样外部来的http请求直接到http.js里面去鉴权通过了才能去访问到somewhere:
function redirect(r) {
for(var i in headers){
r.headersOut[i]=headers[i];
}
if(r.method == "OPTIONS"){
r.return(200, "ok");
}else{
var pathname = r.uri;
if(/\.((jpe?g)|(png)|(gif)|(ico)|(html?))$/.test(r.uri)){
r.internalRedirect('/somewhere'+r.uri);
}else if(r.args && r.args.data){
var checkResult = checkAuth(decodeURIComponent(r.args.data));
if(checkResult){
r.internalRedirect('/somewhere'+checkResult);
}else{
r.internalRedirect('/somewhere/404.html');
}
}else{
r.internalRedirect('/somewhere/404.html');
}
}
}
export default {redirect};
鉴权算法:
function checkAuth(fullpath){
const crypto = require('crypto'),
rFullPath = /https:\/\/www.myDomainName.com([^\.]*\.mp3)\?sign=([\d]+)\-([0-9a-z]+)\-([0-9]+)\-([0-9a-f]+)/ ;
cdnkey = "my-cdn-key...................";
if(!rFullPath.test(fullpath)){
return false
} ;
var t=fullpath.match(rFullPath);
var path=t[1],timestamp=t[2],rand=t[3],uid=t[4],md5=t[5]
var timeDiff = Date.now()-timestamp;
if(timeDiff>3600000){
return false
}
var data = path+"-"+timestamp+"-"+rand+"-"+uid+"-"+cdnkey;
if (md5 == crypto.createHash('md5').update(data).digest("hex")){
return decodeURI(path)
};
return false;
}
天下JS是一家,代码逻辑大部分从Node服务程序里面抠出来就直接可以用了。
就这样用NginScript简单复刻了腾讯云CDN的带校验静态文件分发。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。