基于源码分析appium服务端启动过程

写在前面

本文档主要是通过断点跟踪对于appium源码,从而记录的appium服务端的启动过程,如有错误或者理解不当之处,欢迎评论提出。
appium版本:1.7.2 客户端 appium-python-client 2018年1月
可以直接看结论,根据结论中的关键js文件即可断点跟踪出全过程。

appium文档

github
官方网站

主体结构

官方图片

首先是官方这张图片,这张图片简直涵盖appium所有知识点!而且对于这张图片还有中文的readme!
中文readme直通车
图上分类很清晰 基本上以appium为前缀的都被封装成了类库,通过npm加载,在node_modules中如下图所示,其中appium-base-driver为整个服务的基础类库。上图所示的 jsonwp-proxymobile-json-wire-protocal等都在里面。
image.png

node的express

appium的服务端采用的是express框架,express中文文档,如果之前用express建立过项目的话,会对express中的路由比较熟悉,很多时候路由的处理大概像Appium源码分析(3)-路由器模块这样列出来的样子,即通过rest.get('/wd/hub/status', controller.getStatus);该种方式可以查看到所有路由的处理,但是到今年18年appium的代码它的路由配置经过了层层调用。

而且作为node服务之前比较习惯入口的app.js即作为服务开启,但是在appium中它将该入口作为express模块直接放在了appium-base-driver中,也就是说appium源码的main入口并不是服务入口,那么他们之间的关系是一个怎样的继承及调用呢?

源码目录分析

假设我们想实现一个与客户端通讯的服务,那么主要包括服务开启、客户端http请求,响应函数,那么在appium中我们将其细化一下,大概是

开启服务->客户端传来请求->开启当前测试用例会话->根据配置确定ios、android等->分别处理ios或安卓请求->ios或安卓返回后->响应客户端吧->关闭会话。

首先看入口结构:

WX20180118-194031.png
  • build工程打包后出现的文件 程序执行来源于build中的main.js ,基本是对lib文件夹下通过babel对于代码进行的转换,所以调试的时候建议根据main.js调试
  • config.js 配置文件
  • logger.js 日志处理
  • parser.js 终端命令的处理
  • utils.js 基础函数
    main.js 中除了启动的一些检查,重点代码在于
import { server as baseServer } from 'appium-base-driver';
let router = getAppiumRouter(args);//该函数来源于appium.js
  //此处router返回的是个函数  用于装填路由路径 该函数执行路径位于/mjsonwp/mjsonwp.js 中routeConfiguringFunction 的返回函数
  //baseServer执行之后服务开始启动
let server = await baseServer(router, args.port, args.address);

这两行代码可nb厉害了……就这两行基本就把基础类库溜了一圈!代码都是几行几行的,然后一调就转一大圈
在appium.js中我们找到了以下函数

import { BaseDriver, routeConfiguringFunction, errors,
         isSessionCommand, processCapabilities } from 'appium-base-driver';

function getAppiumRouter (args) {
  let appium = new AppiumDriver(args);//实例化的这个类继承了appium-base-driver!
  return routeConfiguringFunction(appium);//这个函数来自于appium-base-driver 
}

由此成功引入基础类库appium-base-driver,然后就去那里翻吧

基础类库appium-base-driver

没截全的地方都是配置

画出的几个红框基本就是代码功能分类,其中jsonwp-proxymjsonwp是和协议相关,由于我不是很了解,所以不做介绍,只说明其中代码位置。
上边提到代码转向routeConfiguringFunction

routeConfiguringFunction

这出自mjsonwp/mjsonwp.js请牢牢的记住这个返回函数!!!

function routeConfiguringFunction (driver) {
//...省略一些
  // return a function which will add all the routes to the driver
  return function (app) {
    for (let [path, methods] of _.toPairs(METHOD_MAP)) {
      for (let [method, spec] of _.toPairs(methods)) {
        // set up the express route handler
        buildHandler(app, method, path, spec, driver, isSessionCommand(spec.command));
      }
    }
  };
}

它返回了一个函数并且里面还传参了app,之前断点打到这里时满脑子都是我是谁,我在哪里,我要干什么
我们把代码往上看一下routeConfiguringFunction的返回值返回给getAppiumRouter再返回给let router 然后再传给baseServer(怪我不好好学js……看个代码艰辛非常……)
那么baseServer来自哪里呢?看import,它来自appium-base-server!
main.js中调用了一圈再次进入appium-base-server

express中的server.js

之前说到要去找baseServer来自哪里,终于在express/server.js中找到了 就是appium的http服务启动的地方!所以说服务开启的地方不在外部!在基础类库里啊!

async function server (configureRoutes, port, hostname = null) {
//......
//里面有这样的代码
configureServer (app, configureRoutes) {
//然后再该函数中调用了
  configureRoutes(app);
}

所以代码走到这里执行的就是那个返回函数,app是express的实例!那么执行这一步是为了做什么呢?这个METHOD_MAP是最大的全路由配置!来自于mjsonwp/routes.js,其中500行都是路由配置,经过该配置有效避免批量写app.get()//balabala


function (app) {
  for (let [path, methods] of _.toPairs(METHOD_MAP)) {
  //balabalbala
 }

至此全路由配置装填结束!

服务启动

这个就没有什么波折了,既然server.js都找到了,就再这个文件中,看到这里终于看到了熟悉的node启动~

let app = express();
let httpServer = http.createServer(app);

当断点跟到这里时终端就可以跳出如下输出,服务启动啦~

[Appium] Appium REST http interface listener started on 0.0.0.0:4723

总结

启动服务执行过程
lib/main.js 执行来自于lib/appium.js中的getAppiumRouter函数
该函数中实例化AppiumDriver类,同时读取路由配置文件,该类继承于Appium-base-driver库中暴露的基类,路由配置文件来源于Appium-base-driver库中/mjsonwp/routes.js的配置
配置文件读取之后在/mjsonwp/mjsonwp.js中以函数的形式返回main.js 执行baseServer函数 该函数来自于Appium-base-driver/express/server.js

也就是说整个过程从

main.js-[调用]-appium.js-[调用]-appium-base-driver/mjsonwp-[返回]-main.js-[调用]-appium-base-driver/express

其实是通过层层调用将路由已配置的方式进行装填并在基础类库appium-base-server中启动

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342