抓包与mock实战3-mitmproxy

mitmproxy扩展机制

抓包

map local

def request(flow: http.HTTPFlow) -> None:
    # pretty_url takes the "Host" header of the request into account, which
    # is useful in transparent mode where we usually only have the IP otherwise.

    if "quote.json" in flow.request.pretty_url and "x=" in flow.request.pretty_url:
        with open("/Users/seveniruby/ke/lagou_1/mitmproxy/quote.json") as f:
            flow.response = http.HTTPResponse.make(
                200,  # (optional) status code
                f.read(),  # (optional) content
                {"Content-Type": "application/json"}  # (optional) headers
            )

rewrite

import json


def response(flow):
    if "quote.json" in flow.request.pretty_url and "x=" in flow.request.pretty_url:
        data = json.loads(flow.response.content)
        data['data']['items'][0]['quote']['name'] = data['data']['items'][0]['quote']['name'] + " field"
        flow.response.text = json.dumps(data)

自动生成等价类数据

import json

from mitmproxy import http

url_index = dict()
arrays = [-5, -3, -1, 0, 1, 3, 5, 100]


def response(flow: http.HTTPFlow) -> None:
    # if "Content-Type" in flow.response.headers.keys() and \
    #         "json" in flow.response.headers['Content-Type']:
    if "quote.json" in flow.request.pretty_url and "x=" in flow.request.pretty_url:
        url = flow.request.url.split('.json')[0]
        if url not in url_index.keys():
            url_index[url] = 0
        else:
            url_index[url] += 1

        # 去等价类中的某一个,根据访问次数循环使用
        seed = url_index[url] % len(arrays)
        print(seed)
        data = json.loads(flow.response.text)
        # 对数据进行批量修改
        data_new = json_travel(data, num=arrays[seed])
        json_new = json.dumps(data_new, indent=2)
        flow.response.text = json_new


def json_travel(data, array=None, text=1, num=1):
    data_new = None
    # 如果是词典,对词典进行遍历
    if isinstance(data, dict):
        data_new = dict()
        for k, v in data.items():
            data_new[k] = json_travel(v, array, text, num)

    # 如果是列表,对列表的每一项进行遍历
    elif isinstance(data, list):
        data_new = list()
        for item in data:
            item_new = json_travel(item, array, text, num)
            if array is None:
                data_new.append(item_new)
            elif len(data_new) < array:
                data_new.append(item_new)
            else:
                pass
    # 如果是字符串
    elif isinstance(data, str):
        data_new = data * text
    # 如果是int或者float这样的数字
    elif isinstance(data, int) or isinstance(data, float):
        #对数字进行一个乘积计算
        data_new = data * num
    # 其他数据类型保持原样
    else:
        data_new = data
    return data_new


def test_json_travel():
    with open("demo.json") as f:
        data = json.load(f)
        print(json_travel(data, array=0))
        print(json_travel(data, text=5))
        print(json_travel(data, num=5))

生成用例

拔高部分,不做要求,等学完下周的接口测试框架再回头研究吧。

import os
import sys
from mitmproxy import http

addon_dir = os.path.dirname(os.path.dirname(__file__))
sys.path.append(addon_dir)
from test_proxy.template import Template


def response(flow: http.HTTPFlow):
    if ".json" in flow.request.pretty_url:
        method = flow.request.method
        url = flow.request.pretty_url.split('?')[0]
        params = [{k: v} for k, v in flow.request.query.fields]
        cookies = [{k: v} for k, v in flow.request.cookies.fields]
        data = {
            "method": method.__repr__(),
            "url": url.__repr__(),
            "params": params,
            "cookies": cookies
        }
        print(Template.render(addon_dir + "/test_proxy/test_http.mustache", data))

生成的用例模板

import json
from pprint import pprint

import requests
import yaml


class TestHttp:
    def setup(self):
        pass

    def test_request(self):
        r=requests.request(
            'GET',
            url='https://stock.xueqiu.com/v5/stock/stare/notice.json',
            params={
                    {'_t': '1UNKNOWN06f8104c8f011126b0134ad0b793f1a0.2280621283.1589631314152.1589633999816'}
                    {'_s': 'eb1a7a'}
                    {'x': '0.94'}
                    {'stare_type': 'dynamic,event'}
            },
            cookies={
                    {'xq_a_token': 'f4855c806b2fa994489ea1ec96c74f31ed6b1d21'}
                    {'xq_id_token': 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJ1aWQiOjIyODA2MjEyODMsImlzcyI6InVjIiwiZXhwIjoxNTkwMTUzMzU5LCJjdG0iOjE1ODc1NjEzNTkyOTgsImNpZCI6Ikp0WGJhTW43ZVAifQ.YdBlGNRLAaX69EJpdZEFoY1ghJaoudBKJt-Pjd0yY2e7GVcXYRVlmXNS5wI7cb-08fy8Js4aperQoszwaoLzMy4SSXmzCmc2CC96ygp3rzEGggrlMhtVeTxoDIxcevjGnYDmozJHk6LcAGJIP7j8ewgsvwRVszPoJ2Jj-HBSp7ZsByUX82HIsL61iObhMCCVj0ANXDlD2CRqMaWyuv5Q8qYtGqXdn3abliLwai5fUjdKPpafuBahnGScOBP6XyUbsncXG_l35sWaJGinigV3LbH7RHCmFnl16V8eCczXLEUKjOzR9NmVaF61pPYh5IA9f6pKlhqazCCW-GFScYyvRg'}
                    {'u': '2280621283'}
                    {'session_id': ''}
                    {'xid': '0'}
            }
        )
        assert r.status_code == 200

课后作业

拔高部分,做不出来也不做严格要求,试着挑战下,可以在一个月内完成。

对雪球的quote.json数据的股票名字进行多种等价类生成,假设里面有很多股票。

  • 对第一个股票保持原样
  • 对第二个股票名字加长一倍
  • 对第三个股票名字变成空
  • 对第四只股票名字变成超长字符
  • 以及其他等价类 中英文、特殊符号等
  • 对股票的价格也自动进行等价类生成

考察的是技术手段,等价类可以不用太多

mitmdump执行的py,怎么在本地进行debug调试输出到pycharm里面?