其他
在读本文档之前,首先需要了解几个概念:
此文档已过期,仅适用于 v1.2
几个概念
scf:无服务器云函数
scf 是腾讯提供的无服务器云函数服务,它强调无服务器,即用户不需要关心服务器是什么配置,只需要负责好业务处理模块。用户需要提供一组函数代码,并设定特定的触发方式。当有事件产生并且该事件符合该触发方式时,服务器会自动调用用户提供的函数,并完成特定功能。
我们这次将要使用的事件是 api 网关事件。当特定网址被访问时,scf 会自动调用用户提供的函数。关于价格,对于个人来说,scf 提供的免费额度完全够用(具体额度参考 官网 )。
免费额度
资源类型 | 每月免费额度 |
---|---|
资源使用量 | 40 万 GBs |
调用次数 | 100 万次 |
由于 api 网关从 2019 年 12 月 4 日起开始商用,无免费额度,故我又对 onepoint 进行了一些修改,让它能够部署到其他地方。
映射网盘
首先这词可能是我原创的,百度不到。顾名思义,映射网盘并不是一个真正的网盘,它需要有其他网盘作为底层网盘。当用户访问映射网盘时,映射网盘负责请求转换,使得用户实际上访问的是其他网盘。
举个例子,oneindex 就是一个映射网盘,它的底层网盘是 onedrive 。
OnePoint
oneindex 项目很棒 ,但它只能运行在服务器上,代价太高。所以我们考虑用 scf 运行这一套服务,于是就有了 onedrive_scf 。但遗憾的是,这两个项目都对 onedrive 账号有要求,账号必须要能够开通 api 才行,像国内教育邮箱( edu.cn )注册的账号根本无法使用此功能。但 edu.cn 邮箱注册的 onedrive 又是最安全的,所以我就利用 sharepoint 的分享功能创造出了 onepoint,因此可以支持几乎所有的onedrive账户。
关于 onedrive 账号的问题,以后有时间了可以给大家再讲讲。
概述
OnePoint 是对原有 OnePoint (SharePoint 版本) 的扩展。原有的 OnePoint 通过路径映射的方式支持多个onedrive 网盘。这一次我把映射的对象改为了不同的网盘,忽略了网盘之间的差异性,只提取其文件名、大小、修改时间、类型、下载链接等共有信息,将其按照约定的数据类型排列,使得在通过映射网盘访问各个网盘时几乎感受不到差别。因为有了控制和数据的分离,因此,我们也就可以统一风格,让我们的网盘看起来更加规整,更加和谐,更加多样化。
基本流程
- 请求接口适配
- 路径映射
- 调用网盘函数,获取文件信息
- 调用渲染函数,获取 html
路径映射
一般来说,我们把请求的 url 按照这样的格式分割。
http://< ph >/< p0 >/< p1 >/< p2 >
为了便于说明,我们将单个映射后的网盘简称为网盘,将所有网盘组成的整体称为网盘组。
以 http://example.com/release/mmx/a/b/c 为例,各个部分意义如下:
- ph: 请求域名。例如 example.com
- p0: 云盘组无关路径(可为空字符串,尾部不为 " / " )例如 scf 的 /release
- p1: 云盘映射路径(非空字符串,首尾都是 " / " )例如原来的映射路径 /mmx/
- p2: 单个云盘请求路径(非空字符串,首部是 " / " )例如 /a/b/c
当一个 http 请求出现后,我们首先将路径中与云盘组无关的内容(p0)处理掉,剩下的p1+p2就是我们的网盘组的请求路径,我们将其简称为 p_12 。
而 p_12 再按照预先配置好的映射表,按照最长匹配原则分割得到 p1 和 p2 ,其中 p1 由映射的键决定,剩下的就是 p2 。
p2 就是单个网盘的请求路径。一个网盘处理函数只需要处理 p2 即可。
路径映射表格式如下:
const DRIVE_MAP = {
"/": {//映射路径
func: MS_OD,//该映射将会调用的函数, 由开发者提供
spConfig: {},//上面func函数需要的专用配置数据, 开发者决定其结构
cache: {},//开发者自行组织, 数据cache统一放到该对象下, 便于管理
password: "",//保留
}
}
网盘函数
调用形式
func(spConfig, cache, event);
- spConfig:配置文件,对应于 DRIVE_MAP 中的 spConfig 项。由开发者自定义,所需要的配置项均需要放在该对象里面。
- cache:缓存信息,对应于 DRIVE_MAP 中的 cache 项。内容同样由开发者自定义。所需缓存需要保存在里面。考虑到不同路径可能会调用相同的网盘函数,分开存储数据还是很有必要的。
- event:请求有关信息,结构如下
let event = {
method,//GET POST
headers,//http headers
body,//http body,数据为 json 格式
cookie,//解析自 headers, json 格式
query,//解析自 headers, json 格式
sourceIp,//访问 ip
splitPath:{
ph,p0,p_12,p_h01,p2//请求路径信息,与路径映射部分给出的定义相同
}
}
//@depressed 原 request 格式
//let request = {
// httpMethod,//get post
// url_ph01,// //ph/p0/p1, 例如 //release/mmx
// url_p2,// p2, 路径信息,查询该路径下的文件列表或文件。例如 /a/b/c
// queryString,//scf event 提供
// headers,//scf event 提供
// body,//scf event 提供
// sourceIp//访问源ip
//}
一些约定
- query 和 body 保留关键字 sys password json preview ? ,建议不要使用这些
- splitPath 中有可能包含 % # ? 字符,作为 url 返回前需要转义。
一些建议
- query[refresh] 为真时,应重新获取文件列表,并更新 cache。
- query[spPage] 为真时,可通过 spPage 指定文件列表的某一页。
返回值结构
下面是返回对象的结构表,实际使用中只需要返回指定的部分值,具体构成参考下面的具体返回。
{
noRender:true,//如果为true ,则必须与 statusCode headers html 配合使用
html:"",//noRender 为true时有效
statusCode: 200,//200 301 302 401 403 404 500,
type: 1, //0_file 1_dir 2_info #200
data: { // #200
content: [
{
nodeType: 0, //type: 0_file 1_dir 3_drive, drive 类型由系统自动生成。
name: "文件名或文件夹名或云盘名",
fileType: "txt",//文件类型,不带点,nodeType为0时有效
url_p2: "/a/b/c", //以p2为基准的根目录
size: "文件大小xx MB,文件夹 XX 个项目 或 xx MB",
modified: "最近修改日期,文件夹或云盘可为空",
otherInfo: {} //此项不用,留给开发者存放其他信息 //可为 undefined
}
],
prevHref: "", //上一页,以p2为基准的请求 可为 undefined
nextHref: "", //可为 undefined
fileInfo: {
downloadUrl: "https://example.com/abc.txt",//直链
name: "abc.txt",//文件夹名
fileType: "mp4",//文件类型,不带点
url_p2: "/a/b/c/abc.txt",//以p2为基准的根目录
size: "XX MB",//XX items 或 xx MB
modified: "2019-01-02 15:02:44",//最近修改日期,固定格式
otherInfo: {},//此项不用,留给开发者存放其他信息 可为 undefined
mimeType: "",//保留, 此项不用 可为 undefined
}
},
headers:{// info
location:'http://example.com',//# 301 302
'set-cookie':cookiecookie
},
info: "", //all
readMe: { //all
type: 0, //0空,1链接,前端实现加载, 2 md文本,建议不要过长
txt: ""
},
script: "" //all
}
- 其中 可为 undefined 意味该属性可以为 undefined。否则即使为空串,空对象,空数组 也要写成完整形式。为了方便起见,提供了 Msg_file Msg_list Msg_info 三个消息函数以简化返回过程,具体使用可参考函数的源码。
- 无论是 nextHref,prevHref 还是 url_p2 ,他们都是链接,返回值仍属于 p2 类型。如果其中含有 query 内容,则该链接必须以&结尾。例如 /a/b/c?spPage=5&num=6&。
- nextHref,prevHref 还是 url_p2 所返回链接的 path 部分,里面如包含 % ? # 则必须转义为 %25 %3f %23。
- downloadUrl,请求文件时此项必须为直链。如果 downloadUrl 不为直链,建议返回 301。
- readMe:页面的 readme,由 type 和 txt 两部分组成,type 为 0 表示无 readme ;1 表示 txt 为 readme 文件的链接,由前端 Ajax 实现加载;为 2 表示文本,前端负责 md 渲染。
- script:一段可以运行在页面中的脚本,由网盘函数提供脚本内容。
200_文件列表
{
statusCode: 200,//固定值
type: 1,//1_dir 固定值
data: {// #200
content: [
{
nodeType: 0,//type: 0_file
name: "abc.txt",//文件名
fileType: "txt",//文件类型,不带点
url_p2: "/a/b/c/abc.txt",//以p2为基准的根目录
size: "10.32 MB",//文件大小xx.xx MB, 保留两位小数,中间空格不可少
modified: "2019-01-02 15:02:44",//最近修改日期,固定格式
otherInfo: {}//此项不用,留给开发者存放其他信息 可为 undefined
},
{
nodeType: 1,//1_dir
name: "d",//文件夹名
fileType: "",// 为 "" 或 undefined
url_p2: "/a/b/c/d/",//以p2为基准的根目录
size: "XX items",//XX items 或 xx MB
modified: "2019-01-02 15:02:44",//最近修改日期, 固定格式
otherInfo: {}//此项不用,留给开发者存放其他信息 可为 undefined
}
],
prevHref: "/a/b/c/?page=5",//上一页, 以p2为基准的请求, 留空则表示无上一页 可为 undefined
nextHref: "" //可为 undefined
},
readMe: {//all
type: 0,//0空, 1链接 由前端实现加载, 2文本 建议不要过长
txt: ""
},
script: ""//all
}
200_文件信息
{
statusCode: 200,//固定值
type: 0,//0_file 固定值
data: {// #200
fileInfo: {
downloadUrl: "https://example.com/abc.txt",//直链
name: "abc.txt",//文件夹名
fileType: "mp4",//文件类型,不带点
url_p2: "/a/b/c/abc.txt",//以p2为基准的根目录
size: "XX MB",//XX items 或 xx MB
modified: "2019-01-02 15:02:44",//最近修改日期,固定格式
otherInfo: {},//此项不用,留给开发者存放其他信息 可为 undefined
mimeType: "",//保留, 此项不用 可为 undefined
}
},
readMe: {//all
type: 0,//0空,1链接,前端实现加载,2文本,建议不要过长
txt: ""
},
script: ""//all
}
200_消息通知
{
statusCode: 200,//固定值
type: 2,//2_info, //固定值
info: "访问文件不存在",
headers:{},
readMe: {//all
type: 0,//0空,1链接,前端实现加载,2文本,建议不要过长
txt: ""
},
script: ""//all
}
3xx_重定向
{
statusCode: 301,//301 302 固定值
info: "重定向",//
headers:{},
readMe: {//all
type: 0, //0空,1链接,前端实现加载,2文本,建议不要过长
txt: ""
},
script: ""//all
}
4xx_5xx_info
{
statusCode: 404,//401 403 404 500 固定值
info: "访问文件不存在",//#401 403 404 500
headers:{},
readMe: {//all
type: 0, //0空,1链接,前端实现加载,2文本,建议不要过长
txt: ""
},
script: ""//all
}
noRender
{
noRender:true,
statusCode: xxx,
headers:{},
html:""
}
渲染函数
view 层:
四个函数
文件列表,文件预览,信息通知,密码认证
r200_list(data, readMe, script, splitPath, G_CONFIG);
r200_file(fileInfo, readMe, script, splitPath, G_CONFIG);
r401_auth(info, readMe, script, splitPath, G_CONFIG);
rxxx_info(info, readMe, script, splitPath, G_CONFIG);
其中 splitPath, G_CONFIG 分别为:
let splitPath = {
"host": "//" + host,
"p0": p0,
"p1": p1,
"p2": p2
};
let G_CONFIG = {
"enablePreview": true,
"site_title": "onePoint Demo",
"site_icon": "",
"site_keywords": "onePoint",
"site_description": "onePoint description",
"site_script": ""//统计代码之类的可以放这里
};
渲染函数相对来说就比较自由,但仍需要遵守下面的规则。
一些规定
- 渲染链接 nextHref,prevHref 和 url_p2 时,必须加上 ph p0 p1 部分。例如 /a/b/d 将被渲染成 //example.com/release/mmx/a/b/d
- enablePreview 开启时 必须在 文件类型的链接后面加上 ?&preview 例如 /a/b/c?&preview
- G_CONFIG.script 和 script 必须放到 html 中,并保证他们能够被执行。
- 这里的 splitPath 无需再转义,可以直接使用。
编码建议:
建议 node,其他也可,但需要符合返回值格式。
更新日志:
191201
修改 request 为 event
191110
request 新增 sourceIp, req_cookie_json, req_body_json
新增 noRender html 返回项
191101
修改 func(spConfig, cache, p2, query, body);
整合p2 queryString body 至 request 中, p2改名为 url_p2;整合 redirectUrl 至 headers
191029
初次发布
本文由 ukuq 创作,采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为: Mar 15, 2020 at 05:26 pm
有没有视频教程
暂时还没有