上一节 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 winston
logger.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 winston
var 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 instance
var appiumServer = appium(args);
// Hook up REST http interface
appiumServer.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事件,关闭服务的时候,会调用设置好的回调函数。