httprunner3源码解读(3)client.py

httprunner3源码解读(3)client.py源码目录结构ApiResponse这个类没啥好说的classApiResponse(Response):"""继承了requests模块中的Response类

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

源码目录结构

httprunner3源码解读(3)client.py
 

ApiResponse

这个类没啥好说的

class ApiResponse(Response):
    """
    继承了requests模块中的Response类,重写了里面的raise_for_status方法
    """
    def raise_for_status(self):
        if hasattr(self, "error") and self.error:
            raise self.error
        Response.raise_for_status(self)

 

get_req_resp_record

这个函数的功能是获取请求记录和响应记录,源码分为4段来看
 

第1段

def get_req_resp_record(resp_obj: Response) -> ReqRespData:
    """
    :param resp_obj: Response响应
    :return: 返回自定义的ReqResData模型类
    """

    def log_print(req_or_resp, r_type):
        """
        日志打印,格式为标准的json
        """
        msg = f"\n================== {r_type} details ==================\n"
        for key, value in req_or_resp.dict().items():
            # 如果value中还包含着dict或者list,就把value转成json格式
            if isinstance(value, dict) or isinstance(value, list):
                value = json.dumps(value, indent=4, ensure_ascii=False)

            msg += "{:<8} : {}\n".format(key, value)
        logger.debug(msg)

第1段代码就是定义了一个打印日志的函数,打印的日志解析为标准的json格式
 

第2段

# 记录实际请求信息(请求头、cookie信息、请求体)
    request_headers = dict(resp_obj.request.headers)
    request_cookies = resp_obj.request._cookies.get_dict()

    request_body = resp_obj.request.body
    if request_body is not None:
        try:
            request_body = json.loads(request_body)
        except json.JSONDecodeError:
            # str: a=1&b=2
            pass
        except UnicodeDecodeError:
            # bytes/bytearray: request body in protobuf
            pass
        except TypeError:
            # neither str nor bytes/bytearray, e.g. <MultipartEncoder>
            pass

        # lower_dict_keys的作用是将字典中的key大写转小写
        request_content_type = lower_dict_keys(request_headers).get("content-type")
        if request_content_type and "multipart/form-data" in request_content_type:
            # upload file type
            request_body = "upload file stream (OMITTED)"

    request_data = RequestData(
        method=resp_obj.request.method,
        url=resp_obj.request.url,
        headers=request_headers,
        cookies=request_cookies,
        body=request_body,
    )
    # 在debug模式下打印请求日志
    log_print(request_data, "request")

第2段代码是先获取request_headersrequest_cookiesrequest_body,然后将获取到的信息放入RequestData模型中,最后打印请求的信息
 

第3段

# 记录响应信息
    resp_headers = dict(resp_obj.headers)
    lower_resp_headers = lower_dict_keys(resp_headers)
    content_type = lower_resp_headers.get("content-type", "")

    if "image" in content_type:
        # response is image type, record bytes content only
        response_body = resp_obj.content
    else:
        try:
            # try to record json data
            response_body = resp_obj.json()
        except ValueError:
            # only record at most 512 text charactors
            resp_text = resp_obj.text
            response_body = omit_long_data(resp_text)

    response_data = ResponseData(
        status_code=resp_obj.status_code,
        cookies=resp_obj.cookies or {},
        encoding=resp_obj.encoding,
        headers=resp_headers,
        content_type=content_type,
        body=response_body,
    )

    # 在debug模式下打印响应日志
    log_print(response_data, "response")

第3段代码是获取resp_headerscontent_typeresponse_body,最后将这些数据都放入ResponseData模型类中,最后打印响应日志
 

第4段

req_resp_data = ReqRespData(request=request_data, response=response_data)
    return req_resp_data

最后这段就是将刚才的请求信息和响应信息全部放入ReqRespData模型中,最后get_req_resp_record函数返回的内容就是ReqRespData模型
 

HttpSession

requests.Session上进行了二次封装,该类包含4个方法,下面依次介绍
 

init

    def __init__(self):
        super(HttpSession, self).__init__()
        self.data = SessionData()

初始化方法,定义了data属性的默认值为SessionData模型,该模型包含了req_resps: List[ReqRespData] = []请求响应内容
 

update_last_req_resp_record

    def update_last_req_resp_record(self, resp_obj):
        """
        update request and response info from Response() object.
        """
        # TODO: fix
        self.data.req_resps.pop()
        self.data.req_resps.append(get_req_resp_record(resp_obj))

更新最新的请求响应记录,放入req_resps列表中
 

request

发送requests.Request请求,返回requests.Response响应,还做了以下事情

  • 1.设置了超时时间120s
  • 2.计算整个请求花费了多少时间
  • 3.定义了客户端ip地址和端口号、服务端ip地址和端口号
  • 4.计算了响应体的内容大小
  • 5.记录了消耗时间
  • 6.记录了request和response记录,包括重定向记录
     

_send_request_safe_mode

发送一个http请求,并捕获由于连接问题可能发生的任何异常

    def _send_request_safe_mode(self, method, url, **kwargs):
        """
        Send a HTTP request, and catch any exception that might occur due to connection problems.
        Safe mode has been removed from requests 1.x.
        """
        try:
            return requests.Session.request(self, method, url, **kwargs)
        except (MissingSchema, InvalidSchema, InvalidURL):
            raise
        except RequestException as ex:
            resp = ApiResponse()
            resp.error = ex
            resp.status_code = 0  # with this status_code, content returns None
            resp.request = Request(method, url).prepare()
            return resp
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/165701.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 毕业设计之我的项目—-旅游管理系统的设计与实现[通俗易懂]

    毕业设计之我的项目—-旅游管理系统的设计与实现[通俗易懂]本项目需求来源于网络,有需要源码和交流的评论额?喜欢软件对软件有着很高程度认识的朋友也可以指出我的设计问题等等。欢迎与我交流角色分析角色:用户:管理员:功能分析用户:登录注册:修改个人信息预定酒店功能个人酒店订单查询:景点信息查询:酒店评价:景点评价:游记功能:增-查线路查询:轮播图:结伴游:…

    2022年6月3日
    45
  • linux 安装 node_手机安装node环境

    linux 安装 node_手机安装node环境Linux安装node环境1.去node官网下载node安装包2.解压并重命名tar-xvfnode-v14.15.5-linux-x64.tar.xz#解压mvnode-v16.14.2-linux-x64node#重命名为node3.全局引用,创建npm和node软连接ln-s/usr/local/dev/nodejs/node/bin/npm/usr/local/bin#创建npm软连接,其中/usr/local/dev/nodejs/node/bin/

    2022年9月13日
    0
  • 数仓(三):分层设计 ODS-DWD-DWS-ADS

    数仓(三):分层设计 ODS-DWD-DWS-ADS一、数仓建模的意义,为什么要对数据仓库分层?只有数据模型将数据有序的组织和存储起来之后,大数据才能得到高性能、低成本、高效率、高质量的使用。1、清晰数据结构:每一个数据分层都有它的作用域,这样我们在使用表的时候能更方便地定位和理解。数据关系条理化:源系统间存在复杂的数据关系,比如客户信息同时存在于核心系统、信贷系统、理财系统、资金系统,取数时该如何决策呢?数据仓库会对相同主题的数据进行统一建模,把复杂的数据关系梳理成条理清晰的数据模型,使用时就可避免上述问题了。2、数据血缘追…

    2022年6月26日
    29
  • Egret MovieClip

    Egret MovieClip1、准备资源使用TextureMerger生成帧动画所需的png和json文件点击导出即可得到以下2个文件2、代码逻辑//帧动画modulegame{exportclassframeDemoextendsegret.DisplayObjectContainer{publicconstructor(){…

    2022年10月25日
    0
  • 通俗理解动态库与静态库区别是什么_动态ip和静态ip哪个好

    通俗理解动态库与静态库区别是什么_动态ip和静态ip哪个好引:最近做了算法产品化相关的一些工作,其中涉及到算法库封装的相关工作,封装为动态库。总结动态库和静态库区别和对应使用原则。区别:静态库和动态库最本质的区别就是:该库是否被编译进目标(程序)内部。分别介绍:静态(函数)库一般扩展名为(.a或.lib),这类的函数库通常扩展名为libxxx.a或xxx.lib。这类库在编译的时候会直接整合到目标程序中,所以利用静态函数库编译成…

    2022年9月30日
    0
  • Mysql主从配置,实现读写分离

    Mysql主从配置,实现读写分离

    2021年11月7日
    34

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号