js校验原生客户端日志开发
video_js_template
工程编译与使用
工程编译
- 使用
./wbinit.sh
脚本,安装本工程需要的相关依赖; - 使用
npm run webpack
,调用./wbnpx.sh
脚本进行webpack打包;使用node ./dist/bundle.js
可执行打包后的bundle.js
文件; - 使用
npm run build
,内部调用./wbnpx.sh;./wbversion.sh build
脚本进行webpack打包,同时打出来的bundle.js
会生成version版本变量,可使用npm run build 2
来指定build号为2,不传build号则版本信息里的build号会自增;版本信息存储在version.data
文件中; - 使用
npm run release
,调用./wbnpx.sh;./wbversion.sh release
脚本进行webpack打包,同时打出来的bundle.js
会生成version版本变量,可利用npm run release 1.0
命令指定版本号,如果不传版本号会展示最后一次的version号;如果本地安装了wbcompile
工具,在使用npm run release xx
时会直接上传bundle.js
到ftp对应目录下; - 使用
npm run start
可启动nodemon
服务,此服务会监听工程目录下的/tscompile
文件夹文件的改动,若有更改时自动运行项目; - 使用
npm run tscompile
触发编译或者Command + shift + b
手动触发tasks.json
任务,可编译/src/下的所有ts文件,把编译后的中间产物输出到/tscompile
文件夹下,如果开启了nodemon
服务,会自动触发nodemon的watch事件,触发热更新;配置了launch.json
文件,可使用VSCode自带的运行和调试(command + shift + D)
对项目中的具体代码进行断点和调试开发; - 使用
npm run dev
,打开本地server,方便利用chrome调试; - 终端 -> 运行任务 -> 显示所有任务 -> tsc:监视 - tsconfig.json,可以动态编译ts;
设计思路
整体流程
原生端上执行bundle.js
代码,获取js运行环境,然后通过调用js函数并把当前日志json和这条日志对应的js模板代码作为参数,来对日志进行校验,js会返回校验的结果,端上根据返回结果做UI显示;
初步解决方案
js校验api介绍
校验工具暴露出的接口如下
loadTemplate(code: string)
: 加载模板字符串,参数为模板字符串,可以为json或者js模板字符串,内部会自动判断;loadJSTemplate(code: string)
: 参数为动态下发的js文件的模板字符串;可把需要的js模板文件加载执行;loadJsonTemplate(jsonString: string)
: 参数为下发的json格式的模板字符串;加载json模板;checkFunction(log: string, context: string)
: 第一个参数为需要校验的json字符串,第二个参数为需要增量结合模板校验的context;loadJSTemplateAndExecute(code: string, log: string, context: string)
: 加载单个js模板,并立即执行校验;loadJsonTemplateAndExecute(jsonString: string, log: string, context: string)
: 加载单个json模板,并立即执行校验;
loadTemplate、loadJSTemplate、loadJsonTemplate 这三个方法的返回值是json数组,示例如下:
[{"id":"799","items":[{"name":"uicode","logic":3,"rule":"^[0-9]+$"},{"name":"fid","rule":"@fid == 232673"},{"name":"friend","logic":1,"rule":"hi amigo #$$#, my name is #$placeholder$#, my age is #$p$#,see you!"},{"name":"source_info","rule":"(@mid >= 0) && (@source_info include 'face_sign_1')"},{"name":"mid","logic":4},{"name":"ext","sub":[{"name":"objectid","logic":3,"rule":"^[0-9]{1,}(:|.{3})[0-9]+$"},{"name":"authorid","logic":3,"rule":"[0-9]{1,}$"}]}]},{"id":"template123","items":[{"name":"fid","rule":"@fid == 232673"}]},{"items":[{"name":"fid","rule":"@fid == 232673"}],"id":"template456"}]
checkFunction、loadJSTemplateAndExecute、loadJsonTemplateAndExecute 三个方法的返回值为json,示例如下:
{"success":true,"code":1,"reason":"","results":[{"key":"uicode","value":"10001344","success":true,"logic":3,"required":false,"rule":"^[0-9]+$"},{"key":"fid","value":"232673","success":true,"logic":"","required":false,"rule":"@fid == 232673"},{"key":"friend","value":"zjd","success":true,"logic":1,"required":false,"rule":"hi amigo zjd, my name is wyb, my age is 18,see you!"},{"key":"source_info","value":"face_sign_1","success":true,"logic":"","required":false,"rule":"(@mid >= 0) && (@source_info include 'face_sign_1')"},{"key":"mid","value":"4805675316939808","success":true,"logic":4,"required":false,"rule":"Function: e=>!!e.mid&&/^[0-9]+$/.test(e.mid)"},{"key":"objectid","value":"1034%3A4805674547478607","success":true,"logic":3,"required":false,"rule":"^[0-9]{1,}(:|.{3})[0-9]+$"},{"key":"authorid","value":"7168897192","success":true,"logic":3,"required":false,"rule":"[0-9]{1,}$"}]}
工具脚本的使用
使用下面命令安装配套的脚本工具:
# 一键安装wbcompile.sh脚本
sudo curl http://ftp.client.weibo.cn/UI_Image/Video/ShellTools/installwbcompile.sh | sh
wbcompile
脚本具有处理新建日志模板、编译commonJS文件、上传ftp等功能,具体可通过wbcompile -h
查看帮助命令;常用方法总结如下:
wbcompile -t templateName
可在当前执行脚本的目录下生成templateName.ts
模板文件,可根据需求修改模板文件保存;wbcompile -i inputFile(inputDir) -o outputDir
或者wbcompile inputFile(inputDir) outputDir
命令对需要编译的文件进行编译,支持对typescript
和ES6
文件进行统一编译成ES5
规范; -i 是需要编译的文件或文件夹,如果 -i 参数为文件夹,支持递归遍历子目录编译;-o 是编译后输出的文件路径;wbcompile -u file
调用上传命令,上传编译好的ES5文件到ftp服务器;
日志模板的定义
property | 含义 | 备注 |
---|---|---|
name | 需要校验的字段名,如uicode; | |
required | 是否是必须字段,即如果校验失败是否抛异常;默认是false; | |
sub | 如果验证的字段是复合型,比如ext字段,则支持多级嵌套; | |
logic | 逻辑关系,值含义枚举:0:表达式解析;1:包含;2:相等;3:正则;4:js函数; | |
rule | 和logic绑定关系,需要用来校验的rule; | logic为4时,rule为函数或者函数字符串,会调用rule函数来判断校验结果,参数为整个json转成的对象;logic为0或者不传时,默认使用表达式解析规则;可支持常用一元、二元操作符以及逻辑关系; |
rule支持placeholder功能,可使用#$ here-could-be-anystring $#
包括起来的占位符来进行占位,在context传进来时替换占位符,如代码所示:
// 如context 有个friend字段,需要动态拼接rule规则,可按下面示例所示构建rule,可用逗号分割多个值替换多个占位符
var context = '{"friend":"zjd,wyb,18"}';
{
name:"friend",
rule:"hi amigo #$$#, my name is #$placeholder$#, my age is #$p$#,see you!"
}
// 最终拼接好的用来校验的rule
hi amigo zjd, my name is wyb, my age is 18,see you!
遇到的问题和解决办法
- 原生
JSContext
不支持执行多个es6 js
文件,需要合并es6 js
文件; - 使用
webpack
解决多个js文件合并问题,但是使用webpack
的bundle.js
文件是直接执行的匿名函数,一些export的方法名原生执行不到; - 编写
wbnpx.sh
脚本,对webpack生成的bundle.js
文件做处理。匹配入口文件app.js
中需要导出的对象,在bundle.js里直接写入; - 项目中js语法太过灵活,无法做类型定义,项目整体切换到
typescript
; - 单个js文件中可包含多个校验模板,模板和校验
log
逻辑拆分; - 利用
eval()
函数动态执行js文件字符串或者json模板字符串,可动态下发js代码执行; - 校验逻辑新增规则,可在js模板里定义一个
function
对象或者function字符串
来进行校验,利用eval函数动态校验规则;同理json模板里也可返回function字符串
;function的参数为json转成的对象
; - 编写
wbcompile.sh
脚本,脚本可以生成模板文件,执行ts文件
和es6文件
转为es5文件
,支持递归遍历子目录编译;支持直接上传ftp服务器; - 增加表达式解析规则,支持常用逻辑表达式解析,根据
LL(1)递归下降词法算法
编写解析器,读取输入表达式生成AST语法树,操作语法树节点运算校验;表达式支持一元、二元操作符,支持逻辑关系,支持变量的使用,示例如:(@mid === (1+2+3)*2-5) && (@source_info include 'face_sign_1')
; - 编写版本管理脚本,记录每次build行为,保存为
version.data
便于读取;支持build号自增,支持指定release version
; - 在使用
wbcompile -u
上传本地创建好的模板文件时,先通过ftp拉取已经存在的模板配置configurationtable.json
文件;通过脚本创建中间处理文件temp_merge_table.js
,把模板js文件的内容直接输入到temp_merge_table.js
文件中,把configurationtable.json
配置文件的json字符串通过脚本转为temp_merge_table.js
中的一个变量,然后通过编写代码做配置文件的合并;合并完成以后生成新的configurationtable.json
文件,上传到ftp对应目录下; - done.