上一节 Appium Server 源码分析 (一) 中我们大体讲了,appium server在正确运行前做的一些判断,下来我们正式看看main 方法
在看main方法之前我们可以得看看main.js引用的那一大堆第三方的模块的主要作用是什么。
变量 | 模块 | 作用 |
---|---|---|
http | http | http模块 |
express | express | appium server 采用的是express的web框架 |
favicon | serve-favicon | 网页图标模块 |
bodyParser | body-parser | express项目中参数解析 |
methodOverride | method-override | 重写http请求的一些方法 |
morgan | morgan | logger(记录器),在控制台中显示req请求的信息 |
routing | ./routing.js | appium的路由表,就是指明了每一个请求过来时,应该要如何处理 |
appium | path | nodejs 处理目录的对象 |
http | ../appium.js | 存储配置信息,以及服务端的对象,另外还有设备的判断处理 |
parserWrap | ./middleware | 看了大体的代码应该是对python的客户端做了特殊的处理 |
appiumVer | ../../package.json | appium的版本 |
appiumRev | null | |
async | async | 流程控制工具包,解决地狱式回调的问题,很强大的工具 |
helpers | ./helpers.js | 本地的一个帮助模块 |
logFinalWarning | ./helpers.js | 处理使用了将要废弃的api的警告,给出提示信息 |
getConfig | ./helpers.js | 获取appium的配置信息 |
allowCrossDomain | ./helpers.js | 对于请求头的安全校验,对于匹配的请求头才返回200 |
catchAllHandler | ./helpers.js | 500的异常处理 |
checkArgs | ./helpers.js | appium 参数配置的检查 |
configureServer | ./helpers.js | appium server的配置检查(暂时没看懂) |
startListening | ./helpers.js | 启动http server 监听对应的端口 |
conditionallyPreLaunch | ./helpers.js | appium的预创建模式(没懂) |
prepareTmpDir | ./helpers.js | 创建一个tmp目录 |
requestStartLoggingFormat | ./helpers.js | 格式化log,使用colors插件 |
requestEndLoggingFormat | ./helpers.js | 同上 |
domainMiddleware | ./helpers.js | 没懂 |
好了,下来正式看看我们的主角吧。
var nodeVer = Number(process.version.match(/^v(\d+\.\d+)/)[1]);if (nodeVer < 0.10) {logger.error("Appium requires Node >= 0.10");process.exit(1);}if (nodeVer < 0.12) {logger.warn("Appium support for versions of node < 0.12 has been " +"deprecated and will be removed in a future version. Please " +"upgrade!");}
判断nodejs的版本如果是小于0.10版本则直接退出,若小于0.12版本则给出相应的警告。
var rest = express(), server = http.createServer(rest);rest.use(domainMiddleware());rest.use(morgan(function (tokens, req, res) {// morgan output is redirected straight to winstonlogger.info(requestEndLoggingFormat(tokens, req, res),(res.jsonResp || '').grey);}));rest.use(favicon(path.join(__dirname, 'static/favicon.ico')));rest.use(express.static(path.join(__dirname, 'static')));rest.use(allowCrossDomain);rest.use(parserWrap);rest.use(bodyParser.urlencoded({extended: true}));// 8/18/14: body-parser requires that we supply the limit field to ensure the server can// handle requests large enough for Appium's use cases. Neither Node nor HTTP spec defines a max// request size, so any hard-coded request-size limit is arbitrary. Units are in bytes (ie "gb" == "GB",// not "Gb"). Using 1GB because..., well because it's arbitrary and 1GB is sufficiently large for 99.99%// of testing scenarios while still providing an upperbounds to reduce the odds of squirrelliness.rest.use(bodyParser.json({limit: '1gb'}));rest.use(morgan(function (tokens, req, res) {// morgan output is redirected straight to winstonvar data = '';try {if (req.body) data = JSON.stringify(req.body).substring(0, 1000);} catch (ign) {}logger.info(requestStartLoggingFormat(tokens, req, res), data.grey);}, {immediate: true}));rest.use(methodOverride());// Instantiate the appium instancevar appiumServer = appium(args);// Hook up REST http interfaceappiumServer.attachTo(rest);routing(appiumServer);rest.use(catchAllHandler);
创建express的http服务,并通过rest.use加载一系列的中间件,这些中间件的作用在前面的表格里其实已经大部分都说明了,并且在这中间件中还在夹带着初始化了一个appiumServer。实际上appiumServer就是一个附带着参数配置以及http服务的对象
async.series([function (cb) {configureServer(getConfig(), appiumVer, appiumServer, function (err, rev) {if (err) return cb(err);appiumRev = rev;cb();});},function (cb) {prepareTmpDir(args, cb);},function (cb) {conditionallyPreLaunch(args, appiumServer, cb);},function (cb) {startListening(server, args, parser, appiumVer, appiumRev, appiumServer, cb);}], function (err) {if (err) {process.exit(1);} else if (typeof readyCb === "function") {readyCb(appiumServer);}});server.on('close', function () {logFinalWarning();doneCb();});
最后是一系列的同步操作async.series
是顺序执行,最后添加close事件,关闭服务的时候,会调用设置好的回调函数。