├── .gitignore ├── README.MD ├── dumphrun ├── 20190521234042_intercept.log ├── __init__.py ├── casefactory.py ├── casetmp.py ├── filetools.py ├── hrun_case.json ├── hrun_case_back.json ├── proxyserver.py ├── reports │ ├── 1558442162.html │ ├── 1558442233.html │ ├── 1558448260.html │ ├── 1558448626.html │ ├── 1558448818.html │ ├── 1558449341.html │ ├── 1558449652.html │ ├── 1558449699.html │ ├── 1558449741.html │ ├── 1558451350.html │ ├── 1558451916.html │ ├── 1558452980.html │ └── 1558453682.html └── test.py ├── mitm.png ├── proxy.png ├── proxy ├── 20190521225436_intercept.log ├── __init__.py ├── backups.py ├── constant.py ├── filetools.py ├── genhtml.py ├── logger.py ├── mathrandom.py ├── parserjson.py ├── proxyrule.py ├── proxyserver.py ├── run.py ├── script.py └── templates │ └── template.html ├── run.sh ├── 报告1.jpg └── 报告2.jpg /.gitignore: -------------------------------------------------------------------------------- 1 | tutorial-env 2 | proxy/reports/* 3 | *.pyc 4 | .idea -------------------------------------------------------------------------------- /README.MD: -------------------------------------------------------------------------------- 1 | # 介绍 2 | 3 | 使用mitproxy代理工具做自动化Mock数据测试,来验证移动端app对数据的容错性. 4 | 5 | 6 | # 环境搭建 7 | 8 | ## 创建虚拟环境(python 3.7) 9 | ```angularjs 10 | python3.7 -m venv tutorial-env 11 | 12 | source tutorial-env/bin/activate (创建虚拟环境) 13 | 14 | deactivate (退出虚拟环境) 15 | ``` 16 | 17 | ## 安装依赖 18 | ```angular2html 19 | pip3 install mitmproxy 20 | 21 | pip3 install jsonpath-rw 22 | 23 | pip3 install colorama 24 | 25 | pip3 install colorlog 26 | ``` 27 | 28 | 29 | # 规则 30 | ``` 31 | 随机对请求数据做随机拦截篡改,支持事件如下: 32 | 1.随机对返回value做修改/删除 33 | 2.随机对返回list做删除 (可能会引起客户端崩溃,慎用) 34 | 3.随机对返回接口状态码修改 35 | 4.随机对返回接口时间做延迟修改 36 | ``` 37 | 38 | 39 | ## 使用 40 | 41 | ### 手机连接代理 42 | 移动设备和电脑保存在一个wifi网络下,在移动设备在网络代理填写电脑ip+8080(端口) 43 | 44 | ![image](proxy.png) 45 | 46 | ### mitproxy https证书安装 47 | ``` 48 | 在浏览器输入:mitm.it,选择Android证书下载并安装 49 | ``` 50 | ![image](mitm.png) 51 | 52 | 53 | ### 执行mock数据 54 | ```angularjs 55 | mitmdump -s proxyserver.py 56 | ``` 57 | 58 | ### 生成报告 59 | ```angularjs 60 | 参数1:需要保存的报告地址 61 | 参数2:保存到本地篡改数据地址 62 | python genhtml.py ~/PycharmProjects/mitmproxytest/proxy ~/PycharmProjects/mitmproxytest/proxy/20190521143711_intercept.log 63 | ``` 64 | 65 | # 展示 66 | 67 | ![image](报告1.jpg) 68 | 69 | ![image](报告2.jpg) 70 | 71 | 72 | # 参考 73 | mitmproxy的github
74 | https://github.com/mitmproxy/mitmproxy.git
-------------------------------------------------------------------------------- /dumphrun/20190521234042_intercept.log: -------------------------------------------------------------------------------- 1 | http://entree.dev.igetget.com/kaleidoscope/homepage/new_structure|POST|{'X-App-Key': 'android-6.2.0', 'X-Uid': '84846274', 'X-Thumb': 'l', 'X-Dt': 'phone', 'X-Ov': '6.0', 'X-Net': 'WIFI', 'X-Os': 'ANDROID', 'X-D': 'ae244834553d4eda', 'X-Dv': 'Samsung Galaxy S6', 'X-T': 'json', 'X-Chil': '0', 'X-V': '2', 'X-Av': '6.2.0', 'X-Scr': '2.0', 'X-Adv': '1', 'X-Seid': '8742eb6af715b8e2c9c726a42ce8b48c', 'X-Hitdot': '', 'G-Auth-Sign': 'NTMyYzc1YjVlMWUzOTFiNzU4NDRlNGEzNmRjMDJlN2Q=', 'G-Auth-Nonce': '2d4810c940f22e5ac8793de5bcf75ebf', 'G-Auth-Ts': '1558453246', 'G-Auth-Appid': '5a27d122ee4638163f594393', 'G-Auth-Token': 'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJsdW9qaWxhYi5jb20iLCJleHAiOjE1NTkwNTc4OTMsImlhdCI6MTU1ODQ1MzA5MywiaXNzIjoiRWFzZUdhdGV3YXkgSldUQXV0aCBQbHVnaW4iLCJuYmYiOjE1NTg0NTMwOTMsInN1YiI6Ijg0ODQ2Mjc0In0.bXQPMyrUyCZ5r6UvYXVpmENh9wXvunZA8ckdAPoHnVYyx4vxdqUyCke1NehM7IFiM5pW9ZfyTYO4BWrV9PTVmA', 'Content-Type': 'application/json; charset=UTF-8', 'Content-Length': '363', 'Host': 'entree.dev.igetget.com', 'Connection': 'Keep-Alive', 'Accept-Encoding': 'gzip', 'User-Agent': 'okhttp/3.11.0'}|{'page_type': '{ "page_type": "A", "list": [ ] }', 'h': {'u': '84846274', 'thumb': 'l', 'dt': 'phone', 'ov': '6.0', 'net': 'WIFI', 'os': 'ANDROID', 'd': 'ae244834553d4eda', 'dv': 'Samsung Galaxy S6', 't': 'json', 'chil': '0', 'v': '2', 'av': '6.2.0', 'scr': '2.0', 'adv': '1', 'X-Dv': 'Samsung Galaxy S6', 'ts': '1558453246', 's': 'db578eef9d289db9', 'seid': '8742eb6af715b8e2c9c726a42ce8b48c'}} 2 | http://dedao.dev.igetget.com/v3/adv/homepage?sign=2e53d78792ce6406510a5dca6db3d600|POST|{'Cache-Control': 'no-cache', 'Content-Type': 'application/json; charset=UTF-8', 'Content-Length': '309', 'Host': 'dedao.dev.igetget.com', 'Connection': 'Keep-Alive', 'Accept-Encoding': 'gzip', 'User-Agent': 'okhttp/3.11.0'}|{'h': {'u': '84846274', 'thumb': 'l', 'dt': 'phone', 'ov': '6.0', 'net': 'WIFI', 'os': 'ANDROID', 'd': 'ae244834553d4eda', 'dv': 'Samsung Galaxy S6', 't': 'json', 'chil': '0', 'v': '2', 'av': '6.2.0', 'scr': '2.0', 'adv': '1', 'X-Dv': 'Samsung Galaxy S6', 'ts': '1558453246', 's': 'db578eef9d289db9', 'seid': '8742eb6af715b8e2c9c726a42ce8b48c'}} 3 | http://dedao.dev.igetget.com/v3/igettv/structuredata?sign=847fae0f5aaba7f777b0f7fd3f05fc2f|POST|{'Cache-Control': 'no-cache', 'Content-Type': 'application/json; charset=UTF-8', 'Content-Length': '327', 'Host': 'dedao.dev.igetget.com', 'Connection': 'Keep-Alive', 'Accept-Encoding': 'gzip', 'User-Agent': 'okhttp/3.11.0'}|{'struct_id': 25490, 'h': {'u': '84846274', 'thumb': 'l', 'dt': 'phone', 'ov': '6.0', 'net': 'WIFI', 'os': 'ANDROID', 'd': 'ae244834553d4eda', 'dv': 'Samsung Galaxy S6', 't': 'json', 'chil': '0', 'v': '2', 'av': '6.2.0', 'scr': '2.0', 'adv': '1', 'X-Dv': 'Samsung Galaxy S6', 'ts': '1558453247', 's': 'db578eef9d289db9', 'seid': '8742eb6af715b8e2c9c726a42ce8b48c'}} 4 | http://dedao.dev.igetget.com/v3/hotfix/getHotFix?sign=56b1b5c590776d65881f2e31252a30e5|POST|{'Content-Type': 'application/x-www-form-urlencoded', 'User-Agent': 'Dalvik/2.1.0 (Linux; U; Android 6.0; Samsung Galaxy S6 Build/MRA58K)', 'Host': 'dedao.dev.igetget.com', 'Connection': 'Keep-Alive', 'Accept-Encoding': 'gzip', 'Content-Length': '324'}|{'h': {'u': '84846274', 's': 'db578eef9d289db9', 'os': 'ANDROID', 'av': '6.2.0', 'v': '2', 'd': 'ae244834553d4eda', 't': 'json', 'ts': '1558451044', 'thumb': 'l', 'dt': 'phone', 'ov': '6.0', 'net': 'WIFI', 'dv': 'Samsung Galaxy S6', 'chil': '0', 'scr': '0', 'seid': '22eb3b6b029be45d7cd5c7e00c14f3a4', 'adv': '1'}, 'type': 'android', 'version': '6.2.0.SNAPSHOT'} 5 | http://dedao.dev.igetget.com/v3/hotfix/getHotFix?sign=56b1b5c590776d65881f2e31252a30e5|POST|{'Content-Type': 'application/x-www-form-urlencoded', 'User-Agent': 'Dalvik/2.1.0 (Linux; U; Android 6.0; Samsung Galaxy S6 Build/MRA58K)', 'Host': 'dedao.dev.igetget.com', 'Connection': 'Keep-Alive', 'Accept-Encoding': 'gzip', 'Content-Length': '324'}|{'h': {'u': '84846274', 's': 'db578eef9d289db9', 'os': 'ANDROID', 'av': '6.2.0', 'v': '2', 'd': 'ae244834553d4eda', 't': 'json', 'ts': '1558451044', 'thumb': 'l', 'dt': 'phone', 'ov': '6.0', 'net': 'WIFI', 'dv': 'Samsung Galaxy S6', 'chil': '0', 'scr': '0', 'seid': '22eb3b6b029be45d7cd5c7e00c14f3a4', 'adv': '1'}, 'type': 'android', 'version': '6.2.0.SNAPSHOT'} 6 | http://dedao.dev.igetget.com/v3/user/recordtoken?sign=1bb033a2fcf15413fbac0b1648b0dc15|POST|{'Cache-Control': 'no-cache', 'Content-Type': 'application/json; charset=UTF-8', 'Content-Length': '457', 'Host': 'dedao.dev.igetget.com', 'Connection': 'Keep-Alive', 'Accept-Encoding': 'gzip', 'User-Agent': 'okhttp/3.11.0'}|{'h': {'u': '84846274', 'thumb': 'l', 'dt': 'phone', 'ov': '6.0', 'net': 'WIFI', 'os': 'ANDROID', 'd': 'ae244834553d4eda', 'dv': 'Samsung Galaxy S6', 't': 'json', 'chil': '0', 'v': '2', 'av': '6.2.0', 'scr': '0', 'adv': '1', 'X-Dv': 'Samsung Galaxy S6', 'ts': '1558453265', 's': 'db578eef9d289db9', 'seid': '22eb3b6b029be45d7cd5c7e00c14f3a4'}, 'rom': 'sys_name:unknow|sys_version:6.0', 'token': '3hDaKamogI8GYBfigOoy2mXCbM8syOMV4Se4l0uLl/+8G4XMLdJc98vMLrBwm4N/', 'type': 'XIAOMI', 'device': 'ANDROID'} 7 | http://dedao.dev.igetget.com/v3/appmanage/getnewversion?sign=b8f05b54e4a381b4b30966a44bfe6cf3|POST|{'Cache-Control': 'no-cache', 'Content-Type': 'application/json; charset=UTF-8', 'Content-Length': '382', 'Host': 'dedao.dev.igetget.com', 'Connection': 'Keep-Alive', 'Accept-Encoding': 'gzip', 'User-Agent': 'okhttp/3.11.0'}|{'type': 'ANDROID', 'os': '6.0', 'version': '6.2.0', 'token': 'ae244834553d4eda', 'h': {'u': '84846274', 'thumb': 'l', 'dt': 'phone', 'ov': '6.0', 'net': 'WIFI', 'os': 'ANDROID', 'd': 'ae244834553d4eda', 'dv': 'Samsung Galaxy S6', 't': 'json', 'chil': '0', 'v': '2', 'av': '6.2.0', 'scr': '2.0', 'adv': '1', 'X-Dv': 'Samsung Galaxy S6', 'ts': '1558453291', 's': 'db578eef9d289db9', 'seid': '22eb3b6b029be45d7cd5c7e00c14f3a4'}} 8 | http://entree.dev.igetget.com/kaleidoscope/v1/recommend/home|POST|{'X-App-Key': 'android-6.2.0', 'X-Uid': '84846274', 'X-Thumb': 'l', 'X-Dt': 'phone', 'X-Ov': '6.0', 'X-Net': 'WIFI', 'X-Os': 'ANDROID', 'X-D': 'ae244834553d4eda', 'X-Dv': 'Samsung Galaxy S6', 'X-T': 'json', 'X-Chil': '0', 'X-V': '2', 'X-Av': '6.2.0', 'X-Scr': '2.0', 'X-Adv': '1', 'X-Seid': '22eb3b6b029be45d7cd5c7e00c14f3a4', 'X-Hitdot': '', 'G-Auth-Sign': 'ZGIwOTFiOTU2ZWIxZTk3NjRiOWFiYTAxNWIzZmVkZjU=', 'G-Auth-Nonce': '2c8af9a057bb6bab32df3ed0f403da9d', 'G-Auth-Ts': '1558453353', 'G-Auth-Appid': '5a27d122ee4638163f594393', 'G-Auth-Token': 'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJsdW9qaWxhYi5jb20iLCJleHAiOjE1NTkwNTgwNjUsImlhdCI6MTU1ODQ1MzI2NSwiaXNzIjoiRWFzZUdhdGV3YXkgSldUQXV0aCBQbHVnaW4iLCJuYmYiOjE1NTg0NTMyNjUsInN1YiI6Ijg0ODQ2Mjc0In0.J_xlp1L4eCwiUfo8DVjKTRIcbNPIgtoUUJ2iDs3gB2EJDFo_qYcG8l1ZunlvXyYIpLMAEkA4ZyyxvtK1i6S-eQ', 'Content-Type': 'application/json; charset=UTF-8', 'Content-Length': '596', 'Host': 'entree.dev.igetget.com', 'Connection': 'Keep-Alive', 'Accept-Encoding': 'gzip', 'User-Agent': 'okhttp/3.11.0'}|{'page_id': 1, 'page_size': 20, 'is_login': 1, 'ext': [{'count': 0, 'data': {}, 'has_title': 2, 'page_type': 124, 'position': 4, 'struct_id': 25484, 'type': 'RecommendGoods'}, {'count': 0, 'data': {}, 'has_title': 2, 'page_type': 125, 'position': 5, 'struct_id': 25485, 'type': 'RecommendFeedBanner'}], 'is_label_select': 0, 'h': {'u': '84846274', 'thumb': 'l', 'dt': 'phone', 'ov': '6.0', 'net': 'WIFI', 'os': 'ANDROID', 'd': 'ae244834553d4eda', 'dv': 'Samsung Galaxy S6', 't': 'json', 'chil': '0', 'v': '2', 'av': '6.2.0', 'scr': '2.0', 'adv': '1', 'X-Dv': 'Samsung Galaxy S6', 'ts': '1558453352', 's': 'db578eef9d289db9', 'seid': '22eb3b6b029be45d7cd5c7e00c14f3a4'}} 9 | http://dedao.dev.igetget.com/v3/columnnote/userLineation?sign=94f892cd3dc6497130df52ea8f98748e|POST|{'Cache-Control': 'no-cache', 'Content-Type': 'application/json; charset=UTF-8', 'Content-Length': '369', 'Host': 'dedao.dev.igetget.com', 'Connection': 'Keep-Alive', 'Accept-Encoding': 'gzip', 'User-Agent': 'okhttp/3.11.0'}|{'aid': '1000047', 'type': 22, 'audio_id': 'kMXatYiKopG0DQVjWDee', 'h': {'u': '84846274', 'thumb': 'l', 'dt': 'phone', 'ov': '6.0', 'net': 'WIFI', 'os': 'ANDROID', 'd': 'ae244834553d4eda', 'dv': 'Samsung Galaxy S6', 't': 'json', 'chil': '0', 'v': '2', 'av': '6.2.0', 'scr': '2.0', 'adv': '1', 'X-Dv': 'Samsung Galaxy S6', 'ts': '1558453356', 's': 'db578eef9d289db9', 'seid': '22eb3b6b029be45d7cd5c7e00c14f3a4'}} 10 | http://dedao.dev.igetget.com/v3/columnnote/userLineation?sign=853000a7e9e2c804dd748fe4dc022952|POST|{'Cache-Control': 'no-cache', 'Content-Type': 'application/json; charset=UTF-8', 'Content-Length': '366', 'Host': 'dedao.dev.igetget.com', 'Connection': 'Keep-Alive', 'Accept-Encoding': 'gzip', 'User-Agent': 'okhttp/3.11.0'}|{'aid': '3809', 'type': 13, 'audio_id': 'vAkdmo4jroFNvu263tkH', 'h': {'u': '84846274', 'thumb': 'l', 'dt': 'phone', 'ov': '6.0', 'net': 'WIFI', 'os': 'ANDROID', 'd': 'ae244834553d4eda', 'dv': 'Samsung Galaxy S6', 't': 'json', 'chil': '0', 'v': '2', 'av': '6.2.0', 'scr': '2.0', 'adv': '1', 'X-Dv': 'Samsung Galaxy S6', 'ts': '1558453391', 's': 'db578eef9d289db9', 'seid': '22eb3b6b029be45d7cd5c7e00c14f3a4'}} 11 | http://entree.dev.igetget.com/centerproducer/v1/audio/actionpost|POST|{'X-App-Key': 'android-6.2.0', 'X-Uid': '84846274', 'X-Thumb': 'l', 'X-Dt': 'phone', 'X-Ov': '6.0', 'X-Net': 'WIFI', 'X-Os': 'ANDROID', 'X-D': 'ae244834553d4eda', 'X-Dv': 'Samsung Galaxy S6', 'X-T': 'json', 'X-Chil': '0', 'X-V': '2', 'X-Av': '6.2.0', 'X-Scr': '2.0', 'X-Adv': '1', 'X-Seid': '22eb3b6b029be45d7cd5c7e00c14f3a4', 'X-Hitdot': '', 'G-Auth-Sign': 'ODQ2YmZjOGIxMDk3Y2EwZDYwZjAxYmZhMjRjNWY3MTY=', 'G-Auth-Nonce': '10d49a960f18f4f1f444cacbc4b569cb', 'G-Auth-Ts': '1558453395', 'G-Auth-Appid': '5a27d122ee4638163f594393', 'G-Auth-Token': 'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJsdW9qaWxhYi5jb20iLCJleHAiOjE1NTkwNTgwNjUsImlhdCI6MTU1ODQ1MzI2NSwiaXNzIjoiRWFzZUdhdGV3YXkgSldUQXV0aCBQbHVnaW4iLCJuYmYiOjE1NTg0NTMyNjUsInN1YiI6Ijg0ODQ2Mjc0In0.J_xlp1L4eCwiUfo8DVjKTRIcbNPIgtoUUJ2iDs3gB2EJDFo_qYcG8l1ZunlvXyYIpLMAEkA4ZyyxvtK1i6S-eQ', 'Content-Type': 'application/json; charset=UTF-8', 'Content-Length': '449', 'Host': 'entree.dev.igetget.com', 'Connection': 'Keep-Alive', 'Accept-Encoding': 'gzip', 'User-Agent': 'okhttp/3.11.0'}|{'type': 'audio', 'data': [{'action': 'start', 'alias_id': 'vAkdmo4jroFNvu263tkH', 'progress': 0.0, 'time': 1558453395, 'type': 'audio', 'uid': 84846274}], 'h': {'u': '84846274', 'thumb': 'l', 'dt': 'phone', 'ov': '6.0', 'net': 'WIFI', 'os': 'ANDROID', 'd': 'ae244834553d4eda', 'dv': 'Samsung Galaxy S6', 't': 'json', 'chil': '0', 'v': '2', 'av': '6.2.0', 'scr': '2.0', 'adv': '1', 'X-Dv': 'Samsung Galaxy S6', 'ts': '1558453395', 's': 'db578eef9d289db9', 'seid': '22eb3b6b029be45d7cd5c7e00c14f3a4'}} 12 | http://dedao.dev.igetget.com/v3/shzf/homepage?sign=11d6a00a99d5e1431450679406b2d091|POST|{'Cache-Control': 'no-cache', 'Content-Type': 'application/json; charset=UTF-8', 'Content-Length': '327', 'Host': 'dedao.dev.igetget.com', 'Connection': 'Keep-Alive', 'Accept-Encoding': 'gzip', 'User-Agent': 'okhttp/3.11.0'}|{'struct_id': 25484, 'h': {'u': '84846274', 'thumb': 'l', 'dt': 'phone', 'ov': '6.0', 'net': 'WIFI', 'os': 'ANDROID', 'd': 'ae244834553d4eda', 'dv': 'Samsung Galaxy S6', 't': 'json', 'chil': '0', 'v': '2', 'av': '6.2.0', 'scr': '2.0', 'adv': '1', 'X-Dv': 'Samsung Galaxy S6', 'ts': '1558453409', 's': 'db578eef9d289db9', 'seid': '22eb3b6b029be45d7cd5c7e00c14f3a4'}} 13 | http://dedao.dev.igetget.com/v3/shzf/homepage?sign=c628931ca844332f17d8df896b3f8002|POST|{'Cache-Control': 'no-cache', 'Content-Type': 'application/json; charset=UTF-8', 'Content-Length': '327', 'Host': 'dedao.dev.igetget.com', 'Connection': 'Keep-Alive', 'Accept-Encoding': 'gzip', 'User-Agent': 'okhttp/3.11.0'}|{'struct_id': 25484, 'h': {'u': '84846274', 'thumb': 'l', 'dt': 'phone', 'ov': '6.0', 'net': 'WIFI', 'os': 'ANDROID', 'd': 'ae244834553d4eda', 'dv': 'Samsung Galaxy S6', 't': 'json', 'chil': '0', 'v': '2', 'av': '6.2.0', 'scr': '2.0', 'adv': '1', 'X-Dv': 'Samsung Galaxy S6', 'ts': '1558453410', 's': 'db578eef9d289db9', 'seid': '22eb3b6b029be45d7cd5c7e00c14f3a4'}} 14 | http://dedao.dev.igetget.com/v3/columnnote/userLineation?sign=a6af795ab0620fc235c0ead94c18c8fe|POST|{'Cache-Control': 'no-cache', 'Content-Type': 'application/json; charset=UTF-8', 'Content-Length': '366', 'Host': 'dedao.dev.igetget.com', 'Connection': 'Keep-Alive', 'Accept-Encoding': 'gzip', 'User-Agent': 'okhttp/3.11.0'}|{'aid': '3809', 'type': 13, 'audio_id': 'vAkdmo4jroFNvu263tkH', 'h': {'u': '84846274', 'thumb': 'l', 'dt': 'phone', 'ov': '6.0', 'net': 'WIFI', 'os': 'ANDROID', 'd': 'ae244834553d4eda', 'dv': 'Samsung Galaxy S6', 't': 'json', 'chil': '0', 'v': '2', 'av': '6.2.0', 'scr': '2.0', 'adv': '1', 'X-Dv': 'Samsung Galaxy S6', 'ts': '1558453417', 's': 'db578eef9d289db9', 'seid': '22eb3b6b029be45d7cd5c7e00c14f3a4'}} 15 | http://dedao.dev.igetget.com/v3/columnnote/userLineation?sign=b88f8e467b62a74c5b35514bef06fa94|POST|{'Cache-Control': 'no-cache', 'Content-Type': 'application/json; charset=UTF-8', 'Content-Length': '366', 'Host': 'dedao.dev.igetget.com', 'Connection': 'Keep-Alive', 'Accept-Encoding': 'gzip', 'User-Agent': 'okhttp/3.11.0'}|{'aid': '3809', 'type': 13, 'audio_id': 'vAkdmo4jroFNvu263tkH', 'h': {'u': '84846274', 'thumb': 'l', 'dt': 'phone', 'ov': '6.0', 'net': 'WIFI', 'os': 'ANDROID', 'd': 'ae244834553d4eda', 'dv': 'Samsung Galaxy S6', 't': 'json', 'chil': '0', 'v': '2', 'av': '6.2.0', 'scr': '2.0', 'adv': '1', 'X-Dv': 'Samsung Galaxy S6', 'ts': '1558453429', 's': 'db578eef9d289db9', 'seid': '22eb3b6b029be45d7cd5c7e00c14f3a4'}} 16 | http://entree.dev.igetget.com/centerproducer/v1/audio/actionpost|POST|{'X-App-Key': 'android-6.2.0', 'X-Uid': '84846274', 'X-Thumb': 'l', 'X-Dt': 'phone', 'X-Ov': '6.0', 'X-Net': 'WIFI', 'X-Os': 'ANDROID', 'X-D': 'ae244834553d4eda', 'X-Dv': 'Samsung Galaxy S6', 'X-T': 'json', 'X-Chil': '0', 'X-V': '2', 'X-Av': '6.2.0', 'X-Scr': '2.0', 'X-Adv': '1', 'X-Seid': '22eb3b6b029be45d7cd5c7e00c14f3a4', 'X-Hitdot': '', 'G-Auth-Sign': 'ZDgwM2QxMmJiNzA4M2ZmNDBkZWVmODBlNzE3OTY3NWE=', 'G-Auth-Nonce': '6e6b9cbe366f2d6db0a4e84982848200', 'G-Auth-Ts': '1558453434', 'G-Auth-Appid': '5a27d122ee4638163f594393', 'G-Auth-Token': 'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJsdW9qaWxhYi5jb20iLCJleHAiOjE1NTkwNTgwNjUsImlhdCI6MTU1ODQ1MzI2NSwiaXNzIjoiRWFzZUdhdGV3YXkgSldUQXV0aCBQbHVnaW4iLCJuYmYiOjE1NTg0NTMyNjUsInN1YiI6Ijg0ODQ2Mjc0In0.J_xlp1L4eCwiUfo8DVjKTRIcbNPIgtoUUJ2iDs3gB2EJDFo_qYcG8l1ZunlvXyYIpLMAEkA4ZyyxvtK1i6S-eQ', 'Content-Type': 'application/json; charset=UTF-8', 'Content-Length': '462', 'Host': 'entree.dev.igetget.com', 'Connection': 'Keep-Alive', 'Accept-Encoding': 'gzip', 'User-Agent': 'okhttp/3.11.0'}|{'type': 'audio', 'data': [{'action': 'pause', 'alias_id': 'vAkdmo4jroFNvu263tkH', 'progress': 2.34, 'reason': '', 'time': 1558453434, 'type': 'audio', 'uid': 84846274}], 'h': {'u': '84846274', 'thumb': 'l', 'dt': 'phone', 'ov': '6.0', 'net': 'WIFI', 'os': 'ANDROID', 'd': 'ae244834553d4eda', 'dv': 'Samsung Galaxy S6', 't': 'json', 'chil': '0', 'v': '2', 'av': '6.2.0', 'scr': '2.0', 'adv': '1', 'X-Dv': 'Samsung Galaxy S6', 'ts': '1558453434', 's': 'db578eef9d289db9', 'seid': '22eb3b6b029be45d7cd5c7e00c14f3a4'}} 17 | http://entree.dev.igetget.com/centerproducer/v1/audio/actionpost|POST|{'X-App-Key': 'android-6.2.0', 'X-Uid': '84846274', 'X-Thumb': 'l', 'X-Dt': 'phone', 'X-Ov': '6.0', 'X-Net': 'WIFI', 'X-Os': 'ANDROID', 'X-D': 'ae244834553d4eda', 'X-Dv': 'Samsung Galaxy S6', 'X-T': 'json', 'X-Chil': '0', 'X-V': '2', 'X-Av': '6.2.0', 'X-Scr': '2.0', 'X-Adv': '1', 'X-Seid': '22eb3b6b029be45d7cd5c7e00c14f3a4', 'X-Hitdot': '', 'G-Auth-Sign': 'MGJlMDZmMzg3NTg3NWMzMzJmNjBhNzhhYmMwNjc3OWI=', 'G-Auth-Nonce': '494bfc76adbb174c2b800d328671132b', 'G-Auth-Ts': '1558453434', 'G-Auth-Appid': '5a27d122ee4638163f594393', 'G-Auth-Token': 'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJsdW9qaWxhYi5jb20iLCJleHAiOjE1NTkwNTgwNjUsImlhdCI6MTU1ODQ1MzI2NSwiaXNzIjoiRWFzZUdhdGV3YXkgSldUQXV0aCBQbHVnaW4iLCJuYmYiOjE1NTg0NTMyNjUsInN1YiI6Ijg0ODQ2Mjc0In0.J_xlp1L4eCwiUfo8DVjKTRIcbNPIgtoUUJ2iDs3gB2EJDFo_qYcG8l1ZunlvXyYIpLMAEkA4ZyyxvtK1i6S-eQ', 'Content-Type': 'application/json; charset=UTF-8', 'Content-Length': '578', 'Host': 'entree.dev.igetget.com', 'Connection': 'Keep-Alive', 'Accept-Encoding': 'gzip', 'User-Agent': 'okhttp/3.11.0'}|{'type': 'audio', 'data': [{'action': 'pause', 'alias_id': 'vAkdmo4jroFNvu263tkH', 'progress': 2.34, 'reason': '', 'time': 1558453434, 'type': 'audio', 'uid': 84846274}, {'action': 'goon', 'alias_id': 'vAkdmo4jroFNvu263tkH', 'progress': 2.34, 'time': 1558453434, 'type': 'audio', 'uid': 84846274}], 'h': {'u': '84846274', 'thumb': 'l', 'dt': 'phone', 'ov': '6.0', 'net': 'WIFI', 'os': 'ANDROID', 'd': 'ae244834553d4eda', 'dv': 'Samsung Galaxy S6', 't': 'json', 'chil': '0', 'v': '2', 'av': '6.2.0', 'scr': '2.0', 'adv': '1', 'X-Dv': 'Samsung Galaxy S6', 'ts': '1558453434', 's': 'db578eef9d289db9', 'seid': '22eb3b6b029be45d7cd5c7e00c14f3a4'}} 18 | http://entree.dev.igetget.com/centerproducer/v1/audio/actionpost|POST|{'X-App-Key': 'android-6.2.0', 'X-Uid': '84846274', 'X-Thumb': 'l', 'X-Dt': 'phone', 'X-Ov': '6.0', 'X-Net': 'WIFI', 'X-Os': 'ANDROID', 'X-D': 'ae244834553d4eda', 'X-Dv': 'Samsung Galaxy S6', 'X-T': 'json', 'X-Chil': '0', 'X-V': '2', 'X-Av': '6.2.0', 'X-Scr': '2.0', 'X-Adv': '1', 'X-Seid': '22eb3b6b029be45d7cd5c7e00c14f3a4', 'X-Hitdot': '', 'G-Auth-Sign': 'NmZjYTUxNTFiYzkyM2NlZWY0MjUyODY0MGZmYTM5YzU=', 'G-Auth-Nonce': '09fa4a84cfe0e793db7c496f13d6c8e3', 'G-Auth-Ts': '1558453445', 'G-Auth-Appid': '5a27d122ee4638163f594393', 'G-Auth-Token': 'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJsdW9qaWxhYi5jb20iLCJleHAiOjE1NTkwNTgwNjUsImlhdCI6MTU1ODQ1MzI2NSwiaXNzIjoiRWFzZUdhdGV3YXkgSldUQXV0aCBQbHVnaW4iLCJuYmYiOjE1NTg0NTMyNjUsInN1YiI6Ijg0ODQ2Mjc0In0.J_xlp1L4eCwiUfo8DVjKTRIcbNPIgtoUUJ2iDs3gB2EJDFo_qYcG8l1ZunlvXyYIpLMAEkA4ZyyxvtK1i6S-eQ', 'Content-Type': 'application/json; charset=UTF-8', 'Content-Length': '462', 'Host': 'entree.dev.igetget.com', 'Connection': 'Keep-Alive', 'Accept-Encoding': 'gzip', 'User-Agent': 'okhttp/3.11.0'}|{'type': 'audio', 'data': [{'action': 'pause', 'alias_id': 'vAkdmo4jroFNvu263tkH', 'progress': 2.99, 'reason': '', 'time': 1558453445, 'type': 'audio', 'uid': 84846274}], 'h': {'u': '84846274', 'thumb': 'l', 'dt': 'phone', 'ov': '6.0', 'net': 'WIFI', 'os': 'ANDROID', 'd': 'ae244834553d4eda', 'dv': 'Samsung Galaxy S6', 't': 'json', 'chil': '0', 'v': '2', 'av': '6.2.0', 'scr': '2.0', 'adv': '1', 'X-Dv': 'Samsung Galaxy S6', 'ts': '1558453445', 's': 'db578eef9d289db9', 'seid': '22eb3b6b029be45d7cd5c7e00c14f3a4'}} 19 | http://entree.dev.igetget.com/centerproducer/v1/audio/actionpost|POST|{'X-App-Key': 'android-6.2.0', 'X-Uid': '84846274', 'X-Thumb': 'l', 'X-Dt': 'phone', 'X-Ov': '6.0', 'X-Net': 'WIFI', 'X-Os': 'ANDROID', 'X-D': 'ae244834553d4eda', 'X-Dv': 'Samsung Galaxy S6', 'X-T': 'json', 'X-Chil': '0', 'X-V': '2', 'X-Av': '6.2.0', 'X-Scr': '2.0', 'X-Adv': '1', 'X-Seid': '22eb3b6b029be45d7cd5c7e00c14f3a4', 'X-Hitdot': '', 'G-Auth-Sign': 'NGY0OTcyMjAxYjk3OGEwYThmZGQ0YTJjMTY0NWE4OGY=', 'G-Auth-Nonce': 'f5ee4f5fc26b980cc37767f777621d64', 'G-Auth-Ts': '1558453446', 'G-Auth-Appid': '5a27d122ee4638163f594393', 'G-Auth-Token': 'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJsdW9qaWxhYi5jb20iLCJleHAiOjE1NTkwNTgwNjUsImlhdCI6MTU1ODQ1MzI2NSwiaXNzIjoiRWFzZUdhdGV3YXkgSldUQXV0aCBQbHVnaW4iLCJuYmYiOjE1NTg0NTMyNjUsInN1YiI6Ijg0ODQ2Mjc0In0.J_xlp1L4eCwiUfo8DVjKTRIcbNPIgtoUUJ2iDs3gB2EJDFo_qYcG8l1ZunlvXyYIpLMAEkA4ZyyxvtK1i6S-eQ', 'Content-Type': 'application/json; charset=UTF-8', 'Content-Length': '462', 'Host': 'entree.dev.igetget.com', 'Connection': 'Keep-Alive', 'Accept-Encoding': 'gzip', 'User-Agent': 'okhttp/3.11.0'}|{'type': 'audio', 'data': [{'action': 'pause', 'alias_id': 'vAkdmo4jroFNvu263tkH', 'progress': 2.99, 'reason': '', 'time': 1558453446, 'type': 'audio', 'uid': 84846274}], 'h': {'u': '84846274', 'thumb': 'l', 'dt': 'phone', 'ov': '6.0', 'net': 'WIFI', 'os': 'ANDROID', 'd': 'ae244834553d4eda', 'dv': 'Samsung Galaxy S6', 't': 'json', 'chil': '0', 'v': '2', 'av': '6.2.0', 'scr': '2.0', 'adv': '1', 'X-Dv': 'Samsung Galaxy S6', 'ts': '1558453446', 's': 'db578eef9d289db9', 'seid': '22eb3b6b029be45d7cd5c7e00c14f3a4'}} 20 | http://entree.dev.igetget.com/centerproducer/v1/audio/actionpost|POST|{'X-App-Key': 'android-6.2.0', 'X-Uid': '84846274', 'X-Thumb': 'l', 'X-Dt': 'phone', 'X-Ov': '6.0', 'X-Net': 'WIFI', 'X-Os': 'ANDROID', 'X-D': 'ae244834553d4eda', 'X-Dv': 'Samsung Galaxy S6', 'X-T': 'json', 'X-Chil': '0', 'X-V': '2', 'X-Av': '6.2.0', 'X-Scr': '2.0', 'X-Adv': '1', 'X-Seid': '22eb3b6b029be45d7cd5c7e00c14f3a4', 'X-Hitdot': '', 'G-Auth-Sign': 'YjhjNTJkYmExNTMyODhjYjhhZTcxOGU0MTA1NmU3NzM=', 'G-Auth-Nonce': '411b57892b891b6548d71851700ffbc1', 'G-Auth-Ts': '1558453447', 'G-Auth-Appid': '5a27d122ee4638163f594393', 'G-Auth-Token': 'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJsdW9qaWxhYi5jb20iLCJleHAiOjE1NTkwNTgwNjUsImlhdCI6MTU1ODQ1MzI2NSwiaXNzIjoiRWFzZUdhdGV3YXkgSldUQXV0aCBQbHVnaW4iLCJuYmYiOjE1NTg0NTMyNjUsInN1YiI6Ijg0ODQ2Mjc0In0.J_xlp1L4eCwiUfo8DVjKTRIcbNPIgtoUUJ2iDs3gB2EJDFo_qYcG8l1ZunlvXyYIpLMAEkA4ZyyxvtK1i6S-eQ', 'Content-Type': 'application/json; charset=UTF-8', 'Content-Length': '449', 'Host': 'entree.dev.igetget.com', 'Connection': 'Keep-Alive', 'Accept-Encoding': 'gzip', 'User-Agent': 'okhttp/3.11.0'}|{'type': 'audio', 'data': [{'action': 'goon', 'alias_id': 'vAkdmo4jroFNvu263tkH', 'progress': 2.99, 'time': 1558453446, 'type': 'audio', 'uid': 84846274}], 'h': {'u': '84846274', 'thumb': 'l', 'dt': 'phone', 'ov': '6.0', 'net': 'WIFI', 'os': 'ANDROID', 'd': 'ae244834553d4eda', 'dv': 'Samsung Galaxy S6', 't': 'json', 'chil': '0', 'v': '2', 'av': '6.2.0', 'scr': '2.0', 'adv': '1', 'X-Dv': 'Samsung Galaxy S6', 'ts': '1558453446', 's': 'db578eef9d289db9', 'seid': '22eb3b6b029be45d7cd5c7e00c14f3a4'}} 21 | http://entree.dev.igetget.com/centerproducer/v1/audio/actionpost|POST|{'X-App-Key': 'android-6.2.0', 'X-Uid': '84846274', 'X-Thumb': 'l', 'X-Dt': 'phone', 'X-Ov': '6.0', 'X-Net': 'WIFI', 'X-Os': 'ANDROID', 'X-D': 'ae244834553d4eda', 'X-Dv': 'Samsung Galaxy S6', 'X-T': 'json', 'X-Chil': '0', 'X-V': '2', 'X-Av': '6.2.0', 'X-Scr': '2.0', 'X-Adv': '1', 'X-Seid': '22eb3b6b029be45d7cd5c7e00c14f3a4', 'X-Hitdot': '', 'G-Auth-Sign': 'MjljYzgzY2ZkODZlMDZiMmJkZjM0ZTFkMjkyZjYzZjM=', 'G-Auth-Nonce': 'd43fc3b8f646308233b7fc36eb0cdb10', 'G-Auth-Ts': '1558453452', 'G-Auth-Appid': '5a27d122ee4638163f594393', 'G-Auth-Token': 'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJsdW9qaWxhYi5jb20iLCJleHAiOjE1NTkwNTgwNjUsImlhdCI6MTU1ODQ1MzI2NSwiaXNzIjoiRWFzZUdhdGV3YXkgSldUQXV0aCBQbHVnaW4iLCJuYmYiOjE1NTg0NTMyNjUsInN1YiI6Ijg0ODQ2Mjc0In0.J_xlp1L4eCwiUfo8DVjKTRIcbNPIgtoUUJ2iDs3gB2EJDFo_qYcG8l1ZunlvXyYIpLMAEkA4ZyyxvtK1i6S-eQ', 'Content-Type': 'application/json; charset=UTF-8', 'Content-Length': '462', 'Host': 'entree.dev.igetget.com', 'Connection': 'Keep-Alive', 'Accept-Encoding': 'gzip', 'User-Agent': 'okhttp/3.11.0'}|{'type': 'audio', 'data': [{'action': 'pause', 'alias_id': 'vAkdmo4jroFNvu263tkH', 'progress': 3.18, 'reason': '', 'time': 1558453451, 'type': 'audio', 'uid': 84846274}], 'h': {'u': '84846274', 'thumb': 'l', 'dt': 'phone', 'ov': '6.0', 'net': 'WIFI', 'os': 'ANDROID', 'd': 'ae244834553d4eda', 'dv': 'Samsung Galaxy S6', 't': 'json', 'chil': '0', 'v': '2', 'av': '6.2.0', 'scr': '2.0', 'adv': '1', 'X-Dv': 'Samsung Galaxy S6', 'ts': '1558453451', 's': 'db578eef9d289db9', 'seid': '22eb3b6b029be45d7cd5c7e00c14f3a4'}} 22 | http://dedao.dev.igetget.com/v3/columnnote/userLineation?sign=e25310c6b941fccc86298c34234cbc1d|POST|{'Cache-Control': 'no-cache', 'Content-Type': 'application/json; charset=UTF-8', 'Content-Length': '366', 'Host': 'dedao.dev.igetget.com', 'Connection': 'Keep-Alive', 'Accept-Encoding': 'gzip', 'User-Agent': 'okhttp/3.11.0'}|{'aid': '3809', 'type': 13, 'audio_id': 'vAkdmo4jroFNvu263tkH', 'h': {'u': '84846274', 'thumb': 'l', 'dt': 'phone', 'ov': '6.0', 'net': 'WIFI', 'os': 'ANDROID', 'd': 'ae244834553d4eda', 'dv': 'Samsung Galaxy S6', 't': 'json', 'chil': '0', 'v': '2', 'av': '6.2.0', 'scr': '2.0', 'adv': '1', 'X-Dv': 'Samsung Galaxy S6', 'ts': '1558453459', 's': 'db578eef9d289db9', 'seid': '22eb3b6b029be45d7cd5c7e00c14f3a4'}} 23 | http://entree.dev.igetget.com/centerproducer/v1/audio/actionpost|POST|{'X-App-Key': 'android-6.2.0', 'X-Uid': '84846274', 'X-Thumb': 'l', 'X-Dt': 'phone', 'X-Ov': '6.0', 'X-Net': 'WIFI', 'X-Os': 'ANDROID', 'X-D': 'ae244834553d4eda', 'X-Dv': 'Samsung Galaxy S6', 'X-T': 'json', 'X-Chil': '0', 'X-V': '2', 'X-Av': '6.2.0', 'X-Scr': '2.0', 'X-Adv': '1', 'X-Seid': '22eb3b6b029be45d7cd5c7e00c14f3a4', 'X-Hitdot': '', 'G-Auth-Sign': 'MjQxNTM0MDJmM2FlM2U3ZjY3MjFiZjQ1MDM3YjJjYzA=', 'G-Auth-Nonce': 'fb7739bc960d6ac933b03e088abc8033', 'G-Auth-Ts': '1558453477', 'G-Auth-Appid': '5a27d122ee4638163f594393', 'G-Auth-Token': 'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJsdW9qaWxhYi5jb20iLCJleHAiOjE1NTkwNTgwNjUsImlhdCI6MTU1ODQ1MzI2NSwiaXNzIjoiRWFzZUdhdGV3YXkgSldUQXV0aCBQbHVnaW4iLCJuYmYiOjE1NTg0NTMyNjUsInN1YiI6Ijg0ODQ2Mjc0In0.J_xlp1L4eCwiUfo8DVjKTRIcbNPIgtoUUJ2iDs3gB2EJDFo_qYcG8l1ZunlvXyYIpLMAEkA4ZyyxvtK1i6S-eQ', 'Content-Type': 'application/json; charset=UTF-8', 'Content-Length': '451', 'Host': 'entree.dev.igetget.com', 'Connection': 'Keep-Alive', 'Accept-Encoding': 'gzip', 'User-Agent': 'okhttp/3.11.0'}|{'type': 'audio', 'data': [{'action': 'resume', 'alias_id': 'vAkdmo4jroFNvu263tkH', 'progress': 3.18, 'time': 1558453477, 'type': 'audio', 'uid': 84846274}], 'h': {'u': '84846274', 'thumb': 'l', 'dt': 'phone', 'ov': '6.0', 'net': 'WIFI', 'os': 'ANDROID', 'd': 'ae244834553d4eda', 'dv': 'Samsung Galaxy S6', 't': 'json', 'chil': '0', 'v': '2', 'av': '6.2.0', 'scr': '2.0', 'adv': '1', 'X-Dv': 'Samsung Galaxy S6', 'ts': '1558453477', 's': 'db578eef9d289db9', 'seid': '22eb3b6b029be45d7cd5c7e00c14f3a4'}} 24 | http://entree.dev.igetget.com/odob/v2/audio/detail|POST|{'X-App-Key': 'android-6.2.0', 'X-Uid': '84846274', 'X-Thumb': 'l', 'X-Dt': 'phone', 'X-Ov': '6.0', 'X-Net': 'WIFI', 'X-Os': 'ANDROID', 'X-D': 'ae244834553d4eda', 'X-Dv': 'Samsung Galaxy S6', 'X-T': 'json', 'X-Chil': '0', 'X-V': '2', 'X-Av': '6.2.0', 'X-Scr': '2.0', 'X-Adv': '1', 'X-Seid': '22eb3b6b029be45d7cd5c7e00c14f3a4', 'X-Hitdot': '', 'G-Auth-Sign': 'MTI0NjU0MGRmZjJjMmY3YzhlNWMwMmE2OTZkNzkyNjA=', 'G-Auth-Nonce': '81eba977ec71d2da6ace6fa4b200d34a', 'G-Auth-Ts': '1558453497', 'G-Auth-Appid': '5a27d122ee4638163f594393', 'G-Auth-Token': 'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJsdW9qaWxhYi5jb20iLCJleHAiOjE1NTkwNTgwNjUsImlhdCI6MTU1ODQ1MzI2NSwiaXNzIjoiRWFzZUdhdGV3YXkgSldUQXV0aCBQbHVnaW4iLCJuYmYiOjE1NTg0NTMyNjUsInN1YiI6Ijg0ODQ2Mjc0In0.J_xlp1L4eCwiUfo8DVjKTRIcbNPIgtoUUJ2iDs3gB2EJDFo_qYcG8l1ZunlvXyYIpLMAEkA4ZyyxvtK1i6S-eQ', 'Content-Type': 'application/json; charset=UTF-8', 'Content-Length': '325', 'Host': 'entree.dev.igetget.com', 'Connection': 'Keep-Alive', 'Accept-Encoding': 'gzip', 'User-Agent': 'okhttp/3.11.0'}|{'topic_id': 3809, 'h': {'u': '84846274', 'thumb': 'l', 'dt': 'phone', 'ov': '6.0', 'net': 'WIFI', 'os': 'ANDROID', 'd': 'ae244834553d4eda', 'dv': 'Samsung Galaxy S6', 't': 'json', 'chil': '0', 'v': '2', 'av': '6.2.0', 'scr': '2.0', 'adv': '1', 'X-Dv': 'Samsung Galaxy S6', 'ts': '1558453497', 's': 'db578eef9d289db9', 'seid': '22eb3b6b029be45d7cd5c7e00c14f3a4'}} 25 | http://entree.dev.igetget.com/centerproducer/v1/audio/actionpost|POST|{'X-App-Key': 'android-6.2.0', 'X-Uid': '84846274', 'X-Thumb': 'l', 'X-Dt': 'phone', 'X-Ov': '6.0', 'X-Net': 'WIFI', 'X-Os': 'ANDROID', 'X-D': 'ae244834553d4eda', 'X-Dv': 'Samsung Galaxy S6', 'X-T': 'json', 'X-Chil': '0', 'X-V': '2', 'X-Av': '6.2.0', 'X-Scr': '2.0', 'X-Adv': '1', 'X-Seid': '22eb3b6b029be45d7cd5c7e00c14f3a4', 'X-Hitdot': '', 'G-Auth-Sign': 'MzA5YjhmZTUxNWNiZmNmOWIxNDYyOWFmMDk5NzJiYjY=', 'G-Auth-Nonce': 'ab15de0e7422d050a6d572ab967660e7', 'G-Auth-Ts': '1558453498', 'G-Auth-Appid': '5a27d122ee4638163f594393', 'G-Auth-Token': 'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJsdW9qaWxhYi5jb20iLCJleHAiOjE1NTkwNTgwNjUsImlhdCI6MTU1ODQ1MzI2NSwiaXNzIjoiRWFzZUdhdGV3YXkgSldUQXV0aCBQbHVnaW4iLCJuYmYiOjE1NTg0NTMyNjUsInN1YiI6Ijg0ODQ2Mjc0In0.J_xlp1L4eCwiUfo8DVjKTRIcbNPIgtoUUJ2iDs3gB2EJDFo_qYcG8l1ZunlvXyYIpLMAEkA4ZyyxvtK1i6S-eQ', 'Content-Type': 'application/json; charset=UTF-8', 'Content-Length': '480', 'Host': 'entree.dev.igetget.com', 'Connection': 'Keep-Alive', 'Accept-Encoding': 'gzip', 'User-Agent': 'okhttp/3.11.0'}|{'type': 'audio', 'data': [{'action': 'pause', 'alias_id': 'vAkdmo4jroFNvu263tkH', 'progress': 4.55, 'reason': 'MediaSession-pause', 'time': 1558453497, 'type': 'audio', 'uid': 84846274}], 'h': {'u': '84846274', 'thumb': 'l', 'dt': 'phone', 'ov': '6.0', 'net': 'WIFI', 'os': 'ANDROID', 'd': 'ae244834553d4eda', 'dv': 'Samsung Galaxy S6', 't': 'json', 'chil': '0', 'v': '2', 'av': '6.2.0', 'scr': '2.0', 'adv': '1', 'X-Dv': 'Samsung Galaxy S6', 'ts': '1558453497', 's': 'db578eef9d289db9', 'seid': '22eb3b6b029be45d7cd5c7e00c14f3a4'}} 26 | http://entree.dev.igetget.com/centerproducer/v1/audio/actionpost|POST|{'X-App-Key': 'android-6.2.0', 'X-Uid': '84846274', 'X-Thumb': 'l', 'X-Dt': 'phone', 'X-Ov': '6.0', 'X-Net': 'WIFI', 'X-Os': 'ANDROID', 'X-D': 'ae244834553d4eda', 'X-Dv': 'Samsung Galaxy S6', 'X-T': 'json', 'X-Chil': '0', 'X-V': '2', 'X-Av': '6.2.0', 'X-Scr': '2.0', 'X-Adv': '1', 'X-Seid': '22eb3b6b029be45d7cd5c7e00c14f3a4', 'X-Hitdot': '', 'G-Auth-Sign': 'YmZlZjU2M2FjNmJhNGI1OTdmNjNmNGQwZmY1ZjM5NzQ=', 'G-Auth-Nonce': '9b38283bfcd93249632ff9b56f10e180', 'G-Auth-Ts': '1558453498', 'G-Auth-Appid': '5a27d122ee4638163f594393', 'G-Auth-Token': 'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJsdW9qaWxhYi5jb20iLCJleHAiOjE1NTkwNTgwNjUsImlhdCI6MTU1ODQ1MzI2NSwiaXNzIjoiRWFzZUdhdGV3YXkgSldUQXV0aCBQbHVnaW4iLCJuYmYiOjE1NTg0NTMyNjUsInN1YiI6Ijg0ODQ2Mjc0In0.J_xlp1L4eCwiUfo8DVjKTRIcbNPIgtoUUJ2iDs3gB2EJDFo_qYcG8l1ZunlvXyYIpLMAEkA4ZyyxvtK1i6S-eQ', 'Content-Type': 'application/json; charset=UTF-8', 'Content-Length': '449', 'Host': 'entree.dev.igetget.com', 'Connection': 'Keep-Alive', 'Accept-Encoding': 'gzip', 'User-Agent': 'okhttp/3.11.0'}|{'type': 'audio', 'data': [{'action': 'goon', 'alias_id': 'vAkdmo4jroFNvu263tkH', 'progress': 4.48, 'time': 1558453498, 'type': 'audio', 'uid': 84846274}], 'h': {'u': '84846274', 'thumb': 'l', 'dt': 'phone', 'ov': '6.0', 'net': 'WIFI', 'os': 'ANDROID', 'd': 'ae244834553d4eda', 'dv': 'Samsung Galaxy S6', 't': 'json', 'chil': '0', 'v': '2', 'av': '6.2.0', 'scr': '2.0', 'adv': '1', 'X-Dv': 'Samsung Galaxy S6', 'ts': '1558453498', 's': 'db578eef9d289db9', 'seid': '22eb3b6b029be45d7cd5c7e00c14f3a4'}} 27 | http://entree.dev.igetget.com/centerproducer/v1/audio/actionpost|POST|{'X-App-Key': 'android-6.2.0', 'X-Uid': '84846274', 'X-Thumb': 'l', 'X-Dt': 'phone', 'X-Ov': '6.0', 'X-Net': 'WIFI', 'X-Os': 'ANDROID', 'X-D': 'ae244834553d4eda', 'X-Dv': 'Samsung Galaxy S6', 'X-T': 'json', 'X-Chil': '0', 'X-V': '2', 'X-Av': '6.2.0', 'X-Scr': '2.0', 'X-Adv': '1', 'X-Seid': '22eb3b6b029be45d7cd5c7e00c14f3a4', 'X-Hitdot': '', 'G-Auth-Sign': 'NDJiMWYyODYwY2NhNTRlNWU3MDRjYTRlODIyMDkwMTU=', 'G-Auth-Nonce': '863d94df3c3ecaa4ee00ead46c34b35f', 'G-Auth-Ts': '1558453523', 'G-Auth-Appid': '5a27d122ee4638163f594393', 'G-Auth-Token': 'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJsdW9qaWxhYi5jb20iLCJleHAiOjE1NTkwNTgwNjUsImlhdCI6MTU1ODQ1MzI2NSwiaXNzIjoiRWFzZUdhdGV3YXkgSldUQXV0aCBQbHVnaW4iLCJuYmYiOjE1NTg0NTMyNjUsInN1YiI6Ijg0ODQ2Mjc0In0.J_xlp1L4eCwiUfo8DVjKTRIcbNPIgtoUUJ2iDs3gB2EJDFo_qYcG8l1ZunlvXyYIpLMAEkA4ZyyxvtK1i6S-eQ', 'Content-Type': 'application/json; charset=UTF-8', 'Content-Length': '462', 'Host': 'entree.dev.igetget.com', 'Connection': 'Keep-Alive', 'Accept-Encoding': 'gzip', 'User-Agent': 'okhttp/3.11.0'}|{'type': 'audio', 'data': [{'action': 'pause', 'alias_id': 'vAkdmo4jroFNvu263tkH', 'progress': 5.98, 'reason': '', 'time': 1558453523, 'type': 'audio', 'uid': 84846274}], 'h': {'u': '84846274', 'thumb': 'l', 'dt': 'phone', 'ov': '6.0', 'net': 'WIFI', 'os': 'ANDROID', 'd': 'ae244834553d4eda', 'dv': 'Samsung Galaxy S6', 't': 'json', 'chil': '0', 'v': '2', 'av': '6.2.0', 'scr': '2.0', 'adv': '1', 'X-Dv': 'Samsung Galaxy S6', 'ts': '1558453523', 's': 'db578eef9d289db9', 'seid': '22eb3b6b029be45d7cd5c7e00c14f3a4'}} 28 | http://entree.dev.igetget.com/centerproducer/v1/audio/actionpost|POST|{'X-App-Key': 'android-6.2.0', 'X-Uid': '84846274', 'X-Thumb': 'l', 'X-Dt': 'phone', 'X-Ov': '6.0', 'X-Net': 'WIFI', 'X-Os': 'ANDROID', 'X-D': 'ae244834553d4eda', 'X-Dv': 'Samsung Galaxy S6', 'X-T': 'json', 'X-Chil': '0', 'X-V': '2', 'X-Av': '6.2.0', 'X-Scr': '2.0', 'X-Adv': '1', 'X-Seid': '22eb3b6b029be45d7cd5c7e00c14f3a4', 'X-Hitdot': '', 'G-Auth-Sign': 'MDlmNjAxNTRmOTNhYjViODA5NWYwNDVlOTRhZmRlM2Y=', 'G-Auth-Nonce': '5ee3147409383c03108874c5ceb3a2fa', 'G-Auth-Ts': '1558453542', 'G-Auth-Appid': '5a27d122ee4638163f594393', 'G-Auth-Token': 'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJsdW9qaWxhYi5jb20iLCJleHAiOjE1NTkwNTgwNjUsImlhdCI6MTU1ODQ1MzI2NSwiaXNzIjoiRWFzZUdhdGV3YXkgSldUQXV0aCBQbHVnaW4iLCJuYmYiOjE1NTg0NTMyNjUsInN1YiI6Ijg0ODQ2Mjc0In0.J_xlp1L4eCwiUfo8DVjKTRIcbNPIgtoUUJ2iDs3gB2EJDFo_qYcG8l1ZunlvXyYIpLMAEkA4ZyyxvtK1i6S-eQ', 'Content-Type': 'application/json; charset=UTF-8', 'Content-Length': '451', 'Host': 'entree.dev.igetget.com', 'Connection': 'Keep-Alive', 'Accept-Encoding': 'gzip', 'User-Agent': 'okhttp/3.11.0'}|{'type': 'audio', 'data': [{'action': 'resume', 'alias_id': 'vAkdmo4jroFNvu263tkH', 'progress': 5.98, 'time': 1558453542, 'type': 'audio', 'uid': 84846274}], 'h': {'u': '84846274', 'thumb': 'l', 'dt': 'phone', 'ov': '6.0', 'net': 'WIFI', 'os': 'ANDROID', 'd': 'ae244834553d4eda', 'dv': 'Samsung Galaxy S6', 't': 'json', 'chil': '0', 'v': '2', 'av': '6.2.0', 'scr': '2.0', 'adv': '1', 'X-Dv': 'Samsung Galaxy S6', 'ts': '1558453542', 's': 'db578eef9d289db9', 'seid': '22eb3b6b029be45d7cd5c7e00c14f3a4'}} 29 | http://entree.dev.igetget.com/odob/v2/audio/detail|POST|{'X-App-Key': 'android-6.2.0', 'X-Uid': '84846274', 'X-Thumb': 'l', 'X-Dt': 'phone', 'X-Ov': '6.0', 'X-Net': 'WIFI', 'X-Os': 'ANDROID', 'X-D': 'ae244834553d4eda', 'X-Dv': 'Samsung Galaxy S6', 'X-T': 'json', 'X-Chil': '0', 'X-V': '2', 'X-Av': '6.2.0', 'X-Scr': '2.0', 'X-Adv': '1', 'X-Seid': '22eb3b6b029be45d7cd5c7e00c14f3a4', 'X-Hitdot': '', 'G-Auth-Sign': 'MDgyMmQ2MDAzNGVkZThhMjk2YmM0ZGUxZTJkODk5OGI=', 'G-Auth-Nonce': 'b08f1224e1ca49fec5bde0fa4dbd50ef', 'G-Auth-Ts': '1558453549', 'G-Auth-Appid': '5a27d122ee4638163f594393', 'G-Auth-Token': 'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJsdW9qaWxhYi5jb20iLCJleHAiOjE1NTkwNTgwNjUsImlhdCI6MTU1ODQ1MzI2NSwiaXNzIjoiRWFzZUdhdGV3YXkgSldUQXV0aCBQbHVnaW4iLCJuYmYiOjE1NTg0NTMyNjUsInN1YiI6Ijg0ODQ2Mjc0In0.J_xlp1L4eCwiUfo8DVjKTRIcbNPIgtoUUJ2iDs3gB2EJDFo_qYcG8l1ZunlvXyYIpLMAEkA4ZyyxvtK1i6S-eQ', 'Content-Type': 'application/json; charset=UTF-8', 'Content-Length': '325', 'Host': 'entree.dev.igetget.com', 'Connection': 'Keep-Alive', 'Accept-Encoding': 'gzip', 'User-Agent': 'okhttp/3.11.0'}|{'topic_id': 3809, 'h': {'u': '84846274', 'thumb': 'l', 'dt': 'phone', 'ov': '6.0', 'net': 'WIFI', 'os': 'ANDROID', 'd': 'ae244834553d4eda', 'dv': 'Samsung Galaxy S6', 't': 'json', 'chil': '0', 'v': '2', 'av': '6.2.0', 'scr': '2.0', 'adv': '1', 'X-Dv': 'Samsung Galaxy S6', 'ts': '1558453549', 's': 'db578eef9d289db9', 'seid': '22eb3b6b029be45d7cd5c7e00c14f3a4'}} 30 | http://entree.dev.igetget.com/centerproducer/v1/audio/actionpost|POST|{'X-App-Key': 'android-6.2.0', 'X-Uid': '84846274', 'X-Thumb': 'l', 'X-Dt': 'phone', 'X-Ov': '6.0', 'X-Net': 'WIFI', 'X-Os': 'ANDROID', 'X-D': 'ae244834553d4eda', 'X-Dv': 'Samsung Galaxy S6', 'X-T': 'json', 'X-Chil': '0', 'X-V': '2', 'X-Av': '6.2.0', 'X-Scr': '2.0', 'X-Adv': '1', 'X-Seid': '22eb3b6b029be45d7cd5c7e00c14f3a4', 'X-Hitdot': '', 'G-Auth-Sign': 'MDU1N2U2OWY2ZDQyNTdiOTk4ZDg4ZDU2NWMwNjg5ZDQ=', 'G-Auth-Nonce': '321edb94f45dcc52d73949c64ef25244', 'G-Auth-Ts': '1558453550', 'G-Auth-Appid': '5a27d122ee4638163f594393', 'G-Auth-Token': 'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJsdW9qaWxhYi5jb20iLCJleHAiOjE1NTkwNTgwNjUsImlhdCI6MTU1ODQ1MzI2NSwiaXNzIjoiRWFzZUdhdGV3YXkgSldUQXV0aCBQbHVnaW4iLCJuYmYiOjE1NTg0NTMyNjUsInN1YiI6Ijg0ODQ2Mjc0In0.J_xlp1L4eCwiUfo8DVjKTRIcbNPIgtoUUJ2iDs3gB2EJDFo_qYcG8l1ZunlvXyYIpLMAEkA4ZyyxvtK1i6S-eQ', 'Content-Type': 'application/json; charset=UTF-8', 'Content-Length': '461', 'Host': 'entree.dev.igetget.com', 'Connection': 'Keep-Alive', 'Accept-Encoding': 'gzip', 'User-Agent': 'okhttp/3.11.0'}|{'type': 'audio', 'data': [{'action': 'pause', 'alias_id': 'vAkdmo4jroFNvu263tkH', 'progress': 6.5, 'reason': '', 'time': 1558453550, 'type': 'audio', 'uid': 84846274}], 'h': {'u': '84846274', 'thumb': 'l', 'dt': 'phone', 'ov': '6.0', 'net': 'WIFI', 'os': 'ANDROID', 'd': 'ae244834553d4eda', 'dv': 'Samsung Galaxy S6', 't': 'json', 'chil': '0', 'v': '2', 'av': '6.2.0', 'scr': '2.0', 'adv': '1', 'X-Dv': 'Samsung Galaxy S6', 'ts': '1558453550', 's': 'db578eef9d289db9', 'seid': '22eb3b6b029be45d7cd5c7e00c14f3a4'}} 31 | http://entree.dev.igetget.com/centerproducer/v1/audio/actionpost|POST|{'X-App-Key': 'android-6.2.0', 'X-Uid': '84846274', 'X-Thumb': 'l', 'X-Dt': 'phone', 'X-Ov': '6.0', 'X-Net': 'WIFI', 'X-Os': 'ANDROID', 'X-D': 'ae244834553d4eda', 'X-Dv': 'Samsung Galaxy S6', 'X-T': 'json', 'X-Chil': '0', 'X-V': '2', 'X-Av': '6.2.0', 'X-Scr': '2.0', 'X-Adv': '1', 'X-Seid': '22eb3b6b029be45d7cd5c7e00c14f3a4', 'X-Hitdot': '', 'G-Auth-Sign': 'NjUzMWY3YjJkYTk0YjgwNTc3MGY1ODU0MGJjZjhjZTM=', 'G-Auth-Nonce': '25f608945bc0ecc47fdd2cd9b0230c3e', 'G-Auth-Ts': '1558453550', 'G-Auth-Appid': '5a27d122ee4638163f594393', 'G-Auth-Token': 'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJsdW9qaWxhYi5jb20iLCJleHAiOjE1NTkwNTgwNjUsImlhdCI6MTU1ODQ1MzI2NSwiaXNzIjoiRWFzZUdhdGV3YXkgSldUQXV0aCBQbHVnaW4iLCJuYmYiOjE1NTg0NTMyNjUsInN1YiI6Ijg0ODQ2Mjc0In0.J_xlp1L4eCwiUfo8DVjKTRIcbNPIgtoUUJ2iDs3gB2EJDFo_qYcG8l1ZunlvXyYIpLMAEkA4ZyyxvtK1i6S-eQ', 'Content-Type': 'application/json; charset=UTF-8', 'Content-Length': '449', 'Host': 'entree.dev.igetget.com', 'Connection': 'Keep-Alive', 'Accept-Encoding': 'gzip', 'User-Agent': 'okhttp/3.11.0'}|{'type': 'audio', 'data': [{'action': 'goon', 'alias_id': 'vAkdmo4jroFNvu263tkH', 'progress': 6.43, 'time': 1558453550, 'type': 'audio', 'uid': 84846274}], 'h': {'u': '84846274', 'thumb': 'l', 'dt': 'phone', 'ov': '6.0', 'net': 'WIFI', 'os': 'ANDROID', 'd': 'ae244834553d4eda', 'dv': 'Samsung Galaxy S6', 't': 'json', 'chil': '0', 'v': '2', 'av': '6.2.0', 'scr': '2.0', 'adv': '1', 'X-Dv': 'Samsung Galaxy S6', 'ts': '1558453550', 's': 'db578eef9d289db9', 'seid': '22eb3b6b029be45d7cd5c7e00c14f3a4'}} 32 | http://entree.dev.igetget.com/centerproducer/v1/audio/actionpost|POST|{'X-App-Key': 'android-6.2.0', 'X-Uid': '84846274', 'X-Thumb': 'l', 'X-Dt': 'phone', 'X-Ov': '6.0', 'X-Net': 'WIFI', 'X-Os': 'ANDROID', 'X-D': 'ae244834553d4eda', 'X-Dv': 'Samsung Galaxy S6', 'X-T': 'json', 'X-Chil': '0', 'X-V': '2', 'X-Av': '6.2.0', 'X-Scr': '2.0', 'X-Adv': '1', 'X-Seid': '22eb3b6b029be45d7cd5c7e00c14f3a4', 'X-Hitdot': '', 'G-Auth-Sign': 'ZWVhMDY2ZDcyZDJiZjgwM2U2ODViYTNjZTZhNmNkMGI=', 'G-Auth-Nonce': '86b4ba5cc31978c3c4fc0686dace640a', 'G-Auth-Ts': '1558453555', 'G-Auth-Appid': '5a27d122ee4638163f594393', 'G-Auth-Token': 'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJsdW9qaWxhYi5jb20iLCJleHAiOjE1NTkwNTgwNjUsImlhdCI6MTU1ODQ1MzI2NSwiaXNzIjoiRWFzZUdhdGV3YXkgSldUQXV0aCBQbHVnaW4iLCJuYmYiOjE1NTg0NTMyNjUsInN1YiI6Ijg0ODQ2Mjc0In0.J_xlp1L4eCwiUfo8DVjKTRIcbNPIgtoUUJ2iDs3gB2EJDFo_qYcG8l1ZunlvXyYIpLMAEkA4ZyyxvtK1i6S-eQ', 'Content-Type': 'application/json; charset=UTF-8', 'Content-Length': '462', 'Host': 'entree.dev.igetget.com', 'Connection': 'Keep-Alive', 'Accept-Encoding': 'gzip', 'User-Agent': 'okhttp/3.11.0'}|{'type': 'audio', 'data': [{'action': 'pause', 'alias_id': 'vAkdmo4jroFNvu263tkH', 'progress': 6.69, 'reason': '', 'time': 1558453555, 'type': 'audio', 'uid': 84846274}], 'h': {'u': '84846274', 'thumb': 'l', 'dt': 'phone', 'ov': '6.0', 'net': 'WIFI', 'os': 'ANDROID', 'd': 'ae244834553d4eda', 'dv': 'Samsung Galaxy S6', 't': 'json', 'chil': '0', 'v': '2', 'av': '6.2.0', 'scr': '2.0', 'adv': '1', 'X-Dv': 'Samsung Galaxy S6', 'ts': '1558453555', 's': 'db578eef9d289db9', 'seid': '22eb3b6b029be45d7cd5c7e00c14f3a4'}} 33 | http://entree.dev.igetget.com/centerproducer/v1/audio/actionpost|POST|{'X-App-Key': 'android-6.2.0', 'X-Uid': '84846274', 'X-Thumb': 'l', 'X-Dt': 'phone', 'X-Ov': '6.0', 'X-Net': 'WIFI', 'X-Os': 'ANDROID', 'X-D': 'ae244834553d4eda', 'X-Dv': 'Samsung Galaxy S6', 'X-T': 'json', 'X-Chil': '0', 'X-V': '2', 'X-Av': '6.2.0', 'X-Scr': '2.0', 'X-Adv': '1', 'X-Seid': '22eb3b6b029be45d7cd5c7e00c14f3a4', 'X-Hitdot': '', 'G-Auth-Sign': 'ODk5ODk2NGFjMmQwM2U5OTgwZmFkYTRmNWZhMTBlNTM=', 'G-Auth-Nonce': '7321602ea9df8c693bdf8ffe49e56cc9', 'G-Auth-Ts': '1558453557', 'G-Auth-Appid': '5a27d122ee4638163f594393', 'G-Auth-Token': 'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJsdW9qaWxhYi5jb20iLCJleHAiOjE1NTkwNTgwNjUsImlhdCI6MTU1ODQ1MzI2NSwiaXNzIjoiRWFzZUdhdGV3YXkgSldUQXV0aCBQbHVnaW4iLCJuYmYiOjE1NTg0NTMyNjUsInN1YiI6Ijg0ODQ2Mjc0In0.J_xlp1L4eCwiUfo8DVjKTRIcbNPIgtoUUJ2iDs3gB2EJDFo_qYcG8l1ZunlvXyYIpLMAEkA4ZyyxvtK1i6S-eQ', 'Content-Type': 'application/json; charset=UTF-8', 'Content-Length': '451', 'Host': 'entree.dev.igetget.com', 'Connection': 'Keep-Alive', 'Accept-Encoding': 'gzip', 'User-Agent': 'okhttp/3.11.0'}|{'type': 'audio', 'data': [{'action': 'resume', 'alias_id': 'vAkdmo4jroFNvu263tkH', 'progress': 6.69, 'time': 1558453557, 'type': 'audio', 'uid': 84846274}], 'h': {'u': '84846274', 'thumb': 'l', 'dt': 'phone', 'ov': '6.0', 'net': 'WIFI', 'os': 'ANDROID', 'd': 'ae244834553d4eda', 'dv': 'Samsung Galaxy S6', 't': 'json', 'chil': '0', 'v': '2', 'av': '6.2.0', 'scr': '2.0', 'adv': '1', 'X-Dv': 'Samsung Galaxy S6', 'ts': '1558453557', 's': 'db578eef9d289db9', 'seid': '22eb3b6b029be45d7cd5c7e00c14f3a4'}} 34 | http://entree.dev.igetget.com/odob/v2/audio/detail|POST|{'X-App-Key': 'android-6.2.0', 'X-Uid': '84846274', 'X-Thumb': 'l', 'X-Dt': 'phone', 'X-Ov': '6.0', 'X-Net': 'WIFI', 'X-Os': 'ANDROID', 'X-D': 'ae244834553d4eda', 'X-Dv': 'Samsung Galaxy S6', 'X-T': 'json', 'X-Chil': '0', 'X-V': '2', 'X-Av': '6.2.0', 'X-Scr': '2.0', 'X-Adv': '1', 'X-Seid': '22eb3b6b029be45d7cd5c7e00c14f3a4', 'X-Hitdot': '', 'G-Auth-Sign': 'YjIzYzA3MGU4OTA1MDU4OGVkMWJlODU3MDc0MDM2NmQ=', 'G-Auth-Nonce': 'f467a2ec959855da3afefc3923c3ef09', 'G-Auth-Ts': '1558453623', 'G-Auth-Appid': '5a27d122ee4638163f594393', 'G-Auth-Token': 'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJsdW9qaWxhYi5jb20iLCJleHAiOjE1NTkwNTgwNjUsImlhdCI6MTU1ODQ1MzI2NSwiaXNzIjoiRWFzZUdhdGV3YXkgSldUQXV0aCBQbHVnaW4iLCJuYmYiOjE1NTg0NTMyNjUsInN1YiI6Ijg0ODQ2Mjc0In0.J_xlp1L4eCwiUfo8DVjKTRIcbNPIgtoUUJ2iDs3gB2EJDFo_qYcG8l1ZunlvXyYIpLMAEkA4ZyyxvtK1i6S-eQ', 'Content-Type': 'application/json; charset=UTF-8', 'Content-Length': '325', 'Host': 'entree.dev.igetget.com', 'Connection': 'Keep-Alive', 'Accept-Encoding': 'gzip', 'User-Agent': 'okhttp/3.11.0'}|{'topic_id': 3809, 'h': {'u': '84846274', 'thumb': 'l', 'dt': 'phone', 'ov': '6.0', 'net': 'WIFI', 'os': 'ANDROID', 'd': 'ae244834553d4eda', 'dv': 'Samsung Galaxy S6', 't': 'json', 'chil': '0', 'v': '2', 'av': '6.2.0', 'scr': '2.0', 'adv': '1', 'X-Dv': 'Samsung Galaxy S6', 'ts': '1558453623', 's': 'db578eef9d289db9', 'seid': '22eb3b6b029be45d7cd5c7e00c14f3a4'}} 35 | http://entree.dev.igetget.com/centerproducer/v1/audio/actionpost|POST|{'X-App-Key': 'android-6.2.0', 'X-Uid': '84846274', 'X-Thumb': 'l', 'X-Dt': 'phone', 'X-Ov': '6.0', 'X-Net': 'WIFI', 'X-Os': 'ANDROID', 'X-D': 'ae244834553d4eda', 'X-Dv': 'Samsung Galaxy S6', 'X-T': 'json', 'X-Chil': '0', 'X-V': '2', 'X-Av': '6.2.0', 'X-Scr': '2.0', 'X-Adv': '1', 'X-Seid': '22eb3b6b029be45d7cd5c7e00c14f3a4', 'X-Hitdot': '', 'G-Auth-Sign': 'YjNlMmRhODQxMzAwY2E4ZTE0MDI0NWI2YzRmMDRiMTQ=', 'G-Auth-Nonce': 'f7e37d661c01209ae1544094f3fd3dc8', 'G-Auth-Ts': '1558453624', 'G-Auth-Appid': '5a27d122ee4638163f594393', 'G-Auth-Token': 'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJsdW9qaWxhYi5jb20iLCJleHAiOjE1NTkwNTgwNjUsImlhdCI6MTU1ODQ1MzI2NSwiaXNzIjoiRWFzZUdhdGV3YXkgSldUQXV0aCBQbHVnaW4iLCJuYmYiOjE1NTg0NTMyNjUsInN1YiI6Ijg0ODQ2Mjc0In0.J_xlp1L4eCwiUfo8DVjKTRIcbNPIgtoUUJ2iDs3gB2EJDFo_qYcG8l1ZunlvXyYIpLMAEkA4ZyyxvtK1i6S-eQ', 'Content-Type': 'application/json; charset=UTF-8', 'Content-Length': '463', 'Host': 'entree.dev.igetget.com', 'Connection': 'Keep-Alive', 'Accept-Encoding': 'gzip', 'User-Agent': 'okhttp/3.11.0'}|{'type': 'audio', 'data': [{'action': 'pause', 'alias_id': 'vAkdmo4jroFNvu263tkH', 'progress': 10.98, 'reason': '', 'time': 1558453624, 'type': 'audio', 'uid': 84846274}], 'h': {'u': '84846274', 'thumb': 'l', 'dt': 'phone', 'ov': '6.0', 'net': 'WIFI', 'os': 'ANDROID', 'd': 'ae244834553d4eda', 'dv': 'Samsung Galaxy S6', 't': 'json', 'chil': '0', 'v': '2', 'av': '6.2.0', 'scr': '2.0', 'adv': '1', 'X-Dv': 'Samsung Galaxy S6', 'ts': '1558453624', 's': 'db578eef9d289db9', 'seid': '22eb3b6b029be45d7cd5c7e00c14f3a4'}} 36 | http://entree.dev.igetget.com/centerproducer/v1/audio/actionpost|POST|{'X-App-Key': 'android-6.2.0', 'X-Uid': '84846274', 'X-Thumb': 'l', 'X-Dt': 'phone', 'X-Ov': '6.0', 'X-Net': 'WIFI', 'X-Os': 'ANDROID', 'X-D': 'ae244834553d4eda', 'X-Dv': 'Samsung Galaxy S6', 'X-T': 'json', 'X-Chil': '0', 'X-V': '2', 'X-Av': '6.2.0', 'X-Scr': '2.0', 'X-Adv': '1', 'X-Seid': '22eb3b6b029be45d7cd5c7e00c14f3a4', 'X-Hitdot': '', 'G-Auth-Sign': 'MTA3YTBjMTI2NDgwMjhkNzRlZjUzNGRkNjE3MmFjMWQ=', 'G-Auth-Nonce': 'dcaa5fb21dfd66f08d9805179c86d61e', 'G-Auth-Ts': '1558453626', 'G-Auth-Appid': '5a27d122ee4638163f594393', 'G-Auth-Token': 'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJsdW9qaWxhYi5jb20iLCJleHAiOjE1NTkwNTgwNjUsImlhdCI6MTU1ODQ1MzI2NSwiaXNzIjoiRWFzZUdhdGV3YXkgSldUQXV0aCBQbHVnaW4iLCJuYmYiOjE1NTg0NTMyNjUsInN1YiI6Ijg0ODQ2Mjc0In0.J_xlp1L4eCwiUfo8DVjKTRIcbNPIgtoUUJ2iDs3gB2EJDFo_qYcG8l1ZunlvXyYIpLMAEkA4ZyyxvtK1i6S-eQ', 'Content-Type': 'application/json; charset=UTF-8', 'Content-Length': '450', 'Host': 'entree.dev.igetget.com', 'Connection': 'Keep-Alive', 'Accept-Encoding': 'gzip', 'User-Agent': 'okhttp/3.11.0'}|{'type': 'audio', 'data': [{'action': 'goon', 'alias_id': 'vAkdmo4jroFNvu263tkH', 'progress': 10.92, 'time': 1558453626, 'type': 'audio', 'uid': 84846274}], 'h': {'u': '84846274', 'thumb': 'l', 'dt': 'phone', 'ov': '6.0', 'net': 'WIFI', 'os': 'ANDROID', 'd': 'ae244834553d4eda', 'dv': 'Samsung Galaxy S6', 't': 'json', 'chil': '0', 'v': '2', 'av': '6.2.0', 'scr': '2.0', 'adv': '1', 'X-Dv': 'Samsung Galaxy S6', 'ts': '1558453626', 's': 'db578eef9d289db9', 'seid': '22eb3b6b029be45d7cd5c7e00c14f3a4'}} 37 | http://entree.dev.igetget.com/centerproducer/v1/audio/actionpost|POST|{'X-App-Key': 'android-6.2.0', 'X-Uid': '84846274', 'X-Thumb': 'l', 'X-Dt': 'phone', 'X-Ov': '6.0', 'X-Net': 'WIFI', 'X-Os': 'ANDROID', 'X-D': 'ae244834553d4eda', 'X-Dv': 'Samsung Galaxy S6', 'X-T': 'json', 'X-Chil': '0', 'X-V': '2', 'X-Av': '6.2.0', 'X-Scr': '2.0', 'X-Adv': '1', 'X-Seid': '22eb3b6b029be45d7cd5c7e00c14f3a4', 'X-Hitdot': '', 'G-Auth-Sign': 'OWE5YjFkZTIxN2UxNDU5NzhkNTE4NDNlZGZjYWNjYjY=', 'G-Auth-Nonce': '69702b2fd14d6a0006c3d8b6259a68fd', 'G-Auth-Ts': '1558453632', 'G-Auth-Appid': '5a27d122ee4638163f594393', 'G-Auth-Token': 'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJsdW9qaWxhYi5jb20iLCJleHAiOjE1NTkwNTgwNjUsImlhdCI6MTU1ODQ1MzI2NSwiaXNzIjoiRWFzZUdhdGV3YXkgSldUQXV0aCBQbHVnaW4iLCJuYmYiOjE1NTg0NTMyNjUsInN1YiI6Ijg0ODQ2Mjc0In0.J_xlp1L4eCwiUfo8DVjKTRIcbNPIgtoUUJ2iDs3gB2EJDFo_qYcG8l1ZunlvXyYIpLMAEkA4ZyyxvtK1i6S-eQ', 'Content-Type': 'application/json; charset=UTF-8', 'Content-Length': '450', 'Host': 'entree.dev.igetget.com', 'Connection': 'Keep-Alive', 'Accept-Encoding': 'gzip', 'User-Agent': 'okhttp/3.11.0'}|{'type': 'audio', 'data': [{'action': 'goon', 'alias_id': 'vAkdmo4jroFNvu263tkH', 'progress': 11.11, 'time': 1558453632, 'type': 'audio', 'uid': 84846274}], 'h': {'u': '84846274', 'thumb': 'l', 'dt': 'phone', 'ov': '6.0', 'net': 'WIFI', 'os': 'ANDROID', 'd': 'ae244834553d4eda', 'dv': 'Samsung Galaxy S6', 't': 'json', 'chil': '0', 'v': '2', 'av': '6.2.0', 'scr': '2.0', 'adv': '1', 'X-Dv': 'Samsung Galaxy S6', 'ts': '1558453632', 's': 'db578eef9d289db9', 'seid': '22eb3b6b029be45d7cd5c7e00c14f3a4'}} 38 | http://entree.dev.igetget.com/centerproducer/v1/audio/actionpost|POST|{'X-App-Key': 'android-6.2.0', 'X-Uid': '84846274', 'X-Thumb': 'l', 'X-Dt': 'phone', 'X-Ov': '6.0', 'X-Net': 'WIFI', 'X-Os': 'ANDROID', 'X-D': 'ae244834553d4eda', 'X-Dv': 'Samsung Galaxy S6', 'X-T': 'json', 'X-Chil': '0', 'X-V': '2', 'X-Av': '6.2.0', 'X-Scr': '2.0', 'X-Adv': '1', 'X-Seid': '22eb3b6b029be45d7cd5c7e00c14f3a4', 'X-Hitdot': '', 'G-Auth-Sign': 'ZGVkMzlmYTQ3NmZjNjljYzBhMTljZjU3MGUwNDRlYWM=', 'G-Auth-Nonce': '0aff699f73941686bf82e8807b386bfe', 'G-Auth-Ts': '1558453643', 'G-Auth-Appid': '5a27d122ee4638163f594393', 'G-Auth-Token': 'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJsdW9qaWxhYi5jb20iLCJleHAiOjE1NTkwNTgwNjUsImlhdCI6MTU1ODQ1MzI2NSwiaXNzIjoiRWFzZUdhdGV3YXkgSldUQXV0aCBQbHVnaW4iLCJuYmYiOjE1NTg0NTMyNjUsInN1YiI6Ijg0ODQ2Mjc0In0.J_xlp1L4eCwiUfo8DVjKTRIcbNPIgtoUUJ2iDs3gB2EJDFo_qYcG8l1ZunlvXyYIpLMAEkA4ZyyxvtK1i6S-eQ', 'Content-Type': 'application/json; charset=UTF-8', 'Content-Length': '463', 'Host': 'entree.dev.igetget.com', 'Connection': 'Keep-Alive', 'Accept-Encoding': 'gzip', 'User-Agent': 'okhttp/3.11.0'}|{'type': 'audio', 'data': [{'action': 'pause', 'alias_id': 'vAkdmo4jroFNvu263tkH', 'progress': 39.05, 'reason': '', 'time': 1558453643, 'type': 'audio', 'uid': 84846274}], 'h': {'u': '84846274', 'thumb': 'l', 'dt': 'phone', 'ov': '6.0', 'net': 'WIFI', 'os': 'ANDROID', 'd': 'ae244834553d4eda', 'dv': 'Samsung Galaxy S6', 't': 'json', 'chil': '0', 'v': '2', 'av': '6.2.0', 'scr': '2.0', 'adv': '1', 'X-Dv': 'Samsung Galaxy S6', 'ts': '1558453643', 's': 'db578eef9d289db9', 'seid': '22eb3b6b029be45d7cd5c7e00c14f3a4'}} 39 | -------------------------------------------------------------------------------- /dumphrun/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xinxi1990/mitmfuzz/807f105788620b5322e1c59db3c46b816a59c24a/dumphrun/__init__.py -------------------------------------------------------------------------------- /dumphrun/casefactory.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | 批量生成httprunner 6 | """ 7 | 8 | import json 9 | import urllib.parse 10 | from casetmp import * 11 | 12 | class CaseFactory(): 13 | 14 | 15 | @staticmethod 16 | def gen_case(file_path): 17 | ''' 18 | 组装数据 19 | :return: 20 | ''' 21 | records = [] 22 | with open(file_path) as f_r: 23 | for line in f_r.readlines(): 24 | item = line.split('|') 25 | url = item[0] 26 | method = item[1] 27 | header = CaseFactory.gen_header(item[2])[0] 28 | content_type = CaseFactory.gen_header(item[2])[1] 29 | data = CaseFactory.gen_data(item[3]) 30 | if method == "GET": 31 | # print(url) 32 | # print(method) 33 | # print(header) 34 | # print(content_type) 35 | # print(data) 36 | get_tmp['test']['request']['url'] = url 37 | get_tmp['test']['request']['headers'] = header 38 | test_case_tmp.append(get_tmp) 39 | elif method == "POST": 40 | post_tmp['test']['request']['url'] = url 41 | post_tmp['test']['request']['headers'] = header 42 | post_tmp['test']['request']['json'] = data 43 | test_case_tmp.append(post_tmp) 44 | 45 | with open('hrun_case.json', 'w') as f_w: 46 | f_w.write(json.dumps(test_case_tmp, indent=4)) 47 | 48 | 49 | 50 | # @staticmethod 51 | # def gen_header(headers): 52 | # content_type = "" 53 | # itmes = str((headers.replace('Headers[','')).replace(']','')).split(',') 54 | # key_list = [] 55 | # value_list = [] 56 | # for item in itmes[::2]: 57 | # # print(item) 58 | # key_list.append(item.replace("('","").replace(")'","").replace("(b","").replace("'","").replace("'","").strip()) 59 | # for item in itmes[1::2]: 60 | # # print(item) 61 | # value_list.append(item.replace("('","").replace(")'","").replace("(b","").replace("'","").strip()) 62 | # dictionary = dict(zip(key_list, value_list)) 63 | # if ('Content-Type' in dictionary): 64 | # content_type = (dictionary["Content-Type"]) 65 | # return dictionary,content_type 66 | 67 | # @staticmethod 68 | # def gen_data(data): 69 | # print(data) 70 | # s_data = urllib.parse.unquote(data).replace("b'", '').replace("'", '').replace("\n", "") 71 | # key_list = [] 72 | # value_list = [] 73 | # for s in s_data.split("&"): 74 | # if "=" in s: 75 | # key_list.append(s.split("=")[0]) 76 | # value_list.append(s.split("=")[1]) 77 | # dictionary = dict(zip(key_list, value_list)) 78 | # return dictionary 79 | 80 | 81 | @staticmethod 82 | def gen_header(headers): 83 | content_type = "" 84 | dictionary = eval(headers) 85 | if ('Content-Type' in dictionary): 86 | content_type = (dictionary["Content-Type"]) 87 | return dictionary, content_type 88 | 89 | 90 | @staticmethod 91 | def gen_data(data): 92 | dictionary = {} 93 | try: 94 | dictionary = eval(data) 95 | except Exception as e: 96 | print(e) 97 | return dictionary 98 | 99 | 100 | 101 | if __name__ == '__main__': 102 | print("==================== start gen ====================") 103 | CaseFactory.gen_case('20190521234042_intercept.log') 104 | print("==================== end gen ====================") -------------------------------------------------------------------------------- /dumphrun/casetmp.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | 生成httprunner测试用例模版 6 | """ 7 | 8 | import json 9 | 10 | # 11 | # get_tmp = \ 12 | # [ 13 | # { 14 | # "config": { 15 | # "name": "testcase description", 16 | # "variables": {} 17 | # } 18 | # }, 19 | # { 20 | # "test": { 21 | # "name": "casname", 22 | # "request": { 23 | # "url": "", 24 | # "method": "GET", 25 | # "headers": { 26 | # }, 27 | # }, 28 | # "validate": [ 29 | # {"eq": ["status_code", 200]} 30 | # ] 31 | # } 32 | # } 33 | # ] 34 | # 35 | # 36 | # 37 | # post_tmp = \ 38 | # [ 39 | # { 40 | # "config": { 41 | # "name": "testcase description", 42 | # "variables": {} 43 | # } 44 | # }, 45 | # { 46 | # "test": { 47 | # "name": "casname", 48 | # "request": { 49 | # "url": "", 50 | # "method": "POST", 51 | # "headers": { 52 | # }, 53 | # "json": { 54 | # } 55 | # }, 56 | # "validate": [ 57 | # {"eq": ["status_code", 200]} 58 | # ] 59 | # } 60 | # } 61 | # ] 62 | # 63 | # 64 | # 65 | # 66 | # get_tmp = \ 67 | # [ 68 | # { 69 | # "config": { 70 | # "name": "testcase description", 71 | # "variables": {} 72 | # } 73 | # }, 74 | # { 75 | # "test": { 76 | # "name": "casname", 77 | # "request": { 78 | # "url": "", 79 | # "method": "GET", 80 | # "headers": { 81 | # }, 82 | # }, 83 | # "validate": [ 84 | # {"eq": ["status_code", 200]} 85 | # ] 86 | # } 87 | # } 88 | # ] 89 | 90 | 91 | test_case_tmp = [{ 92 | "config": { 93 | "name": "testcase description", 94 | "variables": {} 95 | } 96 | } 97 | ] 98 | 99 | 100 | 101 | 102 | post_tmp = \ 103 | { 104 | "test": { 105 | "name": "casname", 106 | "request": { 107 | "url": "", 108 | "method": "POST", 109 | "headers": { 110 | }, 111 | "json": { 112 | } 113 | }, 114 | "validate": [ 115 | {"eq": ["status_code", 200]} 116 | ] 117 | } 118 | } 119 | 120 | get_tmp = \ 121 | { 122 | "test": { 123 | "name": "casname", 124 | "request": { 125 | "url": "", 126 | "method": "GET", 127 | "headers": { 128 | }, 129 | }, 130 | "validate": [ 131 | {"eq": ["status_code", 200]} 132 | ] 133 | } 134 | } 135 | 136 | 137 | 138 | # get_tmp[1]['test']['request']['headers'] = headers 139 | # get_tmp[1]['test']['request']['url'] = url 140 | 141 | 142 | # print(json.dumps(get_tmp,indent=4)) 143 | # 144 | # with open('hrun_case.json','w') as f_w: 145 | # f_w.write(json.dumps(get_tmp,indent=4)) -------------------------------------------------------------------------------- /dumphrun/filetools.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | 5 | """ 6 | @Author : xinxi 7 | @Time : 2018/12/5 18:34 8 | @describe: 常用操作类 9 | """ 10 | 11 | import os,re,time,subprocess,sys 12 | sys.path.append('..') 13 | 14 | 15 | 16 | def write_file(filename,content,is_cover=False): 17 | ''' 18 | 写入文件 覆盖写入 19 | :param filename: 20 | :param content: 21 | :param is_cover:是否覆盖写入 22 | :return: 23 | ''' 24 | try: 25 | newstr = "" 26 | if isinstance(content,list or tuple): 27 | for str in content: 28 | newstr = newstr + str + "\n" 29 | else: 30 | newstr = content + "\n" 31 | if is_cover == True: 32 | file_mode = "w" 33 | else: 34 | file_mode = "a" 35 | with open(filename,file_mode) as f_w: 36 | f_w.write(newstr) 37 | print('写{}文件完成'.format(filename)) 38 | except Exception as e: 39 | print('{}写入异常!{}'.format(filename,e)) 40 | 41 | 42 | def del_files(filename): 43 | ''' 44 | 删除文件 45 | :param filename: 46 | :return: 47 | ''' 48 | try: 49 | if os.path.exists(filename): 50 | subprocess.call("rm -rf {}".format(filename), shell=True) 51 | print('删除{}完成!'.format(filename)) 52 | except Exception as e: 53 | print('删除{}异常!{}'.format(filename,e)) 54 | 55 | 56 | def mk_dir(foldername): 57 | ''' 58 | 创建文件目录 59 | :return: 60 | ''' 61 | try: 62 | if not os.path.exists(foldername): 63 | subprocess.call("mkdir {}".format(foldername), shell=True) 64 | print('创建{}完成!'.format(foldername)) 65 | except Exception as e: 66 | print('创建{}异常!'.format(foldername,e)) 67 | 68 | 69 | def read_file(filename): 70 | ''' 71 | 读取文件 72 | :return: 73 | ''' 74 | result = '' 75 | try: 76 | with open(filename,"r") as f_r: 77 | result = f_r.readlines() 78 | except Exception as e: 79 | print('{}读取异常!{}'.format(filename,e)) 80 | finally: 81 | if isinstance(result,list) and len(result) == 1: 82 | return result[0] 83 | else: 84 | return result 85 | 86 | 87 | 88 | if __name__ == '__main__': 89 | write_file("test.log", "111111", is_cover=False) 90 | -------------------------------------------------------------------------------- /dumphrun/hrun_case_back.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "config": { 4 | "name": "testcase description", 5 | "variables": {} 6 | } 7 | }, 8 | { 9 | "test": { 10 | "name": "casname", 11 | "request": { 12 | "url": "http://dedao.dev.igetget.com/v3/igettv/structuredata?sign=4056bd5301cff045d4c0c2d8856322ea", 13 | "method": "POST", 14 | "headers": { 15 | "Cache-Control": "no-cache", 16 | "Content-Type": "application/json; charset=UTF-8", 17 | "Content-Length": "327", 18 | "Host": "dedao.dev.igetget.com", 19 | "Connection": "Keep-Alive", 20 | "Accept-Encoding": "gzip", 21 | "User-Agent": "okhttp/3.11.0" 22 | }, 23 | "json": { 24 | "struct_id": 25490, 25 | "h": { 26 | "u": "84846274", 27 | "thumb": "l", 28 | "dt": "phone", 29 | "ov": "6.0", 30 | "net": "WIFI", 31 | "os": "ANDROID", 32 | "d": "ae244834553d4eda", 33 | "dv": "Samsung Galaxy S6", 34 | "t": "json", 35 | "chil": "0", 36 | "v": "2", 37 | "av": "6.2.0", 38 | "scr": "2.0", 39 | "adv": "1", 40 | "X-Dv": "Samsung Galaxy S6", 41 | "ts": "1558452493", 42 | "s": "db578eef9d289db9", 43 | "seid": "1fdab2a5fa99e1edda214151eefc27d2" 44 | } 45 | } 46 | }, 47 | "validate": [ 48 | { 49 | "eq": [ 50 | "status_code", 51 | 200 52 | ] 53 | } 54 | ] 55 | } 56 | }, 57 | { 58 | "test": { 59 | "name": "casname", 60 | "request": { 61 | "url": "http://dedao.dev.igetget.com/v3/igettv/structuredata?sign=4056bd5301cff045d4c0c2d8856322ea", 62 | "method": "POST", 63 | "headers": { 64 | "Cache-Control": "no-cache", 65 | "Content-Type": "application/json; charset=UTF-8", 66 | "Content-Length": "327", 67 | "Host": "dedao.dev.igetget.com", 68 | "Connection": "Keep-Alive", 69 | "Accept-Encoding": "gzip", 70 | "User-Agent": "okhttp/3.11.0" 71 | }, 72 | "json": { 73 | "struct_id": 25490, 74 | "h": { 75 | "u": "84846274", 76 | "thumb": "l", 77 | "dt": "phone", 78 | "ov": "6.0", 79 | "net": "WIFI", 80 | "os": "ANDROID", 81 | "d": "ae244834553d4eda", 82 | "dv": "Samsung Galaxy S6", 83 | "t": "json", 84 | "chil": "0", 85 | "v": "2", 86 | "av": "6.2.0", 87 | "scr": "2.0", 88 | "adv": "1", 89 | "X-Dv": "Samsung Galaxy S6", 90 | "ts": "1558452493", 91 | "s": "db578eef9d289db9", 92 | "seid": "1fdab2a5fa99e1edda214151eefc27d2" 93 | } 94 | } 95 | }, 96 | "validate": [ 97 | { 98 | "eq": [ 99 | "status_code", 100 | 200 101 | ] 102 | } 103 | ] 104 | } 105 | }, 106 | { 107 | "test": { 108 | "name": "casname", 109 | "request": { 110 | "url": "http://dedao.dev.igetget.com/v3/igettv/structuredata?sign=4056bd5301cff045d4c0c2d8856322ea", 111 | "method": "POST", 112 | "headers": { 113 | "Cache-Control": "no-cache", 114 | "Content-Type": "application/json; charset=UTF-8", 115 | "Content-Length": "327", 116 | "Host": "dedao.dev.igetget.com", 117 | "Connection": "Keep-Alive", 118 | "Accept-Encoding": "gzip", 119 | "User-Agent": "okhttp/3.11.0" 120 | }, 121 | "json": { 122 | "struct_id": 25490, 123 | "h": { 124 | "u": "84846274", 125 | "thumb": "l", 126 | "dt": "phone", 127 | "ov": "6.0", 128 | "net": "WIFI", 129 | "os": "ANDROID", 130 | "d": "ae244834553d4eda", 131 | "dv": "Samsung Galaxy S6", 132 | "t": "json", 133 | "chil": "0", 134 | "v": "2", 135 | "av": "6.2.0", 136 | "scr": "2.0", 137 | "adv": "1", 138 | "X-Dv": "Samsung Galaxy S6", 139 | "ts": "1558452493", 140 | "s": "db578eef9d289db9", 141 | "seid": "1fdab2a5fa99e1edda214151eefc27d2" 142 | } 143 | } 144 | }, 145 | "validate": [ 146 | { 147 | "eq": [ 148 | "status_code", 149 | 200 150 | ] 151 | } 152 | ] 153 | } 154 | }, 155 | { 156 | "test": { 157 | "name": "casname", 158 | "request": { 159 | "url": "http://dedao.dev.igetget.com/v3/igettv/structuredata?sign=4056bd5301cff045d4c0c2d8856322ea", 160 | "method": "POST", 161 | "headers": { 162 | "Cache-Control": "no-cache", 163 | "Content-Type": "application/json; charset=UTF-8", 164 | "Content-Length": "327", 165 | "Host": "dedao.dev.igetget.com", 166 | "Connection": "Keep-Alive", 167 | "Accept-Encoding": "gzip", 168 | "User-Agent": "okhttp/3.11.0" 169 | }, 170 | "json": { 171 | "struct_id": 25490, 172 | "h": { 173 | "u": "84846274", 174 | "thumb": "l", 175 | "dt": "phone", 176 | "ov": "6.0", 177 | "net": "WIFI", 178 | "os": "ANDROID", 179 | "d": "ae244834553d4eda", 180 | "dv": "Samsung Galaxy S6", 181 | "t": "json", 182 | "chil": "0", 183 | "v": "2", 184 | "av": "6.2.0", 185 | "scr": "2.0", 186 | "adv": "1", 187 | "X-Dv": "Samsung Galaxy S6", 188 | "ts": "1558452493", 189 | "s": "db578eef9d289db9", 190 | "seid": "1fdab2a5fa99e1edda214151eefc27d2" 191 | } 192 | } 193 | }, 194 | "validate": [ 195 | { 196 | "eq": [ 197 | "status_code", 198 | 200 199 | ] 200 | } 201 | ] 202 | } 203 | }, 204 | { 205 | "test": { 206 | "name": "casname", 207 | "request": { 208 | "url": "http://dedao.dev.igetget.com/v3/igettv/structuredata?sign=4056bd5301cff045d4c0c2d8856322ea", 209 | "method": "POST", 210 | "headers": { 211 | "Cache-Control": "no-cache", 212 | "Content-Type": "application/json; charset=UTF-8", 213 | "Content-Length": "327", 214 | "Host": "dedao.dev.igetget.com", 215 | "Connection": "Keep-Alive", 216 | "Accept-Encoding": "gzip", 217 | "User-Agent": "okhttp/3.11.0" 218 | }, 219 | "json": { 220 | "struct_id": 25490, 221 | "h": { 222 | "u": "84846274", 223 | "thumb": "l", 224 | "dt": "phone", 225 | "ov": "6.0", 226 | "net": "WIFI", 227 | "os": "ANDROID", 228 | "d": "ae244834553d4eda", 229 | "dv": "Samsung Galaxy S6", 230 | "t": "json", 231 | "chil": "0", 232 | "v": "2", 233 | "av": "6.2.0", 234 | "scr": "2.0", 235 | "adv": "1", 236 | "X-Dv": "Samsung Galaxy S6", 237 | "ts": "1558452493", 238 | "s": "db578eef9d289db9", 239 | "seid": "1fdab2a5fa99e1edda214151eefc27d2" 240 | } 241 | } 242 | }, 243 | "validate": [ 244 | { 245 | "eq": [ 246 | "status_code", 247 | 200 248 | ] 249 | } 250 | ] 251 | } 252 | }, 253 | { 254 | "test": { 255 | "name": "casname", 256 | "request": { 257 | "url": "http://dedao.dev.igetget.com/v3/igettv/structuredata?sign=4056bd5301cff045d4c0c2d8856322ea", 258 | "method": "POST", 259 | "headers": { 260 | "Cache-Control": "no-cache", 261 | "Content-Type": "application/json; charset=UTF-8", 262 | "Content-Length": "327", 263 | "Host": "dedao.dev.igetget.com", 264 | "Connection": "Keep-Alive", 265 | "Accept-Encoding": "gzip", 266 | "User-Agent": "okhttp/3.11.0" 267 | }, 268 | "json": { 269 | "struct_id": 25490, 270 | "h": { 271 | "u": "84846274", 272 | "thumb": "l", 273 | "dt": "phone", 274 | "ov": "6.0", 275 | "net": "WIFI", 276 | "os": "ANDROID", 277 | "d": "ae244834553d4eda", 278 | "dv": "Samsung Galaxy S6", 279 | "t": "json", 280 | "chil": "0", 281 | "v": "2", 282 | "av": "6.2.0", 283 | "scr": "2.0", 284 | "adv": "1", 285 | "X-Dv": "Samsung Galaxy S6", 286 | "ts": "1558452493", 287 | "s": "db578eef9d289db9", 288 | "seid": "1fdab2a5fa99e1edda214151eefc27d2" 289 | } 290 | } 291 | }, 292 | "validate": [ 293 | { 294 | "eq": [ 295 | "status_code", 296 | 200 297 | ] 298 | } 299 | ] 300 | } 301 | }, 302 | { 303 | "test": { 304 | "name": "casname", 305 | "request": { 306 | "url": "http://dedao.dev.igetget.com/v3/igettv/structuredata?sign=4056bd5301cff045d4c0c2d8856322ea", 307 | "method": "POST", 308 | "headers": { 309 | "Cache-Control": "no-cache", 310 | "Content-Type": "application/json; charset=UTF-8", 311 | "Content-Length": "327", 312 | "Host": "dedao.dev.igetget.com", 313 | "Connection": "Keep-Alive", 314 | "Accept-Encoding": "gzip", 315 | "User-Agent": "okhttp/3.11.0" 316 | }, 317 | "json": { 318 | "struct_id": 25490, 319 | "h": { 320 | "u": "84846274", 321 | "thumb": "l", 322 | "dt": "phone", 323 | "ov": "6.0", 324 | "net": "WIFI", 325 | "os": "ANDROID", 326 | "d": "ae244834553d4eda", 327 | "dv": "Samsung Galaxy S6", 328 | "t": "json", 329 | "chil": "0", 330 | "v": "2", 331 | "av": "6.2.0", 332 | "scr": "2.0", 333 | "adv": "1", 334 | "X-Dv": "Samsung Galaxy S6", 335 | "ts": "1558452493", 336 | "s": "db578eef9d289db9", 337 | "seid": "1fdab2a5fa99e1edda214151eefc27d2" 338 | } 339 | } 340 | }, 341 | "validate": [ 342 | { 343 | "eq": [ 344 | "status_code", 345 | 200 346 | ] 347 | } 348 | ] 349 | } 350 | }, 351 | { 352 | "test": { 353 | "name": "casname", 354 | "request": { 355 | "url": "http://dedao.dev.igetget.com/v3/igettv/structuredata?sign=4056bd5301cff045d4c0c2d8856322ea", 356 | "method": "POST", 357 | "headers": { 358 | "Cache-Control": "no-cache", 359 | "Content-Type": "application/json; charset=UTF-8", 360 | "Content-Length": "327", 361 | "Host": "dedao.dev.igetget.com", 362 | "Connection": "Keep-Alive", 363 | "Accept-Encoding": "gzip", 364 | "User-Agent": "okhttp/3.11.0" 365 | }, 366 | "json": { 367 | "struct_id": 25490, 368 | "h": { 369 | "u": "84846274", 370 | "thumb": "l", 371 | "dt": "phone", 372 | "ov": "6.0", 373 | "net": "WIFI", 374 | "os": "ANDROID", 375 | "d": "ae244834553d4eda", 376 | "dv": "Samsung Galaxy S6", 377 | "t": "json", 378 | "chil": "0", 379 | "v": "2", 380 | "av": "6.2.0", 381 | "scr": "2.0", 382 | "adv": "1", 383 | "X-Dv": "Samsung Galaxy S6", 384 | "ts": "1558452493", 385 | "s": "db578eef9d289db9", 386 | "seid": "1fdab2a5fa99e1edda214151eefc27d2" 387 | } 388 | } 389 | }, 390 | "validate": [ 391 | { 392 | "eq": [ 393 | "status_code", 394 | 200 395 | ] 396 | } 397 | ] 398 | } 399 | }, 400 | { 401 | "test": { 402 | "name": "casname", 403 | "request": { 404 | "url": "http://dedao.dev.igetget.com/v3/igettv/structuredata?sign=4056bd5301cff045d4c0c2d8856322ea", 405 | "method": "POST", 406 | "headers": { 407 | "Cache-Control": "no-cache", 408 | "Content-Type": "application/json; charset=UTF-8", 409 | "Content-Length": "327", 410 | "Host": "dedao.dev.igetget.com", 411 | "Connection": "Keep-Alive", 412 | "Accept-Encoding": "gzip", 413 | "User-Agent": "okhttp/3.11.0" 414 | }, 415 | "json": { 416 | "struct_id": 25490, 417 | "h": { 418 | "u": "84846274", 419 | "thumb": "l", 420 | "dt": "phone", 421 | "ov": "6.0", 422 | "net": "WIFI", 423 | "os": "ANDROID", 424 | "d": "ae244834553d4eda", 425 | "dv": "Samsung Galaxy S6", 426 | "t": "json", 427 | "chil": "0", 428 | "v": "2", 429 | "av": "6.2.0", 430 | "scr": "2.0", 431 | "adv": "1", 432 | "X-Dv": "Samsung Galaxy S6", 433 | "ts": "1558452493", 434 | "s": "db578eef9d289db9", 435 | "seid": "1fdab2a5fa99e1edda214151eefc27d2" 436 | } 437 | } 438 | }, 439 | "validate": [ 440 | { 441 | "eq": [ 442 | "status_code", 443 | 200 444 | ] 445 | } 446 | ] 447 | } 448 | }, 449 | { 450 | "test": { 451 | "name": "casname", 452 | "request": { 453 | "url": "http://dedao.dev.igetget.com/v3/igettv/structuredata?sign=4056bd5301cff045d4c0c2d8856322ea", 454 | "method": "POST", 455 | "headers": { 456 | "Cache-Control": "no-cache", 457 | "Content-Type": "application/json; charset=UTF-8", 458 | "Content-Length": "327", 459 | "Host": "dedao.dev.igetget.com", 460 | "Connection": "Keep-Alive", 461 | "Accept-Encoding": "gzip", 462 | "User-Agent": "okhttp/3.11.0" 463 | }, 464 | "json": { 465 | "struct_id": 25490, 466 | "h": { 467 | "u": "84846274", 468 | "thumb": "l", 469 | "dt": "phone", 470 | "ov": "6.0", 471 | "net": "WIFI", 472 | "os": "ANDROID", 473 | "d": "ae244834553d4eda", 474 | "dv": "Samsung Galaxy S6", 475 | "t": "json", 476 | "chil": "0", 477 | "v": "2", 478 | "av": "6.2.0", 479 | "scr": "2.0", 480 | "adv": "1", 481 | "X-Dv": "Samsung Galaxy S6", 482 | "ts": "1558452493", 483 | "s": "db578eef9d289db9", 484 | "seid": "1fdab2a5fa99e1edda214151eefc27d2" 485 | } 486 | } 487 | }, 488 | "validate": [ 489 | { 490 | "eq": [ 491 | "status_code", 492 | 200 493 | ] 494 | } 495 | ] 496 | } 497 | } 498 | ] -------------------------------------------------------------------------------- /dumphrun/proxyserver.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | 5 | """ 6 | 使用mitmproxy录制测试用例 7 | """ 8 | 9 | import mitmproxy.http 10 | from mitmproxy import ctx 11 | import json,time,os 12 | from filetools import * 13 | 14 | 15 | project_path = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) 16 | now = time.strftime("%Y%m%d%H%M%S", time.localtime()) + "_intercept.log" 17 | save_log_file = os.path.join(project_path, now) 18 | 19 | def request(flow: mitmproxy.http.HTTPFlow): 20 | request = flow.request 21 | ctx.log.info("========================== intercept request start ==========================") 22 | ctx.log.info("========================== intercept request start ==========================") 23 | ctx.log.info("========================== host is:{} ========================== ".format(request.host)) 24 | ctx.log.info("========================== url is:{} ========================== ".format(request.pretty_url)) 25 | ctx.log.info("========================== method is:{} ========================== ".format(request.method)) 26 | ctx.log.info("========================== body is:{} ========================== ".format(request.get_text())) 27 | ctx.log.info("========================== intercept request end ==========================") 28 | 29 | 30 | def response(flow: mitmproxy.http.HTTPFlow): 31 | ''' 32 | 篡改response返回数据 33 | :param flow: 34 | :return: 35 | ''' 36 | is_mock = True 37 | 38 | black_list = ["png", "jpg", "js", "css", "html",'img','cdn'] 39 | 40 | for balck_str in black_list: 41 | if balck_str in flow.request.url: 42 | ctx.log.info("========================== not intercept response ==========================") 43 | is_mock = False 44 | break 45 | 46 | if int(flow.response.status_code) == 200 and is_mock == True: 47 | original_data = (flow.response.text) 48 | if original_data.startswith("{") and original_data.endswith("}"): 49 | ctx.log.info("========================== intercept response end ==========================") 50 | spend_time = int((flow.response.timestamp_end - flow.request.timestamp_start) * 1000) 51 | key_list = [] 52 | values_list = [] 53 | for key, values in flow.request.headers.items(): 54 | key_list.append(key) 55 | values_list.append(values) 56 | headers = dict(zip(key_list, values_list)) 57 | key_list = [] 58 | values_list = [] 59 | for key, values in eval(flow.request.data.content).items(): 60 | key_list.append(key) 61 | values_list.append(values) 62 | data = dict(zip(key_list, values_list)) 63 | content = str(flow.request.url) + '|' + str(flow.request.method) + '|' + str(headers) + '|' \ 64 | + str(data) 65 | write_file(save_log_file,content,is_cover=False) 66 | 67 | 68 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /dumphrun/reports/1558442162.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | - TestReport 5 | 149 | 150 | 151 | 152 |

Test Report:

153 | 154 |

Summary

155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 |
START AT2019-05-21 20:36:02
DURATION0.111 seconds
PLATFORMHttpRunner 2.0.6 CPython 2.7.15 Darwin-17.7.0-x86_64-i386-64bit
STATTESTCASES (success/fail)TESTSTEPS (success/fail/error/skip)
total (details) =>1 (0/1)1 (0/1/0/0)
181 | 182 |

Details

183 | 184 | 185 | 186 |

testcase description

187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 490 | 491 | 492 |
TOTAL: 1SUCCESS: 0FAILED: 1ERROR: 0SKIPPED: 0
StatusNameResponse TimeDetail
failurecasname28.43 ms 210 | 211 | 212 | 213 | log-1 214 | 471 | 472 | 473 | 474 | traceback 475 | 487 | 488 | 489 |
493 | 494 | -------------------------------------------------------------------------------- /dumphrun/reports/1558442233.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | - TestReport 5 | 149 | 150 | 151 | 152 |

Test Report:

153 | 154 |

Summary

155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 |
START AT2019-05-21 20:37:13
DURATION0.089 seconds
PLATFORMHttpRunner 2.0.6 CPython 2.7.15 Darwin-17.7.0-x86_64-i386-64bit
STATTESTCASES (success/fail)TESTSTEPS (success/fail/error/skip)
total (details) =>1 (1/0)1 (1/0/0/0)
181 | 182 |

Details

183 | 184 | 185 | 186 |

testcase description

187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 472 | 473 | 474 |
TOTAL: 1SUCCESS: 1FAILED: 0ERROR: 0SKIPPED: 0
StatusNameResponse TimeDetail
successcasname32.60 ms 210 | 211 | 212 | 213 | log-1 214 | 467 | 468 | 469 | 470 | 471 |
475 | 476 | -------------------------------------------------------------------------------- /dumphrun/reports/1558448260.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | - TestReport 5 | 149 | 150 | 151 | 152 |

Test Report:

153 | 154 |

Summary

155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 |
START AT2019-05-21 22:17:40
DURATION0.343 seconds
PLATFORMHttpRunner 2.0.6 CPython 2.7.15 Darwin-17.7.0-x86_64-i386-64bit
STATTESTCASES (success/fail)TESTSTEPS (success/fail/error/skip)
total (details) =>1 (1/0)1 (1/0/0/0)
181 | 182 |

Details

183 | 184 | 185 | 186 |

testcase description

187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 531 | 532 | 533 |
TOTAL: 1SUCCESS: 1FAILED: 0ERROR: 0SKIPPED: 0
StatusNameResponse TimeDetail
successcasname280.73 ms 210 | 211 | 212 | 213 | log-1 214 | 526 | 527 | 528 | 529 | 530 |
534 | 535 | -------------------------------------------------------------------------------- /dumphrun/reports/1558448626.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | - TestReport 5 | 149 | 150 | 151 | 152 |

Test Report:

153 | 154 |

Summary

155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 |
START AT2019-05-21 22:23:46
DURATION0.144 seconds
PLATFORMHttpRunner 2.0.6 CPython 2.7.15 Darwin-17.7.0-x86_64-i386-64bit
STATTESTCASES (success/fail)TESTSTEPS (success/fail/error/skip)
total (details) =>1 (1/0)1 (1/0/0/0)
181 | 182 |

Details

183 | 184 | 185 | 186 |

testcase description

187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 531 | 532 | 533 |
TOTAL: 1SUCCESS: 1FAILED: 0ERROR: 0SKIPPED: 0
StatusNameResponse TimeDetail
successcasname84.05 ms 210 | 211 | 212 | 213 | log-1 214 | 526 | 527 | 528 | 529 | 530 |
534 | 535 | -------------------------------------------------------------------------------- /dumphrun/test.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | import json 4 | 5 | headers = {} 6 | headers["User-Agent"] = "111" 7 | 8 | print(str(headers)) 9 | print(json.dumps(headers)) 10 | print(type()) -------------------------------------------------------------------------------- /mitm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xinxi1990/mitmfuzz/807f105788620b5322e1c59db3c46b816a59c24a/mitm.png -------------------------------------------------------------------------------- /proxy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xinxi1990/mitmfuzz/807f105788620b5322e1c59db3c46b816a59c24a/proxy.png -------------------------------------------------------------------------------- /proxy/20190521225436_intercept.log: -------------------------------------------------------------------------------- 1 | http://entree.dev.igetget.com/odob/v2/agency/list|POST|200|103|{"h":{"c":0,"e":"","s":1558450481,"t":42},"c":{"list":[{"id":16,"name":"韩焱","intro":"韩焱,资深出版人,著名图书出版品牌“湛庐文化”创始人、董事长,在得到App“每天听本书”栏目解读了众多湛庐文化出版的优质图书。\r\n\r\n湛庐文化自2005年创办至今,出版图书上千种,涵盖科技趋势、金融投资、经济管理、心理学等众多领域,如《影响力》《牛奶可乐经济学》《大数据时代》《千面英雄》等。\r\n\r\n2017年,湛庐文化基于上千种图书和2000万读者的积累,创办了自有知识服务平台“湛庐阅读”。\r\n\r\n“让我们与最聪明的人共同进化。”","qcg_id":243,"qcg_member_name":"韩焱","qcg_member_avatar":"http://piccdn.igetget.com/img/201804/17/201804171909028650884783.jpg","book_count":26,"uv":0,"status":1,"share_title":"听书解读人:韩焱","share_summary":"韩焱,资深出版人,著名图书出版品牌“湛庐文化”创始人、董事长,在得到App“每天听本书”栏目解读了众多湛庐文化出版的优质图书。\r\n\r\n湛庐文化自2005年创办至今,出版图书上千种,涵盖科技趋势、金融投资、经济管理、心理学等众多领域,如《影响力》《牛奶可乐经济学》《大数据时代》《千面英雄》等。\r\n\r\n2017年,湛庐文化基于上千种图书和2000万读者的积累,创办了自有知识服务平台“湛庐阅读”。\r\n\r\n“让我们与最聪明的人共同进化。”","share_img":"http://piccdn.igetget.com/img/201804/17/201804171909028650884783.jpg","share_url":"http://m.dev.igetget.com/share/agency/id/16","created_at":1521719737,"updated_at":1556264585,"rank_pos":1,"log_id":"16","log_type":"agency"},{"id":15,"name":"张凯","intro":"张凯,自由撰稿人,得到App精品课《怎样成为快速阅读的高手》主讲人,少年得到App《十倍速阅读法》主讲人,得到App“每天听本书”栏目资深撰稿人。\r\n\r\n解读代表作有《光荣与梦想》《伯罗奔尼撒战争》《魔鬼经济学》《文明之光》《超预测》等,涉及管理学、心理学、经济学、社会学等多个领域。\r\n\r\n擅长用简洁的语言,讲述陌生领域的新知识。","qcg_id":142,"qcg_member_name":"张凯","qcg_member_avatar":"http://piccdn.igetget.com/img/201803/22/201803221923519969331605.jpg","book_count":61,"uv":0,"status":1,"share_title":"听书解读人:张凯","share_summary":"张凯,自由撰稿人,得到App精品课《怎样成为快速阅读的高手》主讲人,少年得到App《十倍速阅读法》主讲人,得到App“每天听本书”栏目资深撰稿人。\r\n\r\n解读代表作有《光荣与梦想》《伯罗奔尼撒战争》《魔鬼经济学》《文明之光》《超预测》等,涉及管理学、心理学、经济学、社会学等多个领域。\r\n\r\n擅长用简洁的语言,讲述陌生领域的新知识。","share_img":"http://piccdn.igetget.com/img/201803/22/201803221923519969331605.jpg","share_url":"http://m.dev.igetget.com/share/agency/id/15","created_at":1521718025,"updated_at":1548301144,"rank_pos":2,"log_id":"15","log_type":"agency"},{"id":7,"name":"刘玮","intro":"刘玮,中国人民大学哲学院副教授。他是北京大学哲学学士,清华大学哲学硕士,香港中文大学哲学博士,美国加州大学伯克利分校、德国慕尼黑大学访问学者。\r\n\r\n主要研究古希腊哲学、西方哲学史。\r\n\r\n他是得到App“每天听本书”栏目西方哲学经典系列解读人。这个系列希望带你领略哲学家探索人类知识边界的一次次伟大努力,用平实的语言展示伟大哲学著作的深刻与魅力。","qcg_id":77,"qcg_member_name":"刘玮","qcg_member_avatar":"http://piccdn.igetget.com/img/201708/25/201708251126368588659193.jpg","book_count":13,"uv":0,"status":1,"share_title":"听书解读人:刘玮","share_summary":"刘玮,中国人民大学哲学院副教授。他是北京大学哲学学士,清华大学哲学硕士,香港中文大学哲学博士,美国加州大学伯克利分校、德国慕尼黑大学访问学者。\r\n\r\n主要研究古希腊哲学、西方哲学史。\r\n\r\n他是得到App“每天听本书”栏目西方哲学经典系列解读人。这个系列希望带你领略哲学家探索人类知识边界的一次次伟大努力,用平实的语言展示伟大哲学著作的深刻与魅力。","share_img":"http://piccdn.igetget.com/img/201708/25/201708251126368588659193.jpg","share_url":"http://m.dev.igetget.com/share/agency/id/7","created_at":1521524985,"updated_at":1548301243,"rank_pos":3,"log_id":"7","log_type":"agency"},{"id":12,"name":"柴知道","intro":"专注于知识传播的自媒体团队。2016年开始制作知识短视频和读书节目,目前全网视频播放量超过5亿次,全平台粉丝数超过1000万。\r\n\r\n擅长解读科普经典著作、知识型书籍。","qcg_id":296,"qcg_member_name":"柴知道","qcg_member_avatar":"http://piccdn.igetget.com/img/201803/20/201803201106400361846914.jpg","book_count":17,"uv":0,"status":1,"share_title":"听书解读人:柴知道","share_summary":"专注于知识传播的自媒体团队。2016年开始制作知识短视频和读书节目,目前全网视频播放量超过5亿次,全平台粉丝数超过1000万。\r\n\r\n擅长解读科普经典著作、知识型书籍。","share_img":"http://piccdn.igetget.com/img/201803/20/201803201106400361846914.jpg","share_url":"http://m.dev.igetget.com/share/agency/id/12","created_at":1521529920,"updated_at":1550746618,"rank_pos":4,"log_id":"12","log_type":"agency"}]}}|{"h": {"c": 0, "e": "", "s": 1558450481, "t": 42}, "c": {"list": [{"id": 16, "name": "\u97e9\u7131", "intro": "\u97e9\u7131\uff0c\u8d44\u6df1\u51fa\u7248\u4eba\uff0c\u8457\u540d\u56fe\u4e66\u51fa\u7248\u54c1\u724c\u201c\u6e5b\u5e90\u6587\u5316\u201d\u521b\u59cb\u4eba\u3001\u8463\u4e8b\u957f\uff0c\u5728\u5f97\u5230App\u201c\u6bcf\u5929\u542c\u672c\u4e66\u201d\u680f\u76ee\u89e3\u8bfb\u4e86\u4f17\u591a\u6e5b\u5e90\u6587\u5316\u51fa\u7248\u7684\u4f18\u8d28\u56fe\u4e66\u3002\r\n\r\n\u6e5b\u5e90\u6587\u5316\u81ea2005\u5e74\u521b\u529e\u81f3\u4eca\uff0c\u51fa\u7248\u56fe\u4e66\u4e0a\u5343\u79cd\uff0c\u6db5\u76d6\u79d1\u6280\u8d8b\u52bf\u3001\u91d1\u878d\u6295\u8d44\u3001\u7ecf\u6d4e\u7ba1\u7406\u3001\u5fc3\u7406\u5b66\u7b49\u4f17\u591a\u9886\u57df\uff0c\u5982\u300a\u5f71\u54cd\u529b\u300b\u300a\u725b\u5976\u53ef\u4e50\u7ecf\u6d4e\u5b66\u300b\u300a\u5927\u6570\u636e\u65f6\u4ee3\u300b\u300a\u5343\u9762\u82f1\u96c4\u300b\u7b49\u3002\r\n\r\n2017\u5e74\uff0c\u6e5b\u5e90\u6587\u5316\u57fa\u4e8e\u4e0a\u5343\u79cd\u56fe\u4e66\u548c2000\u4e07\u8bfb\u8005\u7684\u79ef\u7d2f\uff0c\u521b\u529e\u4e86\u81ea\u6709\u77e5\u8bc6\u670d\u52a1\u5e73\u53f0\u201c\u6e5b\u5e90\u9605\u8bfb\u201d\u3002\r\n\r\n\u201c\u8ba9\u6211\u4eec\u4e0e\u6700\u806a\u660e\u7684\u4eba\u5171\u540c\u8fdb\u5316\u3002\u201d", "qcg_id": 243, "qcg_member_name": "\u97e9\u7131", "qcg_member_avatar": "http://piccdn.igetget.com/img/201804/17/201804171909028650884783.jpg", "book_count": 26, "uv": 0, "status": 1, "share_title": "\u542c\u4e66\u89e3\u8bfb\u4eba:\u97e9\u7131", "share_summary": "\u97e9\u7131\uff0c\u8d44\u6df1\u51fa\u7248\u4eba\uff0c\u8457\u540d\u56fe\u4e66\u51fa\u7248\u54c1\u724c\u201c\u6e5b\u5e90\u6587\u5316\u201d\u521b\u59cb\u4eba\u3001\u8463\u4e8b\u957f\uff0c\u5728\u5f97\u5230App\u201c\u6bcf\u5929\u542c\u672c\u4e66\u201d\u680f\u76ee\u89e3\u8bfb\u4e86\u4f17\u591a\u6e5b\u5e90\u6587\u5316\u51fa\u7248\u7684\u4f18\u8d28\u56fe\u4e66\u3002\r\n\r\n\u6e5b\u5e90\u6587\u5316\u81ea2005\u5e74\u521b\u529e\u81f3\u4eca\uff0c\u51fa\u7248\u56fe\u4e66\u4e0a\u5343\u79cd\uff0c\u6db5\u76d6\u79d1\u6280\u8d8b\u52bf\u3001\u91d1\u878d\u6295\u8d44\u3001\u7ecf\u6d4e\u7ba1\u7406\u3001\u5fc3\u7406\u5b66\u7b49\u4f17\u591a\u9886\u57df\uff0c\u5982\u300a\u5f71\u54cd\u529b\u300b\u300a\u725b\u5976\u53ef\u4e50\u7ecf\u6d4e\u5b66\u300b\u300a\u5927\u6570\u636e\u65f6\u4ee3\u300b\u300a\u5343\u9762\u82f1\u96c4\u300b\u7b49\u3002\r\n\r\n2017\u5e74\uff0c\u6e5b\u5e90\u6587\u5316\u57fa\u4e8e\u4e0a\u5343\u79cd\u56fe\u4e66\u548c2000\u4e07\u8bfb\u8005\u7684\u79ef\u7d2f\uff0c\u521b\u529e\u4e86\u81ea\u6709\u77e5\u8bc6\u670d\u52a1\u5e73\u53f0\u201c\u6e5b\u5e90\u9605\u8bfb\u201d\u3002\r\n\r\n\u201c\u8ba9\u6211\u4eec\u4e0e\u6700\u806a\u660e\u7684\u4eba\u5171\u540c\u8fdb\u5316\u3002\u201d", "share_img": "http://piccdn.igetget.com/img/201804/17/201804171909028650884783.jpg", "share_url": "http://m.dev.igetget.com/share/agency/id/16", "created_at": 1521719737, "updated_at": 1556264585, "rank_pos": 1, "log_id": "16", "log_type": "agency"}, {"id": 15, "intro": "\u5f20\u51ef\uff0c\u81ea\u7531\u64b0\u7a3f\u4eba\uff0c\u5f97\u5230App\u7cbe\u54c1\u8bfe\u300a\u600e\u6837\u6210\u4e3a\u5feb\u901f\u9605\u8bfb\u7684\u9ad8\u624b\u300b\u4e3b\u8bb2\u4eba\uff0c\u5c11\u5e74\u5f97\u5230App\u300a\u5341\u500d\u901f\u9605\u8bfb\u6cd5\u300b\u4e3b\u8bb2\u4eba\uff0c\u5f97\u5230App\u201c\u6bcf\u5929\u542c\u672c\u4e66\u201d\u680f\u76ee\u8d44\u6df1\u64b0\u7a3f\u4eba\u3002\r\n\r\n\u89e3\u8bfb\u4ee3\u8868\u4f5c\u6709\u300a\u5149\u8363\u4e0e\u68a6\u60f3\u300b\u300a\u4f2f\u7f57\u5954\u5c3c\u6492\u6218\u4e89\u300b\u300a\u9b54\u9b3c\u7ecf\u6d4e\u5b66\u300b\u300a\u6587\u660e\u4e4b\u5149\u300b\u300a\u8d85\u9884\u6d4b\u300b\u7b49\uff0c\u6d89\u53ca\u7ba1\u7406\u5b66\u3001\u5fc3\u7406\u5b66\u3001\u7ecf\u6d4e\u5b66\u3001\u793e\u4f1a\u5b66\u7b49\u591a\u4e2a\u9886\u57df\u3002\r\n\r\n\u64c5\u957f\u7528\u7b80\u6d01\u7684\u8bed\u8a00\uff0c\u8bb2\u8ff0\u964c\u751f\u9886\u57df\u7684\u65b0\u77e5\u8bc6\u3002", "qcg_id": 142, "qcg_member_name": "\u5f20\u51ef", "qcg_member_avatar": "http://piccdn.igetget.com/img/201803/22/201803221923519969331605.jpg", "book_count": 61, "uv": 0, "status": 1, "share_title": "XN~qvHc6Kr", "share_summary": "\u5f20\u51ef\uff0c\u81ea\u7531\u64b0\u7a3f\u4eba\uff0c\u5f97\u5230App\u7cbe\u54c1\u8bfe\u300a\u600e\u6837\u6210\u4e3a\u5feb\u901f\u9605\u8bfb\u7684\u9ad8\u624b\u300b\u4e3b\u8bb2\u4eba\uff0c\u5c11\u5e74\u5f97\u5230App\u300a\u5341\u500d\u901f\u9605\u8bfb\u6cd5\u300b\u4e3b\u8bb2\u4eba\uff0c\u5f97\u5230App\u201c\u6bcf\u5929\u542c\u672c\u4e66\u201d\u680f\u76ee\u8d44\u6df1\u64b0\u7a3f\u4eba\u3002\r\n\r\n\u89e3\u8bfb\u4ee3\u8868\u4f5c\u6709\u300a\u5149\u8363\u4e0e\u68a6\u60f3\u300b\u300a\u4f2f\u7f57\u5954\u5c3c\u6492\u6218\u4e89\u300b\u300a\u9b54\u9b3c\u7ecf\u6d4e\u5b66\u300b\u300a\u6587\u660e\u4e4b\u5149\u300b\u300a\u8d85\u9884\u6d4b\u300b\u7b49\uff0c\u6d89\u53ca\u7ba1\u7406\u5b66\u3001\u5fc3\u7406\u5b66\u3001\u7ecf\u6d4e\u5b66\u3001\u793e\u4f1a\u5b66\u7b49\u591a\u4e2a\u9886\u57df\u3002\r\n\r\n\u64c5\u957f\u7528\u7b80\u6d01\u7684\u8bed\u8a00\uff0c\u8bb2\u8ff0\u964c\u751f\u9886\u57df\u7684\u65b0\u77e5\u8bc6\u3002", "share_img": "http://piccdn.igetget.com/img/201803/22/201803221923519969331605.jpg", "share_url": "http://m.dev.igetget.com/share/agency/id/15", "created_at": 1521718025, "updated_at": 1548301144, "rank_pos": 2, "log_id": "15", "log_type": "agency"}, {"id": 7, "name": "\u5218\u73ae", "intro": "\u5218\u73ae\uff0c\u4e2d\u56fd\u4eba\u6c11\u5927\u5b66\u54f2\u5b66\u9662\u526f\u6559\u6388\u3002\u4ed6\u662f\u5317\u4eac\u5927\u5b66\u54f2\u5b66\u5b66\u58eb\uff0c\u6e05\u534e\u5927\u5b66\u54f2\u5b66\u7855\u58eb\uff0c\u9999\u6e2f\u4e2d\u6587\u5927\u5b66\u54f2\u5b66\u535a\u58eb\uff0c\u7f8e\u56fd\u52a0\u5dde\u5927\u5b66\u4f2f\u514b\u5229\u5206\u6821\u3001\u5fb7\u56fd\u6155\u5c3c\u9ed1\u5927\u5b66\u8bbf\u95ee\u5b66\u8005\u3002\r\n\r\n\u4e3b\u8981\u7814\u7a76\u53e4\u5e0c\u814a\u54f2\u5b66\u3001\u897f\u65b9\u54f2\u5b66\u53f2\u3002\r\n\r\n\u4ed6\u662f\u5f97\u5230App\u201c\u6bcf\u5929\u542c\u672c\u4e66\u201d\u680f\u76ee\u897f\u65b9\u54f2\u5b66\u7ecf\u5178\u7cfb\u5217\u89e3\u8bfb\u4eba\u3002\u8fd9\u4e2a\u7cfb\u5217\u5e0c\u671b\u5e26\u4f60\u9886\u7565\u54f2\u5b66\u5bb6\u63a2\u7d22\u4eba\u7c7b\u77e5\u8bc6\u8fb9\u754c\u7684\u4e00\u6b21\u6b21\u4f1f\u5927\u52aa\u529b\uff0c\u7528\u5e73\u5b9e\u7684\u8bed\u8a00\u5c55\u793a\u4f1f\u5927\u54f2\u5b66\u8457\u4f5c\u7684\u6df1\u523b\u4e0e\u9b45\u529b\u3002", "qcg_id": 77, "qcg_member_name": "\u5218\u73ae", "qcg_member_avatar": "http://piccdn.igetget.com/img/201708/25/201708251126368588659193.jpg", "book_count": 13, "uv": 0, "status": 1, "share_title": "\u542c\u4e66\u89e3\u8bfb\u4eba:\u5218\u73ae", "share_summary": "\u5218\u73ae\uff0c\u4e2d\u56fd\u4eba\u6c11\u5927\u5b66\u54f2\u5b66\u9662\u526f\u6559\u6388\u3002\u4ed6\u662f\u5317\u4eac\u5927\u5b66\u54f2\u5b66\u5b66\u58eb\uff0c\u6e05\u534e\u5927\u5b66\u54f2\u5b66\u7855\u58eb\uff0c\u9999\u6e2f\u4e2d\u6587\u5927\u5b66\u54f2\u5b66\u535a\u58eb\uff0c\u7f8e\u56fd\u52a0\u5dde\u5927\u5b66\u4f2f\u514b\u5229\u5206\u6821\u3001\u5fb7\u56fd\u6155\u5c3c\u9ed1\u5927\u5b66\u8bbf\u95ee\u5b66\u8005\u3002\r\n\r\n\u4e3b\u8981\u7814\u7a76\u53e4\u5e0c\u814a\u54f2\u5b66\u3001\u897f\u65b9\u54f2\u5b66\u53f2\u3002\r\n\r\n\u4ed6\u662f\u5f97\u5230App\u201c\u6bcf\u5929\u542c\u672c\u4e66\u201d\u680f\u76ee\u897f\u65b9\u54f2\u5b66\u7ecf\u5178\u7cfb\u5217\u89e3\u8bfb\u4eba\u3002\u8fd9\u4e2a\u7cfb\u5217\u5e0c\u671b\u5e26\u4f60\u9886\u7565\u54f2\u5b66\u5bb6\u63a2\u7d22\u4eba\u7c7b\u77e5\u8bc6\u8fb9\u754c\u7684\u4e00\u6b21\u6b21\u4f1f\u5927\u52aa\u529b\uff0c\u7528\u5e73\u5b9e\u7684\u8bed\u8a00\u5c55\u793a\u4f1f\u5927\u54f2\u5b66\u8457\u4f5c\u7684\u6df1\u523b\u4e0e\u9b45\u529b\u3002", "share_img": "http://piccdn.igetget.com/img/201708/25/201708251126368588659193.jpg", "share_url": "http://m.dev.igetget.com/share/agency/id/7", "created_at": 1521524985, "updated_at": 1548301243, "rank_pos": 3, "log_id": "7", "log_type": "agency"}, {"id": 12, "name": "\u67f4\u77e5\u9053", "intro": "\u4e13\u6ce8\u4e8e\u77e5\u8bc6\u4f20\u64ad\u7684\u81ea\u5a92\u4f53\u56e2\u961f\u30022016\u5e74\u5f00\u59cb\u5236\u4f5c\u77e5\u8bc6\u77ed\u89c6\u9891\u548c\u8bfb\u4e66\u8282\u76ee\uff0c\u76ee\u524d\u5168\u7f51\u89c6\u9891\u64ad\u653e\u91cf\u8d85\u8fc75\u4ebf\u6b21\uff0c\u5168\u5e73\u53f0\u7c89\u4e1d\u6570\u8d85\u8fc71000\u4e07\u3002\r\n\r\n\u64c5\u957f\u89e3\u8bfb\u79d1\u666e\u7ecf\u5178\u8457\u4f5c\u3001\u77e5\u8bc6\u578b\u4e66\u7c4d\u3002", "qcg_id": 296, "qcg_member_name": "\u67f4\u77e5\u9053", "qcg_member_avatar": "http://piccdn.igetget.com/img/201803/20/201803201106400361846914.jpg", "book_count": 17, "uv": 0, "status": 1, "share_title": "\u542c\u4e66\u89e3\u8bfb\u4eba:\u67f4\u77e5\u9053", "share_summary": "\u4e13\u6ce8\u4e8e\u77e5\u8bc6\u4f20\u64ad\u7684\u81ea\u5a92\u4f53\u56e2\u961f\u30022016\u5e74\u5f00\u59cb\u5236\u4f5c\u77e5\u8bc6\u77ed\u89c6\u9891\u548c\u8bfb\u4e66\u8282\u76ee\uff0c\u76ee\u524d\u5168\u7f51\u89c6\u9891\u64ad\u653e\u91cf\u8d85\u8fc75\u4ebf\u6b21\uff0c\u5168\u5e73\u53f0\u7c89\u4e1d\u6570\u8d85\u8fc71000\u4e07\u3002\r\n\r\n\u64c5\u957f\u89e3\u8bfb\u79d1\u666e\u7ecf\u5178\u8457\u4f5c\u3001\u77e5\u8bc6\u578b\u4e66\u7c4d\u3002", "share_img": "http://piccdn.igetget.com/img/201803/20/201803201106400361846914.jpg", "share_url": "http://m.dev.igetget.com/share/agency/id/12", "created_at": 1521529920, "updated_at": 1550746618, "rank_pos": 4, "log_id": "12", "log_type": "agency"}]}} 2 | http://entree.dev.igetget.com/kaleidoscope/homepage/new_structure|POST|200|95|{"h":{"c":0,"e":"","s":1558450482,"t":2},"c":{"home_bucket_id":"A","ios_column_switch":0,"now":"2019-05-21","structure":[{"count":5,"data":{},"has_title":2,"page_type":112,"position":20,"struct_id":25487,"type":"NewCategory"},{"count":1,"data":{},"has_title":2,"page_type":113,"position":40,"struct_id":25489,"type":"HomepageOperationAssortment"},{"count":1,"data":{},"has_title":2,"page_type":10,"position":50,"struct_id":25490,"type":"live"},{"count":0,"data":{},"has_title":1,"page_type":3,"position":60,"struct_id":25491,"type":"freeAudio"},{"count":0,"data":{},"has_title":2,"page_type":2,"position":70,"struct_id":25494,"type":"column"},{"count":0,"data":{},"has_title":2,"page_type":36,"position":80,"struct_id":25493,"type":"master"},{"count":0,"data":{},"has_title":2,"page_type":22,"position":90,"struct_id":25492,"type":"course"},{"count":1,"data":{},"has_title":2,"page_type":131,"position":100,"struct_id":25495,"type":"HomepageLastUpdateStory"},{"count":1,"data":{},"has_title":2,"page_type":130,"position":110,"struct_id":25496,"type":"HomepageLastUpdateEbook"},{"count":1,"data":{},"has_title":2,"page_type":132,"position":120,"struct_id":25497,"type":"NewHomepageLastUpdateClass"},{"count":1,"data":{},"has_title":2,"page_type":90,"position":130,"struct_id":25498,"type":"NewHomepageOperationContentModule"},{"count":3,"data":{},"has_title":2,"page_type":127,"position":150,"struct_id":25500,"type":"HomepageRankList"},{"count":0,"data":{"list":[{"count":0,"data":{},"has_title":2,"page_type":124,"position":4,"struct_id":25484,"type":"RecommendGoods"},{"count":0,"data":{},"has_title":2,"page_type":125,"position":5,"struct_id":25485,"type":"RecommendFeedBanner"}]},"has_title":2,"page_type":129,"position":270,"struct_id":25512,"type":"NewGuessYouLike"}]}}|{"h": {"c": 0, "e": "", "s": 1558450482, "t": 2}, "c": {"home_bucket_id": "A", "ios_column_switch": 0, "now": "2019-05-21", "structure": [{"count": 5, "data": {}, "has_title": 2, "page_type": 112, "position": "", "struct_id": 25487, "type": "NewCategory"}, {"count": 1, "data": {}, "has_title": 2, "page_type": 113, "position": 40, "struct_id": 25489, "type": "HomepageOperationAssortment"}, {"count": 1, "data": {}, "has_title": 2, "page_type": 10, "position": 50, "struct_id": 25490, "type": "live"}, {"count": 0, "data": {}, "has_title": 1, "page_type": 3, "position": 60, "struct_id": 25491, "type": "freeAudio"}, {"count": 0, "data": {}, "has_title": 2, "page_type": 2, "position": 70, "struct_id": 25494, "type": "column"}, {"count": 0, "data": {}, "has_title": 2, "page_type": 36, "position": 80, "struct_id": 25493, "type": "master"}, {"count": 0, "data": {}, "has_title": 2, "page_type": 22, "position": 90, "struct_id": 25492, "type": "course"}, {"count": 1, "data": {}, "has_title": 2, "page_type": 131, "position": 100, "struct_id": 25495, "type": "HomepageLastUpdateStory"}, {"count": 1, "data": {}, "has_title": 2, "page_type": 130, "position": 110, "struct_id": 25496, "type": "HomepageLastUpdateEbook"}, {"count": 1, "data": {}, "has_title": 2, "page_type": 132, "position": 120, "struct_id": 25497, "type": "NewHomepageLastUpdateClass"}, {"count": 1, "data": {}, "has_title": 2, "page_type": 90, "position": 130, "struct_id": 25498, "type": "NewHomepageOperationContentModule"}, {"count": 3, "data": {}, "has_title": 2, "page_type": 127, "position": 150, "struct_id": 25500, "type": "HomepageRankList"}, {"count": 0, "data": {"list": [{"count": 0, "data": {}, "has_title": 2, "page_type": 124, "position": 4, "struct_id": 25484, "type": "RecommendGoods"}, {"count": 0, "data": {}, "has_title": 2, "page_type": 125, "position": 5, "struct_id": 25485, "type": "RecommendFeedBanner"}]}, "has_title": 2, "page_type": 129, "position": 270, "struct_id": 25512, "type": "NewGuessYouLike"}]}} 3 | http://entree.dev.igetget.com/ddph/createToken|POST|200|72|{"c":{"token":"e45d7f444c59a9afe26e4224324a4e3e"},"h":{"c":0,"e":"","t":0,"s":1558450493}}|{"c": {"token": "\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32\u8d85\u957f\u5b57\u7b26\u4e32"}, "h": {"c": 0, "e": "", "t": 0, "s": 1558450493}} 4 | -------------------------------------------------------------------------------- /proxy/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xinxi1990/mitmfuzz/807f105788620b5322e1c59db3c46b816a59c24a/proxy/__init__.py -------------------------------------------------------------------------------- /proxy/backups.py: -------------------------------------------------------------------------------- 1 | # -*- encoding:utf-8 -*- 2 | 3 | 4 | # author:授客 5 | 6 | 7 | import re 8 | 9 | 10 | def parse_sub_expr(sub_expr): 11 | ''' 12 | 13 | 解析字表达式-元素路径的组成部分 14 | 15 | :param sub_expr: 16 | 17 | :return: 18 | 19 | ''' 20 | 21 | RIGHT_INDEX_DEFAULT = '200000000' # 右侧索引的默认值 未指定右侧索引时使用,形如 key[2:]、key[:] 22 | 23 | result = re.findall('\[.+\]', sub_expr) 24 | 25 | if result: # 如果子表达式为数组,形如 [1]、key[1]、 key[1:2]、 key[2:]、 key[:3]、key[:] 26 | 27 | array_part = result[0] 28 | 29 | array_part = array_part.lstrip('[').rstrip(']') 30 | 31 | key_part = sub_expr[:sub_expr.index('[')] 32 | 33 | if key_part == '$': # 如果key为 $ ,为根,替换为数据变量 json_data 34 | 35 | key_part = JSON_DATA_VARNAME 36 | 37 | elif key_part == '*': 38 | 39 | key_part == '\[.+\]' # 如果key为 * ,替换为 \[\.+\] 以便匹配 ["key1"]、["key2"]、…… 40 | 41 | else: 42 | 43 | key_part = '\["%s"\]' % key_part 44 | 45 | if array_part == '*': # 如果数组索引为 * ,替换为 \[\d+\] 以便匹配 [0]、[1]、…… 46 | 47 | array_part = '\[\d+\]' 48 | 49 | else: 50 | 51 | array_part_list = array_part.replace(' ', '').split(':') 52 | 53 | left_index = array_part_list[0:1] 54 | 55 | right_index = array_part_list[1:] 56 | 57 | if left_index: 58 | 59 | left_index = left_index[0] 60 | 61 | if not (left_index or left_index.isdigit()): # 为空字符串、非数字 62 | 63 | left_index = '0' 64 | 65 | else: 66 | 67 | left_index = '0' 68 | 69 | if right_index: 70 | 71 | right_index = right_index[0] 72 | 73 | if not (right_index or right_index.isdigit()): 74 | right_index = RIGHT_INDEX_DEFAULT # 一个比较大的值, 75 | 76 | array_part = left_index + '-' + right_index 77 | 78 | else: 79 | 80 | array_part = left_index 81 | 82 | array_part = '\[[%s]\]' % array_part # 数组索引设置为 \[[n-m]\],以便匹配[n],[n+1], ……,[m-1] 83 | 84 | return key_part + array_part 85 | 86 | elif sub_expr == '*': 87 | 88 | sub_expr = '\[.+\]' 89 | 90 | elif sub_expr == '$': 91 | 92 | sub_expr = JSON_DATA_VARNAME 93 | 94 | else: 95 | 96 | sub_expr = '\["%s"\]' % sub_expr 97 | 98 | return sub_expr 99 | 100 | 101 | def parse_json(json_data, data_struct_link): 102 | ''' 103 | 104 | 递归解析json数据结构,存储元素的路径 105 | 106 | :param json_data: 107 | 108 | :param data_struct_link: 109 | 110 | :return: 111 | 112 | ''' 113 | 114 | if type(json_data) == type({}): # 字典类型 115 | 116 | keys_list = json_data.keys() 117 | 118 | for key in keys_list: 119 | 120 | temp_data_struct_link = data_struct_link + '["%s"]' % key 121 | 122 | if type(json_data[key]) not in [type({}), type([])]: # key对应的value值既不是数组,也不是字典 123 | 124 | data_struct_list.append(temp_data_struct_link) 125 | 126 | else: 127 | 128 | parse_json(json_data[key], temp_data_struct_link) 129 | 130 | elif type(json_data) == type([]): # 数组类型 131 | 132 | array_length = len(json_data) 133 | 134 | for index in range(0, array_length): 135 | 136 | temp_json_data = json_data[index] 137 | 138 | keys_list = temp_json_data.keys() 139 | 140 | for key in keys_list: 141 | 142 | temp_data_struct_link = data_struct_link + '[%s]["%s"]' % (str(index), key) 143 | 144 | if type(temp_json_data[key]) not in [type({}), type([])]: # key对应的value值既不是数组,也不是字典 145 | 146 | data_struct_list.append(temp_data_struct_link) 147 | 148 | else: 149 | 150 | parse_json(temp_json_data[key], temp_data_struct_link) 151 | 152 | 153 | if __name__ == '__main__': 154 | 155 | json_data = [{"data": [{ 156 | 157 | "admin": "string|集群负责人|||", 158 | 159 | "components": [ 160 | 161 | { 162 | 163 | "clusterId": "integer|组件所属的集群 id|||", 164 | 165 | "createTime": "string|组件创建时间|||", 166 | 167 | "description": "string|组件描述|||", 168 | 169 | "enabled": "boolean|组件是否开启||false|", 170 | 171 | }, 172 | 173 | { 174 | 175 | "clusterId": "integer|组件所属的集群 id|||", 176 | 177 | "createTime": "string|组件创建时间|||", 178 | 179 | "description": "string|组件描述|||", 180 | 181 | "enabled": "boolean|组件是否开启||false|", 182 | 183 | } 184 | 185 | ], 186 | 187 | "createTime": "string|集群创建时间|||", 188 | 189 | "description": "string|集群描述|||", 190 | 191 | "enabled": "boolean|集群是否开启||false|", 192 | 193 | "id": "integer|集群 id|||", 194 | 195 | "modifyTime": "string|集群修改时间|||", 196 | 197 | "name": "string|集群名|||" 198 | 199 | }], 200 | 201 | "errMsg": "string||||", 202 | 203 | "ok": "boolean||||", 204 | 205 | "status": "integer||||" 206 | 207 | }] 208 | 209 | JSON_DATA_VARNAME = 'json_data' # 存在json数据的变量名称 210 | 211 | data_struct_list = [] # 用于存放所有 json 元素路径,形如 json_data[0]["data"][0]["components"][0]["enabled"] 212 | 213 | data_struct_link = 'json_data' # 用于临时存放单条json 元素路径(的一部分) 214 | 215 | parse_json(json_data, data_struct_link) 216 | 217 | print('获取的json元素路径,元素值如下:') 218 | 219 | for item in data_struct_list: 220 | print(item, '\t', eval(item)) 221 | 222 | # 测试用表达式 223 | 224 | # expr = '$.data[*].components[0]' # json数据为字典 形如 {……} 225 | 226 | # expr = '$[*].data[0:1].components[*]' # json数据为数组 形如 [{……}] 227 | 228 | expr = 'data[0:1].components[*]' 229 | 230 | # expr = 'data[0:1].components' 231 | 232 | # 解析表达式为正则表达式 233 | 234 | re_pattern = '' 235 | 236 | for sub_expr in expr.split('.'): 237 | re_pattern += parse_sub_expr(sub_expr) 238 | 239 | print('\n元素路径jsonpath表达式为:%s' % expr) 240 | 241 | print('元素路径正则表达式re pattern为:%s' % re_pattern) 242 | 243 | print('\njsonpath 匹配结果如下:') 244 | 245 | re_pattern = re.compile(re_pattern) 246 | 247 | target_set = set() # 匹配结果会有重复值,所以采用集合 248 | 249 | for item in data_struct_list: 250 | 251 | results = re.findall(re_pattern, item) 252 | 253 | for result in results: 254 | print('匹配的元素路径jsonpath为:%s' % item) 255 | 256 | print('正则匹配结果为:%s' % result) 257 | 258 | target = item[0:item.index(result) + len(result)] 259 | 260 | print('供提取数据使用的jsonpath为:%s' % target) 261 | 262 | print('提取的结果值为:%s \n' % eval(target)) 263 | 264 | target_set.add(target) 265 | 266 | # 通过匹配提取的目标结果,操作json串 267 | 268 | for item in target_set: 269 | print("target item:" + item) 270 | target = eval(item) 271 | print("target value:{}".format(target)) 272 | print("target type:{}".format(type(target))) 273 | 274 | if type(target) == type({}): # 如果为字典 275 | 276 | # 更改键的值 277 | print("更改键的值") 278 | target['clusterId'] = 10 279 | 280 | # 新增键值对 281 | 282 | target['new_key'] = 'key_value' 283 | 284 | # 更改键的名称,可以考虑先复制旧的键值,赋值给新的键,然后删除旧的键 285 | 286 | target['description_new'] = target['description'] 287 | 288 | # 删除键值对 289 | 290 | del target['description'] 291 | 292 | 293 | 294 | elif type(target) == type([]): 295 | 296 | # 暂不实现 297 | 298 | pass 299 | 300 | print(json_data) -------------------------------------------------------------------------------- /proxy/constant.py: -------------------------------------------------------------------------------- 1 | # *_*coding:utf-8 *_* 2 | 3 | split_joint='+' -------------------------------------------------------------------------------- /proxy/filetools.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | 5 | """ 6 | @Author : xinxi 7 | @Time : 2018/12/5 18:34 8 | @describe: 常用操作类 9 | """ 10 | 11 | import os,re,time,subprocess,sys 12 | sys.path.append('..') 13 | 14 | 15 | 16 | def write_file(filename,content,is_cover=False): 17 | ''' 18 | 写入文件 覆盖写入 19 | :param filename: 20 | :param content: 21 | :param is_cover:是否覆盖写入 22 | :return: 23 | ''' 24 | try: 25 | newstr = "" 26 | if isinstance(content,list or tuple): 27 | for str in content: 28 | newstr = newstr + str + "\n" 29 | else: 30 | newstr = content + "\n" 31 | if is_cover == True: 32 | file_mode = "w" 33 | else: 34 | file_mode = "a" 35 | with open(filename,file_mode,encoding='utf-8') as f_w: 36 | f_w.write(newstr) 37 | print('写{}文件完成'.format(filename)) 38 | except Exception as e: 39 | print('{}写入异常!{}'.format(filename,e)) 40 | 41 | 42 | def del_files(filename): 43 | ''' 44 | 删除文件 45 | :param filename: 46 | :return: 47 | ''' 48 | try: 49 | if os.path.exists(filename): 50 | subprocess.call("rm -rf {}".format(filename), shell=True) 51 | print('删除{}完成!'.format(filename)) 52 | except Exception as e: 53 | print('删除{}异常!{}'.format(filename,e)) 54 | 55 | 56 | def mk_dir(foldername): 57 | ''' 58 | 创建文件目录 59 | :return: 60 | ''' 61 | try: 62 | if not os.path.exists(foldername): 63 | subprocess.call("mkdir {}".format(foldername), shell=True) 64 | print('创建{}完成!'.format(foldername)) 65 | except Exception as e: 66 | print('创建{}异常!'.format(foldername,e)) 67 | 68 | 69 | def read_file(filename): 70 | ''' 71 | 读取文件 72 | :return: 73 | ''' 74 | result = '' 75 | try: 76 | with open(filename,"r") as f_r: 77 | result = f_r.readlines() 78 | except Exception as e: 79 | print('{}读取异常!{}'.format(filename,e)) 80 | finally: 81 | if isinstance(result,list) and len(result) == 1: 82 | return result[0] 83 | else: 84 | return result 85 | 86 | 87 | 88 | if __name__ == '__main__': 89 | write_file("test.log", "111111", is_cover=False) 90 | -------------------------------------------------------------------------------- /proxy/genhtml.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | @Author : xinxi 6 | @Time : 2018/12/5 18:34 7 | @describe: 创建报告 8 | """ 9 | 10 | import os, time, sys, json 11 | sys.path.append('..') 12 | from jinja2 import Environment, PackageLoader 13 | from deepdiff import DeepDiff 14 | 15 | 16 | class Create(): 17 | 18 | def __init__(self, report_path, log_path): 19 | self.report_path = report_path 20 | self.log_path = log_path 21 | 22 | def create_html(self): 23 | ''' 24 | 生成html报告 25 | ''' 26 | report_folder = os.path.join(self.report_path, 'reports') 27 | if not os.path.exists(report_folder): 28 | os.makedirs(report_folder) 29 | print("创建报告存储文件夹:{}".format(report_folder)) 30 | report_path = os.path.join(report_folder, "report_{}.html".format(time.strftime("%Y%m%d%H%M%S"))) 31 | try: 32 | env = Environment(loader=PackageLoader('proxy', 'templates')) 33 | template = env.get_template("template.html") 34 | records = Create.gen_data(self.log_path) 35 | html_content = template.render(html_report_name="测试报告", records=records) 36 | with open(report_path, "wb") as f: 37 | f.write(html_content.encode("utf-8")) 38 | print('报告地址:\n{}'.format(report_path)) 39 | except Exception as e: 40 | print('生成报告异常!{}'.format(e)) 41 | finally: 42 | return report_path 43 | 44 | @staticmethod 45 | def gen_data(file_path): 46 | ''' 47 | 组装数据 48 | :return: 49 | ''' 50 | records = [] 51 | with open(file_path, encoding='utf-8') as f_r: 52 | i=0 53 | for line in f_r.readlines(): 54 | i=i+1 55 | print('line:',line) 56 | print('line[0]:',line[0]) 57 | if line[0]!='{': 58 | line_json = eval(line[1:]) #第一行第一个可能有个特殊字符 59 | else: 60 | line_json = eval(line) 61 | param_len = line_json['param_len'] 62 | item = line_json['param_value'] 63 | data = {} 64 | data['name'] = item[0:param_len[0]] 65 | data['method'] = item[param_len[0] + 1:param_len[0] + 1 + param_len[1]] 66 | data['status'] = item[param_len[0] + param_len[1] + 2:param_len[0] + param_len[1] + param_len[2] + 2] 67 | data['response_time_ms'] = item[ 68 | param_len[0] + param_len[1] + param_len[2] + 3:param_len[0] + param_len[1] + 69 | param_len[2] + param_len[ 70 | 3] + 3] 71 | data_original_str = str(item[ 72 | param_len[0] + param_len[1] + param_len[2] + param_len[3] + 4:param_len[0] + 73 | param_len[1] + 74 | param_len[2] + 75 | param_len[3] + 76 | param_len[4] + 4]) 77 | data_intercept_str = str(item[ 78 | param_len[0] + param_len[1] + param_len[2] + param_len[3] + param_len[4] + 5: 79 | param_len[0] + param_len[1] + param_len[2] + param_len[3] + param_len[4] + 80 | param_len[5] + 5]) 81 | data['original'] = json.dumps(eval(data_original_str), indent=4) 82 | data['intercept'] = json.dumps(eval(data_intercept_str), indent=4) 83 | # diff_data = diff(eval(item[2]),eval(item[3])) 84 | diff_data = DeepDiff(eval(data_original_str), eval(data_intercept_str), ignore_order=True) 85 | data['diff'] = diff_data 86 | records.append(data) 87 | return records 88 | 89 | 90 | if __name__ == '__main__': 91 | save_path = sys.argv[1] 92 | request_log_path = sys.argv[2] 93 | Create(save_path, request_log_path).create_html() 94 | -------------------------------------------------------------------------------- /proxy/logger.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | 5 | ''' 6 | 日志级别大小关系为:CRITICAL > ERROR > WARNING > INFO > DEBUG > NOTSET 7 | 使用规则: 8 | 1.正常输出使用INFO 9 | 2.捕获异常使用ERROR 10 | 3.调试代码使用DEBUG 11 | 4.setLevel可以通过外部参数修改 12 | @author:xinxi 13 | ''' 14 | 15 | import logging 16 | import sys 17 | import time 18 | from colorama import Back, Fore, Style, init 19 | from colorlog import ColoredFormatter 20 | 21 | 22 | 23 | init(autoreset=True) 24 | 25 | log_colors_config = { 26 | 'DEBUG': 'cyan', 27 | 'INFO': 'green', 28 | 'WARNING': 'yellow', 29 | 'ERROR': 'red', 30 | 'CRITICAL': 'red', 31 | } 32 | 33 | 34 | def setup_logger(log_level): 35 | """setup root logger with ColoredFormatter.""" 36 | level = getattr(logging, log_level.upper(), None) 37 | if not level: 38 | color_print("Invalid log level: %s" % log_level, "RED") 39 | sys.exit(1) 40 | 41 | # hide traceback when log level is INFO/WARNING/ERROR/CRITICAL 42 | if level >= logging.INFO: 43 | sys.tracebacklimit = 0 44 | 45 | formatter = ColoredFormatter( 46 | u"%(log_color)s%(bg_white)s%(levelname)-8s%(reset)s%(message)s", 47 | datefmt=None, 48 | reset=True, 49 | log_colors=log_colors_config 50 | ) 51 | 52 | handler = logging.StreamHandler() 53 | handler.setFormatter(formatter) 54 | logging.root.addHandler(handler) 55 | logging.root.setLevel(level) 56 | 57 | 58 | def coloring(dt,text, color="WHITE"): 59 | fore_color = getattr(Fore, color.upper()) 60 | 61 | if isinstance(text,tuple or list): 62 | text = str(text) 63 | 64 | return fore_color + ' - ' + dt + ' - ' + text 65 | 66 | def color_print(msg, color="WHITE"): 67 | fore_color = getattr(Fore, color.upper()) 68 | print(fore_color + msg) 69 | 70 | def log_with_color(level): 71 | """ log with color by different level 72 | """ 73 | def wrapper(text): 74 | dt = time.strftime("%Y-%m-%d %H:%M:%S") 75 | color = log_colors_config[level.upper()] 76 | getattr(logging, level.lower())(coloring(dt,text, color)) 77 | 78 | return wrapper 79 | 80 | log_debug = log_with_color("debug") 81 | log_info = log_with_color("info") 82 | log_warning = log_with_color("warning") 83 | log_error = log_with_color("error") 84 | log_critical = log_with_color("critical") 85 | -------------------------------------------------------------------------------- /proxy/mathrandom.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | 5 | """ 6 | 随机数类 7 | """ 8 | import random 9 | 10 | 11 | """ generated source for module MathRandomBACK """ 12 | class MathRandom(object): 13 | """ generated source for class MathRandomBACK """ 14 | NOT_REPLACE = 0.35 15 | REPLACE_RESPONSE_JSON = 0.25 16 | REPLACE_RESPONSE_STR = 0.1 17 | REPLACE_RESPONSE_LIST = 0.05 18 | DELAY_RESPONES_TIME = 0.30 19 | REPLACE_STATUS_CODE = 0.04 20 | 21 | def PercentageRandom(self): 22 | """ generated source for method PercentageRandom """ 23 | randomNumber = float() 24 | randomNumber = random.random() 25 | if randomNumber >= 0 and randomNumber <= self.NOT_REPLACE: 26 | return 0 27 | elif randomNumber >= self.NOT_REPLACE / 100 and randomNumber <= self.NOT_REPLACE + self.REPLACE_RESPONSE_JSON: 28 | return 1 29 | elif randomNumber >= self.NOT_REPLACE + self.REPLACE_RESPONSE_JSON and randomNumber <= self.NOT_REPLACE + self.REPLACE_RESPONSE_JSON + self.REPLACE_RESPONSE_STR: 30 | return 2 31 | elif randomNumber >= self.NOT_REPLACE + self.REPLACE_RESPONSE_JSON + self.REPLACE_RESPONSE_STR and randomNumber <= self.NOT_REPLACE + self.REPLACE_RESPONSE_JSON + self.REPLACE_RESPONSE_STR + self.REPLACE_RESPONSE_LIST: 32 | return 3 33 | elif randomNumber >= self.NOT_REPLACE + self.REPLACE_RESPONSE_JSON + self.REPLACE_RESPONSE_STR + self.REPLACE_RESPONSE_LIST and randomNumber <= self.NOT_REPLACE + self.REPLACE_RESPONSE_JSON + self.REPLACE_RESPONSE_STR + self.REPLACE_RESPONSE_LIST + self.DELAY_RESPONES_TIME: 34 | return 4 35 | elif randomNumber >= self.NOT_REPLACE + self.REPLACE_RESPONSE_JSON + self.REPLACE_RESPONSE_STR + self.REPLACE_RESPONSE_LIST + self.DELAY_RESPONES_TIME and randomNumber <= self.NOT_REPLACE + self.REPLACE_RESPONSE_JSON + self.REPLACE_RESPONSE_STR + self.REPLACE_RESPONSE_LIST + self.DELAY_RESPONES_TIME + self.REPLACE_STATUS_CODE: 36 | return 5 37 | elif randomNumber >= self.NOT_REPLACE + self.REPLACE_RESPONSE_JSON + self.REPLACE_RESPONSE_STR + self.REPLACE_RESPONSE_LIST + self.DELAY_RESPONES_TIME + self.REPLACE_STATUS_CODE and randomNumber <= self.NOT_REPLACE + self.REPLACE_RESPONSE_JSON + self.REPLACE_RESPONSE_STR + self.REPLACE_RESPONSE_LIST + self.DELAY_RESPONES_TIME + self.REPLACE_STATUS_CODE: 38 | return 6 39 | return -1 40 | 41 | @classmethod 42 | def main(cls, args): 43 | """ generated source for method main """ 44 | from collections import Counter 45 | a_list = [] 46 | for line in range(100): 47 | a_list.append(MathRandom().PercentageRandom()) 48 | result = Counter(a_list) 49 | print(result) 50 | 51 | 52 | 53 | def get_random_list(self,list): 54 | ''' 55 | 列表中随机返回一个 56 | :param list: 57 | :return: 58 | ''' 59 | return random.choice(list) 60 | 61 | 62 | 63 | 64 | if __name__ == '__main__': 65 | import sys 66 | MathRandom.main(sys.argv) 67 | 68 | 69 | -------------------------------------------------------------------------------- /proxy/parserjson.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | 解析json数据 6 | """ 7 | 8 | from __future__ import print_function 9 | from mathrandom import MathRandom 10 | from jsonpath_rw import jsonpath, parse 11 | import json,re 12 | import logger 13 | logger.setup_logger('DEBUG') 14 | 15 | JSON_DATA_VARNAME = 'json_data' # 存在json数据的变量名称 16 | data_struct_list = [] # 用于存放所有 json 元素路径,形如 json_data[0]["data"][0]["components"][0]["enabled"] 17 | data_struct_link = 'json_data' # 用于临时存放单条json 元素路径(的一部分) 18 | 19 | def modify_deep_dict(new_value, json_path, json_dict): 20 | if "." in json_path: 21 | json_path_list = [] 22 | for path in str(json_path).split("."): 23 | if "[" and "]" in path: 24 | value_1 = path.split('[')[0] 25 | value_2 = path.split('[')[1].replace(']', '') 26 | json_path_list.append(value_1) 27 | json_path_list.append(int(value_2)) 28 | else: 29 | json_path_list.append(path) 30 | for path_str in json_path_list: 31 | get_dict(path_str, json_dict) 32 | else: 33 | json_dict[json_path] = new_value 34 | dict(json_dict).update() 35 | return json_dict 36 | 37 | 38 | def get_dict_value(new_value, json_path_list, json_dict): 39 | for path_str in json_path_list: 40 | if type(json_dict) == dict or type(json_dict) == list: 41 | new_dict = json_dict[path_str] 42 | print(new_dict) 43 | if type(new_dict) == dict or type(new_dict) == list: 44 | json_path_list.remove(path_str) 45 | print("current list size:{}".format(json_path_list.__len__())) 46 | print("current list :{}".format(json_path_list)) 47 | if json_path_list.__len__() > 0: 48 | get_dict_value(new_value, json_path_list, new_dict) 49 | else: 50 | break 51 | else: 52 | print(json_dict) 53 | json_dict = new_value 54 | dict(json_dict).update() 55 | break 56 | 57 | 58 | def dict_generator(indict, pre=None): 59 | ''' 60 | 递归生成所有的jsonpath路径 61 | :param indict: 62 | :param pre: 63 | :return: 64 | ''' 65 | pre = pre[:] if pre else [] 66 | if isinstance(indict, dict): 67 | for key, value in indict.items(): 68 | if isinstance(value, dict): 69 | if len(value) == 0: 70 | yield pre + [key, '{}'] 71 | else: 72 | for d in dict_generator(value, pre + [key]): 73 | yield d 74 | elif isinstance(value, list): 75 | if len(value) == 0: 76 | yield pre + [key, '[]'] 77 | else: 78 | for index,v in enumerate(value): 79 | for d in dict_generator(v, pre + [key + "[{}]".format(index)]): 80 | yield d 81 | elif isinstance(value, tuple): 82 | if len(value) == 0: 83 | yield pre + [key, '()'] 84 | else: 85 | for v in value: 86 | for d in dict_generator(v, pre + [key]): 87 | yield d 88 | else: 89 | yield pre + [key, value] 90 | else: 91 | yield indict 92 | 93 | 94 | 95 | def get_jsonpath_list(sJOSN): 96 | ''' 97 | 生成递归jsonpath列表 98 | :return: 99 | ''' 100 | jsonpath_list = [] 101 | sValue = json.dumps(sJOSN) 102 | for i in dict_generator(sJOSN): 103 | get_json_path = '.'.join(i[0:-1]) 104 | json_path_value = i[-1] 105 | logger.log_debug("get json path is:{}".format(get_json_path)) 106 | logger.log_debug("get json path value:{}".format(json_path_value)) 107 | jsonpath_list.append(get_json_path) 108 | return jsonpath_list 109 | 110 | 111 | 112 | 113 | def parse_sub_expr(sub_expr): 114 | ''' 115 | 解析字表达式-元素路径的组成部分 116 | :param sub_expr: 117 | :return: 118 | ''' 119 | RIGHT_INDEX_DEFAULT = '200000000' # 右侧索引的默认值 未指定右侧索引时使用,形如 key[2:]、key[:] 120 | result = re.findall('\[.+\]', sub_expr) 121 | if result: # 如果子表达式为数组,形如 [1]、key[1]、 key[1:2]、 key[2:]、 key[:3]、key[:] 122 | array_part = result[0] 123 | array_part = array_part.lstrip('[').rstrip(']') 124 | key_part = sub_expr[:sub_expr.index('[')] 125 | if key_part == '$': # 如果key为 $ ,为根,替换为数据变量 json_data 126 | key_part = JSON_DATA_VARNAME 127 | elif key_part == '*': 128 | key_part == '\[.+\]' # 如果key为 * ,替换为 \[\.+\] 以便匹配 ["key1"]、["key2"]、…… 129 | else: 130 | key_part = '\["%s"\]' % key_part 131 | if array_part == '*': # 如果数组索引为 * ,替换为 \[\d+\] 以便匹配 [0]、[1]、…… 132 | array_part = '\[\d+\]' 133 | else: 134 | array_part_list = array_part.replace(' ', '').split(':') 135 | left_index = array_part_list[0:1] 136 | right_index = array_part_list[1:] 137 | if left_index: 138 | left_index = left_index[0] 139 | if not (left_index or left_index.isdigit()): # 为空字符串、非数字 140 | left_index = '0' 141 | else: 142 | left_index = '0' 143 | if right_index: 144 | right_index = right_index[0] 145 | if not (right_index or right_index.isdigit()): 146 | right_index = RIGHT_INDEX_DEFAULT # 一个比较大的值, 147 | array_part = left_index + '-' + right_index 148 | else: 149 | array_part = left_index 150 | array_part = '\[[%s]\]' % array_part # 数组索引设置为 \[[n-m]\],以便匹配[n],[n+1], ……,[m-1] 151 | return key_part + array_part 152 | elif sub_expr == '*': 153 | sub_expr = '\[.+\]' 154 | elif sub_expr == '$': 155 | sub_expr = JSON_DATA_VARNAME 156 | else: 157 | sub_expr = '\["%s"\]' % sub_expr 158 | return sub_expr 159 | 160 | 161 | 162 | 163 | def parse_json(json_data, data_struct_link): 164 | ''' 165 | 递归解析json数据结构,存储元素的路径 166 | :param json_data: 167 | :param data_struct_link: 168 | :return: 169 | ''' 170 | if type(json_data) == type({}): # 字典类型 171 | keys_list = json_data.keys() 172 | for key in keys_list: 173 | temp_data_struct_link = data_struct_link + '["%s"]' % key 174 | if type(json_data[key]) not in [type({}), type([])]: # key对应的value值既不是数组,也不是字典 175 | data_struct_list.append(temp_data_struct_link) 176 | else: 177 | parse_json(json_data[key], temp_data_struct_link) 178 | elif type(json_data) == type([]): # 数组类型 179 | array_length = len(json_data) 180 | for index in range(0, array_length): 181 | temp_json_data = json_data[index] 182 | keys_list = temp_json_data.keys() 183 | for key in keys_list: 184 | temp_data_struct_link = data_struct_link + '[%s]["%s"]' % (str(index), key) 185 | if type(temp_json_data[key]) not in [type({}), type([])]: # key对应的value值既不是数组,也不是字典 186 | data_struct_list.append(temp_data_struct_link) 187 | else: 188 | parse_json(temp_json_data[key], temp_data_struct_link) 189 | 190 | 191 | 192 | def edit_dict(expr,new_value,json_data): 193 | ''' 194 | 修改更改键的值 195 | :return: 196 | ''' 197 | expr_path = expr.split(".") 198 | edit_key = expr_path[-1] 199 | expr = expr.replace("." + edit_key,'') 200 | # 解析表达式为正则表达式 201 | parse_json(json_data, data_struct_link) 202 | re_pattern = '' 203 | 204 | for sub_expr in expr.split('.'): 205 | re_pattern += parse_sub_expr(sub_expr) 206 | logger.log_debug('\n元素路径jsonpath表达式为:%s' % expr) 207 | logger.log_debug('元素路径正则表达式re pattern为:%s' % re_pattern) 208 | logger.log_debug('\njsonpath 匹配结果如下:') 209 | re_pattern = re.compile(re_pattern) 210 | target_set = set() # 匹配结果会有重复值,所以采用集合 211 | for item in data_struct_list: 212 | results = re.findall(re_pattern, item) 213 | for result in results: 214 | target = item[0:item.index(result) + len(result)] 215 | target_set.add(target) 216 | 217 | # 通过匹配提取的目标结果,操作json串 218 | for item in target_set: 219 | target = eval(item) 220 | if type(target) == type({}): # 如果为字典 221 | # 更改键的值 222 | logger.log_debug("更改键:" + edit_key) 223 | target[edit_key] = new_value 224 | elif type(target) == type([]): 225 | # 暂不实现 226 | pass 227 | logger.log_debug('重新生成的新json数据:\n{}'.format(json_data)) 228 | return json_data 229 | 230 | 231 | 232 | def del_dict(expr,json_data): 233 | ''' 234 | 删除键的值 235 | :return: 236 | ''' 237 | expr_path = expr.split(".") 238 | del_key = expr_path[-1] 239 | expr = expr.replace("." + del_key,'') 240 | # 解析表达式为正则表达式 241 | parse_json(json_data, data_struct_link) 242 | re_pattern = '' 243 | for sub_expr in expr.split('.'): 244 | re_pattern += parse_sub_expr(sub_expr) 245 | logger.log_debug('\n元素路径jsonpath表达式为:%s' % expr) 246 | logger.log_debug('元素路径正则表达式re pattern为:%s' % re_pattern) 247 | logger.log_debug('\njsonpath 匹配结果如下:') 248 | re_pattern = re.compile(re_pattern) 249 | target_set = set() # 匹配结果会有重复值,所以采用集合 250 | for item in data_struct_list: 251 | results = re.findall(re_pattern, item) 252 | for result in results: 253 | target = item[0:item.index(result) + len(result)] 254 | target_set.add(target) 255 | # 通过匹配提取的目标结果,操作json串 256 | for item in target_set: 257 | target = eval(item) 258 | if type(target) == type({}): # 如果为字典 259 | logger.log_debug("删除键:" + del_key) 260 | del target[del_key] 261 | elif type(target) == type([]): 262 | # 暂不实现 263 | pass 264 | logger.log_debug('重新生成的新json数据:\n{}'.format(json_data)) 265 | return json_data 266 | 267 | 268 | 269 | 270 | def drop_list(expr,json_data): 271 | ''' 272 | 改成空列表 273 | :return: 274 | ''' 275 | # 解析表达式为正则表达式 276 | expr_path = expr.split(".") 277 | del_key = expr_path[-1] 278 | expr = expr.replace("." + del_key, '') 279 | parse_json(json_data, data_struct_link) 280 | re_pattern = '' 281 | for sub_expr in expr.split('.'): 282 | re_pattern += parse_sub_expr(sub_expr) 283 | logger.log_debug('\n元素路径jsonpath表达式为:%s' % expr) 284 | logger.log_debug('元素路径正则表达式re pattern为:%s' % re_pattern) 285 | logger.log_debug('\njsonpath 匹配结果如下:') 286 | re_pattern = re.compile(re_pattern) 287 | target_set = set() # 匹配结果会有重复值,所以采用集合 288 | for item in data_struct_list: 289 | results = re.findall(re_pattern, item) 290 | for result in results: 291 | target = item[0:item.index(result) + len(result)] 292 | target_set.add(target) 293 | # 通过匹配提取的目标结果,操作json串 294 | for item in target_set: 295 | target = eval(item) 296 | print(target) 297 | if type(target) == type({}): # 如果为字典 298 | if '[*]' in del_key: 299 | target[del_key.replace('[*]','')] = [] 300 | else: 301 | target[del_key] = [] 302 | elif type(target) == type([]): 303 | # 暂不实现 304 | pass 305 | logger.log_debug('重新生成的新json数据:\n{}'.format(json_data)) 306 | return json_data 307 | 308 | 309 | 310 | 311 | 312 | if __name__ == "__main__": 313 | json_data = { 314 | "base_config":{ 315 | "enforce":{ 316 | "value":"0", 317 | "inherit":"0", 318 | "global":"0" 319 | }, 320 | "modify":{ 321 | "value":"0", 322 | "inherit":"0", 323 | "global":"0" 324 | } 325 | }, 326 | "safe_control_list":{ 327 | "list":[ 328 | { 329 | "gid":"0", 330 | "gname":"全网计算机", 331 | "isactive":"1", 332 | "rule_id":"0", 333 | "rule_name":"请选择规则", 334 | "time_range":"所有时间", 335 | "time_range_id":"1", 336 | "policy_tpl":"33", 337 | "policy_tpl_id":"17", 338 | "isonline":"3", 339 | "priority":"88888" 340 | }, 341 | { 342 | "gid": "1", 343 | "gname": "全网计算机", 344 | "isactive": "1", 345 | "rule_id": "0", 346 | "rule_name": "请选择规则", 347 | "time_range": "所有时间", 348 | "time_range_id": "1", 349 | "policy_tpl": "33", 350 | "policy_tpl_id": "17", 351 | "isonline": "3", 352 | "priority": "99999" 353 | } 354 | ] 355 | } 356 | } 357 | # drop } _list(expr=expr, json_data=self.rep_json) 358 | # ] 359 | # } 360 | # 361 | # expr = 'safe_control_list.list[*]' 362 | # new_data = drop_list(expr=expr,json_data=json_data) 363 | # 364 | # print(new_data) 365 | 366 | 367 | 368 | 369 | # del_dict(expr=expr,json_data=json_data) 370 | 371 | # for index in range(1): 372 | # json_path_list = get_jsonpath_list(json_data) 373 | # expr = (MathRandom().get_random_list(json_path_list)) 374 | # print(expr) 375 | # print(edit_dict(expr=expr,new_value="555555555555",json_data=json_data)) 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | -------------------------------------------------------------------------------- /proxy/proxyrule.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | 5 | """ 6 | 使用mitmproxy的rule的规则 7 | @author:xinxi 8 | """ 9 | 10 | import json,time 11 | from mathrandom import MathRandom 12 | from parserjson import * 13 | import random 14 | import logger 15 | logger.setup_logger('INFO') 16 | 17 | class ProxyRule(): 18 | 19 | def __init__(self,rep_json): 20 | self.rep_json = eval(rep_json) 21 | 22 | 23 | 24 | def get_defult_data(self): 25 | return '{"h":{"c":0,"e":"","t":0.004232388,"s":1558015779},"c":{"data":{"status":1,"online_num":0,"reservation_num":0,"title":"直播测试22222","room_id":205,"intro":"test","starttime":1554972060,"starttime_desc":"周四16:41","duration":110,"endtime":1554978660,"id":205,"type":0,"log_id":205,"log_type":"igettv"}}}' 26 | 27 | 28 | def get_edit_str(self): 29 | ''' 30 | 修改后的字典 31 | :return: 32 | ''' 33 | json_path_list = get_jsonpath_list(self.rep_json) 34 | logger.log_debug("{}".format(json_path_list)) 35 | expr = MathRandom().get_random_list(json_path_list) 36 | logger.log_debug("{}".format(expr)) 37 | new_json_data = edit_dict(expr=expr, new_value=self.get_random_string(), json_data=self.rep_json) 38 | logger.log_debug("{}".format(new_json_data)) 39 | return json.dumps(new_json_data) 40 | 41 | 42 | def get_del_str(self): 43 | ''' 44 | 删除后的字典 45 | :return: 46 | ''' 47 | json_path_list = get_jsonpath_list(self.rep_json) 48 | logger.log_debug("{}".format(json_path_list)) 49 | expr = MathRandom().get_random_list(json_path_list) 50 | logger.log_debug("{}".format(expr)) 51 | new_json_data = del_dict(expr=expr, json_data=self.rep_json) 52 | logger.log_debug("{}".format(new_json_data)) 53 | return json.dumps(new_json_data) 54 | 55 | 56 | 57 | def not_intercept(self): 58 | ''' 59 | 不篡改响应,直接返回结果 60 | :return: 61 | ''' 62 | logger.log_info("not_intercept") 63 | return json.dumps(self.rep_json) 64 | 65 | 66 | def intercept_respones_json(self): 67 | ''' 68 | 对返回的json数据做随机做增删操作 69 | :return: 70 | ''' 71 | logger.log_info("intercept_respones_json") 72 | return json.dumps(self.rep_json) 73 | 74 | 75 | 76 | def intercept_respones_str(self): 77 | ''' 78 | 对返回结果中的某个字段所增删改操作 79 | :return: 80 | ''' 81 | logger.log_info("intercept_respones_str") 82 | event_list = [self.get_edit_str(), self.get_del_str()] 83 | event = MathRandom().get_random_list(event_list) 84 | return event 85 | 86 | 87 | def intercept_respones_list(self): 88 | ''' 89 | 多返回结果中的数组做增删改操作 90 | :return: 91 | ''' 92 | path_list = [] 93 | logger.log_debug("replace_respones_list") 94 | json_path_list = get_jsonpath_list(self.rep_json) 95 | logger.log_debug("{}".format(json_path_list)) 96 | for line in json_path_list: 97 | if "[" and "]" in str(line): 98 | #logger.log_info("intercept line is:{}".format(line)) 99 | path_list.append(line) 100 | if path_list.__len__() != 0: 101 | expr = MathRandom().get_random_list(path_list) 102 | expr = str(expr).split('[')[0] 103 | logger.log_debug("{}".format(expr)) 104 | new_json_data = drop_list(expr=expr, json_data=self.rep_json) 105 | logger.log_debug("{}".format(new_json_data)) 106 | return json.dumps(new_json_data) 107 | else: 108 | return json.dumps(self.rep_json) 109 | 110 | 111 | 112 | 113 | 114 | def delay_respones_time(self): 115 | ''' 116 | 对返回数据做延迟返回 117 | :return: 118 | ''' 119 | random_time = random.randint(100,1000) 120 | time.sleep(random_time/1000) 121 | logger.log_info("delay_respones_time:{}ms".format(random_time)) 122 | return json.dumps(self.rep_json) 123 | 124 | 125 | 126 | @staticmethod 127 | def intercept_status_code(): 128 | ''' 129 | 对返回的状态码做随机修改 130 | :return: 131 | ''' 132 | code_list = [404,500,503,302,301] 133 | random_code = MathRandom().get_random_list(code_list) 134 | logger.log_info("replace_status_code:{}".format(random_code)) 135 | return random_code 136 | 137 | 138 | def get_random_string(self): 139 | ''' 140 | 获取随机字符串 141 | :return: 142 | ''' 143 | string_list = ['','超长字符串' * 100, self.special_string()] 144 | string = MathRandom().get_random_list(string_list) 145 | return string 146 | 147 | 148 | def special_string(self): 149 | ''' 150 | 随机10位特殊字符 151 | :return: 152 | ''' 153 | list = [chr(i) for i in range(65, 91)] + [chr(i) for i in range(97, 123)] + [str(i) for i in range(10)] + ['.','-','~','_'] 154 | # 大写字母+小写字母+数字 +特殊字符.-_~ 155 | num = random.sample(list, 10) 156 | str1 = '' 157 | value = str1.join(num) 158 | logger.log_info("special_string is:{}".format(value)) 159 | return value 160 | 161 | 162 | 163 | def get_random_event(self): 164 | ''' 165 | 获取随机事件 166 | :param num: 167 | :return: 168 | ''' 169 | num = MathRandom().PercentageRandom() 170 | for case in switch(num): 171 | if case(0): 172 | self.not_intercept() 173 | break 174 | if case(1): 175 | self.intercept_respones_json() 176 | break 177 | if case(2): 178 | self.intercept_respones_str() 179 | break 180 | if case(3): 181 | self.intercept_respones_list() 182 | break 183 | if case(4): 184 | self.delay_respones_time() 185 | break 186 | if case(4): 187 | self.intercept_status_code() 188 | break 189 | if case(): 190 | self.not_intercept() 191 | 192 | 193 | 194 | class switch(object): 195 | def __init__(self, value): 196 | self.value = value 197 | self.fall = False 198 | 199 | def __iter__(self): 200 | """Return the match method once, then stop""" 201 | yield self.match 202 | raise StopIteration 203 | 204 | def match(self, *args): 205 | """Indicate whether or not to enter a case suite""" 206 | if self.fall or not args: 207 | return True 208 | elif self.value in args: # changed for v1.5, see below 209 | self.fall = True 210 | return True 211 | else: 212 | return False 213 | 214 | 215 | -------------------------------------------------------------------------------- /proxy/proxyserver.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | 5 | """ 6 | 使用mitmproxy代理工具篡改请求 7 | """ 8 | 9 | import mitmproxy.http 10 | from mitmproxy import ctx 11 | import json, time, os 12 | 13 | from constant import split_joint 14 | from proxyrule import ProxyRule 15 | from mathrandom import MathRandom 16 | from filetools import * 17 | 18 | project_path = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) 19 | now = time.strftime("%Y%m%d%H%M%S", time.localtime()) + "_intercept.log" 20 | save_log_file = os.path.join(project_path, now) 21 | 22 | 23 | def request(flow: mitmproxy.http.HTTPFlow): 24 | request = flow.request 25 | ctx.log.info("========================== intercept request start ==========================") 26 | ctx.log.info("========================== host is:{} ========================== ".format(request.host)) 27 | ctx.log.info("========================== url is:{} ========================== ".format(request.pretty_url)) 28 | ctx.log.info("========================== method is:{} ========================== ".format(request.method)) 29 | ctx.log.info("========================== body is:{} ========================== ".format(request.get_text())) 30 | ctx.log.info("========================== intercept request end ==========================") 31 | 32 | 33 | def response(flow: mitmproxy.http.HTTPFlow): 34 | ''' 35 | 篡改response返回数据 36 | :param flow: 37 | :return: 38 | ''' 39 | is_mock = True 40 | 41 | black_list = ["png", "jpg", "js", "css", "html", 'img', 'cdn'] 42 | 43 | for black_str in black_list: 44 | if black_str in flow.request.url: 45 | ctx.log.info("========================== not necessary intercept response ==========================") 46 | is_mock = False 47 | break 48 | 49 | if int(flow.response.status_code) == 200 and is_mock == True: 50 | 51 | original_data = (flow.response.text) 52 | 53 | if original_data.startswith("{") and original_data.endswith("}"): 54 | # get_mock_data = ProxyRule(original_data).get_random_event() 55 | get_mock_data = ProxyRule(original_data).intercept_respones_str() 56 | ctx.log.info("========================== intercept response start ==========================") 57 | # ctx.log.info("========================== mock after data:{} ==========================".format(original_data)) 58 | # ctx.log.info("========================== mock before data:{} ==========================".format(get_mock_data)) 59 | flow.response.set_text(get_mock_data) 60 | ctx.log.info(flow.response.text) 61 | ctx.log.info("========================== intercept response end ==========================") 62 | spend_time = int((flow.response.timestamp_end - flow.request.timestamp_start) * 1000) 63 | req_url = str(flow.request.url) 64 | 65 | req_method = str(flow.request.method) 66 | resp_status_code = str(flow.response.status_code) 67 | spend_time_str = str(spend_time) 68 | original_data_str = str(original_data) 69 | get_mock_data_str = str(get_mock_data) 70 | content={"param_len":" ","param_value":" "} 71 | param_value = req_url + split_joint + req_method + split_joint + resp_status_code + split_joint \ 72 | + spend_time_str + split_joint + original_data_str + split_joint + get_mock_data_str 73 | req_url_len = len(req_url) 74 | req_method_len = len(req_method) 75 | resp_status_code_len = len(resp_status_code) 76 | spend_time_str_len = len(spend_time_str) 77 | original_data_str_len = len(original_data_str) 78 | get_mock_data_str_len = len(get_mock_data_str) 79 | content["param_len"] = [req_url_len, req_method_len, resp_status_code_len, spend_time_str_len, 80 | original_data_str_len, get_mock_data_str_len] 81 | content["param_value"]=param_value 82 | 83 | ctx.log.info("========================== write data to file==========================") 84 | 85 | write_file(save_log_file, str(content), is_cover=False) 86 | -------------------------------------------------------------------------------- /proxy/run.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | 5 | """ 6 | 运行入口 7 | """ 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /proxy/script.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | 5 | 6 | def request(flow): 7 | flow.request.headers['User-Agent'] = 'MitmProxy' 8 | print(flow.request.headers) -------------------------------------------------------------------------------- /proxy/templates/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | TestReport 5 | 129 | 130 | 131 |

Test Report: {{html_report_name}}

132 | 133 |

Details

134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | {% for record in records %} 142 | 143 | 145 | 146 | 162 | 163 | {% endfor %} 164 |
NameStatusResponse TimeDetail
{{record.name}} 144 | {{record.status}}{{ '%0.1f'| format(record.response_time_ms|float) }} ms 147 | data 148 | 159 | 160 | 161 |
165 | 166 | -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | 2 | 3 | source tutorial-env/bin/activate 4 | 5 | cd dumphrun 6 | 7 | mitmweb -s proxyserver.py -------------------------------------------------------------------------------- /报告1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xinxi1990/mitmfuzz/807f105788620b5322e1c59db3c46b816a59c24a/报告1.jpg -------------------------------------------------------------------------------- /报告2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xinxi1990/mitmfuzz/807f105788620b5322e1c59db3c46b816a59c24a/报告2.jpg --------------------------------------------------------------------------------