zoukankan      html  css  js  c++  java
  • MitmProxy使用:流量劫持与入库,流量回放

    流量截取与入库

    我们需要先定义和初始化流量截取后存储的表结构,这里我们采用 peewee 这个 ORM 库,进行操作。
    更多操作可参考:
    http://docs.peewee-orm.com/en/latest/peewee/quickstart.html

    from peewee import *
    import datetime
    //可以考虑通过 docker 快速搭建 Mysql 服务
    db = MySQLDatabase("mitmproxy", host="172.17.0.2", port=3306, user="root", passwd="xxxx")
    db.connect()
    
    class HttpRecords(Model):
        //定义了三个字段,id, http 请求记录,时间戳
        id = BigAutoField(primary_key=True)
        httprecord = TextField()
        timestamps = DateTimeField(default=datetime.datetime.utcnow)
    
        class Meta:
            database = db

    接下来编写我们的插件脚本,用于拦截请求,并且写入到我们定义好的数据库表中,如下:

    //关注接口(get 请求)
    get_url = "https://frodo.douban.com/api/v2/user/91807076/following"
    
    //发表说说的接口(post 请求)
    post_url = "https://frodo.douban.com/api/v2/status/create_status?loc_id=118282"
    httprecord = {}
    url_list = [get_url, post_url]
    
    def parser_data(query):
        data = {}
        for key, value in query.items():
            data[key] = value
        return data
    
    class HttpRecord:
        @concurrent
        def request(self, flow: http.HTTPFlow):
            //这里可以根据自身业务需求,拦截特定域名下的请求(这里为了方便演示,特地指定了两个接口地址)
            if flow.request.pretty_url.startswith(get_url):
                httprecord['method'] = flow.request.method
                httprecord['scheme'] = flow.request.scheme
                httprecord['url'] = flow.request.pretty_url
                httprecord['request_headers'] = {}
                for item in flow.request.headers:
                    httprecord['request_headers'][item] = flow.request.headers[item]
                httprecord['get_data'] = parser_data(flow.request.query)
                httprecord['post_data'] = parser_data(flow.request.urlencoded_form)
    
        @concurrent
        def response(self, flow: http.HTTPFlow):
            if flow.request.pretty_url.startswith(get_url):
                httprecord['status_code'] = flow.response.status_code
                httprecord['response_headers'] = {}
                for item in flow.response.headers:
                    httprecord['response_headers'][item] = flow.response.headers[item]
                httprecord['response_content'] = flow.response.get_text()
    
                # 插入数据库
                record = HttpRecords(httprecord=httprecord)
                record.save()
    
    addons = [
        HttpRecord()
    ]

    检查数据库表,看是否插入成功,如下:

    流量回放进行接口测试

    从数据库中查询请求记录,并按不同请求方法,e.g. get/post 进行分类;
    通过 request 网络请求库,进行重新回放请求接口;
    引入 Pytest 测试框架,加入断言,进行组织测试用例的执行,具体代码可参考如下:

    import demjson
    import requests
    from replay.httpmodel import HttpRecords
    import pytest
    
    class TestInterface:
        get_http = []
        post_http = []
        def setup_class(self):
            # 从数据库获取流量记录(前置处理操作)
            self.httprecords = HttpRecords.select()
            for item in self.httprecords:
                data = demjson.decode(item.httprecord)
                if data['method'] == "GET":
                    self.get_http.append(data)
                elif data['method'] == "POST":
                    self.post_http.append(data)
                else:
                    ...
            # 初始化请求 session
            self.session = requests.session()
    
        def testReplayGet(self):
            """
             测试回放 Get 请求
            """
            for i in range(len(self.get_http)):
                res = self.session.get(url=self.get_http[i]['url'], headers=self.get_http[i]['request_headers'], data=self.get_http[i]['get_data'])
                //这里主要是断言了响应状态码,在实际业务中,我们还需要断言返回格式及校验核心字段。
                assert res.status_code == 200
    
        def testRelayPost(self):
            """
            测试回放 Post 请求
            """
            for i in range(len(self.post_http)):
                res = self.session.post(url=self.post_http[i]['url'], headers=self.post_http[i]['request_headers'], data=self.post_http[i]['post_data'])
                assert res.status_code == 200
    
    if __name__ == '__main__':
        pytest.main(["--html=report.html --self-contained-html", "interfacereplay.py"])

    查看测试报告
    get 和 post 请求分别回放测试成功:

  • 相关阅读:
    [战略]当你收到面试通知后,如下的准备可以大大提升面试成功率
    tfzq & dml
    kjl & jsd(1yet)内存泄漏定位
    面试 sn (1yet) zk watcher原理
    thread.join的本质
    关于linux中的man
    linux 新手入门
    Linux 中如何卸载已安装的软件(转载)
    如何在Linux下创建与解压,安装zip, tar, tar.gz和tar.bz2文件
    Linux系统下如何查看及修改文件读写权限
  • 原文地址:https://www.cnblogs.com/-wenli/p/13940934.html
Copyright © 2011-2022 走看看