您当前的位置:首页 > 电脑百科 > 软件技术 > 软件技术

HTTP请求工具之“拿来吧你”

时间:2023-03-01 15:54:11  来源:今日头条  作者:闪念基因

导语:在进行网关、CDN类型产品的转发测试过程中,除了普通的HTTP|HTTPS请求,通常我们还会涉及到一些协议以及TLS层面的测试。在敏捷环境下,通常到一定时间段我们的测试工具会五花八门,不便于管理的同时,也增加了其他同事使用的学习成本。本文将介绍使用Python/ target=_blank class=infotextkey>Python的httpx库以及curl来支持绝大部分HTTP请求场景,希望能给大家带来一些帮助,欢迎大家留言讨论,一起进一步完善工具。

1.准备工作

1.1.httpx

httpx库仅支持Python3,可通过pip命令安装支持HTTP2与命令行工具。

python -m pip install httpx
# 支持HTTP2
python -m pip install 'httpx[http2]'
# 安装命令行客户端
python -m pip install 'httpx[cli]'

Python中使用示例:

>>> import httpx
>>> r = httpx.get('https://www.example.org/')
>>> r
<Response [200 OK]>
>>> r.status_code
200
>>> r.headers['content-type']
'text/html; charset=UTF-8'
>>> r.text
'<!doctype html>n<html>n<head>n<title>Example DomAIn</title>...'

命令行使用示例:

 


 

1.2.curl

建议将curl版本升级至7.68.0或以上,本文中以7.68.0为例。

为了让 curl 支持 HTTP2 我们需要安装 nghttp2(http2 的 C 语言库):

# 从git直接拷贝项目或下载压缩包:
git clone https://Github.com/tatsuhiro-t/nghttp2.git
cd nghttp2-master
autoreconf -i
automake
autoconf
./configure
make && make install
echo '/usr/local/lib' > /etc/ld.so.conf.d/local.conf
ldconfig

升级curl版本:

yum install build-dep curl
wget http://curl.haxx.se/download/curl-7.68.0.zip
unzip curl-7.68.0.zip
cd curl-7.68.0
./configure --with-nghttp2=/usr/local --with-ssl
make && make install
ldconfig

在执行./configure时,可以从终端观察到HTTP2是enabled的状态:

 

2.开始

2.1.基本请求

2.1.1.httpx.Client

从上文的示例中,我们可以看到httpx库可以在import后,直接通过调用httpx.get、httpx.post等调用发起对应method的请求。在小工具中,此类调用方式无疑是方便、快捷且实用的。而在工程中,则推荐使用httpx.Client或httpx.AsyncClient,并通过调用示例化对象client的request方法代替直接调用get、post等来使代码更灵活。

with httpx.Client() as client:
    client.request(
        method=method,
        url=req_url,
        headers=req_headers,
        content=content
    )

2.1.2.curl

curl <url> -X <method> -d <data> -H <header>
# POST或PUT大文件时,建议使用 -F 'file=@<filename>'
# HEAD请求建议直接使用-I,而不是 -X HEAD

2.2.chunked

有时候我们需要通过在Client端构造chunked请求,来验证反向代理的模块对此类请求处理的准确性。但是现有的工具却没有一个明确的参数方便我们构造此类请求。

首先,chunked是指分块传输编码(Chunked transfer encoding),允许客户端或服务端将body分成不确定的多块进行传输。

而通过help,可以看到httpx请求方法中的content参数是允许传入一个byte iterator的。

 

那么我们只要实现一个生成器,将content进行切块,再将生成器作为参数传给httpx.request即可。

if req_chunked:
    _content = content
    _middle = _content.__len__() // 2


    async def content():
        yield _content[:_middle]
        yield _content[_middle:]
else:
    pass


async with httpx.AsyncClient(http2=http2) as client:
    task = asyncio.create_task(
        client.request(
            method=method,
            url=req_url,
            headers=req_headers,
            content=content() if callable(content) else content
        )
    )


    try:
        await task
    except asyncio.CancelledError:
        pass

2.3.HTTP2

备注:成功完成一个HTTP2请求,需要Server端也支持HTTP2协议。

由于httpx库对HTTP2有较完善的支持,发起HTTP2请求也非常方便,只需在实例化Client时指定参数http2=True即可。

with httpx.Client(http2=True) as client:
    client.request(
        method=method,
        url=req_url,
        headers=req_headers,
        content=content
    )

curl命令则只需带上--http2参数即可。

curl <url> --http2

2.3.1.构造多路复用请求

多路复用 —— 一个连接中的请求是非阻塞的,即同连接中的请求可并发,存在多个stream。我们通过httpx.AsyncClient来构造:

async with httpx.AsyncClient(http2=http2) as client:
    for i in range(req_num):
        task_list = list()
        for m in range(multiplexing):  # multiplexing,指定stream的数量
            task = asyncio.create_task(
                client.request(
                    method=method,
                    url=req_url,
                    headers=req_headers,
                    content=content
                )
            )
            task_list.Append(task)


        await asyncio.wait(task_list)
        for t in task_list:
            try:
                await t
            except _err_type:
                pass


        for t in task_list:
            if t.exception():
                logger.warning(t.exception())
            else:
                pass
            response_list.append(t.result())

2.4.SSL/TLS

在SSL/TLS协议相关测试过程中,通常需要验证系统的各种功能在和不同的Cipher suite(密码套件)以及SSL/TLS版本结合的情况下,运作能力是否付符合设计预期。

在Python中,存在一个内置的库:ssl,它能满足测试验证的大部分述求。需要注意的是,ssl库依赖于设备上的OpenSSL。

在curl中,则可以通过--ciphers、--tls-max、--tlsv1.x等参数来满足述求。

2.4.1.Ciphers

httpx+ssl:

import httpx
import ssl


### 创建默认SSL上下文 ###
ssl_ctx = ssl.create_default_context()


### 关闭单向认证场景的证书校验 ###
# 修改校验标志位
ssl_ctx.verify_flags = ssl.VerifyFlags.VERIFY_DEFAULT
# 关闭域名校验
ssl_ctx.check_hostname = False
# 关闭证书校验
ssl_ctx.verify_mode=ssl.VerifyMode.CERT_NONE


### 设置SSL上下文的cipher suite ###
ssl_ctx.set_ciphers("AES128-GCM-SHA256")


### 发起HTTPS单向认证请求 ###
url = "https://<vip>:<vport>/"
rsp = httpx.get(url, verify=ssl_ctx)
"""
>>> rsp.status_code
200
>>> rsp.headers
Headers({'date': 'Fri, 01 Jul 2022 08:25:55 GMT', 'content-type': 'application/octet-stream', 'transfer-encoding': 'chunked', 'connection': 'keep-alive', 'server': 'openresty/1.17.8.1', 'cid': '215253869784', 'cipher': 'AES128-GCM-SHA256'})
"""


# 查询cipher suite,如果调用过set_ciphers(),则只会返回配置的ciphers信息
ssl_ctx.get_ciphers()
"""
[{'id': 50380848,
 'name': 'ECDHE-RSA-AES256-GCM-SHA384',
 'protocol': 'TLSv1/SSLv3',
 'description': 'ECDHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=RSA Enc=AESGCM(256) mac=AEAD',
 'strength_bits': 256,
 'alg_bits': 256},
 {'id': 50380844,
 'name': 'ECDHE-ECDSA-AES256-GCM-SHA384',
 'protocol': 'TLSv1/SSLv3',
 'description': 'ECDHE-ECDSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESGCM(256) Mac=AEAD',
 'strength_bits': 256,
 'alg_bits': 256},
 ...
]
"""

curl:

curl <https url> -k --cipher ECDHE-RSA-AES256-GCM-SHA384

查询系统支持哪些cipher suite:

openssl ciphers

2.4.2.指定SSL/TLS版本

httpx+ssl:

import httpx
import ssl


### 创建默认SSL上下文 ###
ssl_ctx = ssl.create_default_context()


### 关闭单向认证场景的证书校验 ###
# 修改校验标志位
ssl_ctx.verify_flags = ssl.VerifyFlags.VERIFY_DEFAULT
# 关闭域名校验
ssl_ctx.check_hostname = False
# 关闭证书校验
ssl_ctx.verify_mode=ssl.VerifyMode.CERT_NONE


### 设置SSL协议版本 ###
ssl_ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_1)
# 校验SSL上下文对象的协议版本号
ssl_ctx.protocol
"""
<_SSLMethod.PROTOCOL_TLSv1_1: 4>
"""


### 发起HTTPS单向认证请求 ###
url = "https://<vip>:<vport>/"
rsp = httpx.get(url, verify=ssl_ctx)
"""
>>> rsp.status_code
200
>>> rsp.headers
Headers({'date': 'Mon, 04 Jul 2022 06:28:08 GMT', 'content-type': 'application/octet-stream', 'transfer-encoding': 'chunked', 'connection': 'keep-alive', 'server': 'openresty/1.17.8.1', 'cid': '218525668279', 'cipher': 'ECDHE-RSA-AES128-SHA', 'ssl_protocol': 'TLSv1.1'})
"""

curl:

# 示例为TLSv1.2,其他版本以此类推。
# 注意:最好指定--tls-max,否则请求会优先按支持的最新版本协商。
curl <https url> -k --tlsv1.2 --tls-max 1.2

2.5.Resolve/SNI

SNI(Server Name Indication)是为了解决一个服务器使用多个域名和证书的TLS扩展,主要解决一台服务器只能使用一个证书的缺点。

在验证域名查找与SNI的场景时,需要Client支持域名解析。通常的临时做法是,去修改系统中的/etc/hosts,固定被测IP地址与域名的映射。这么做虽然方便快捷,但是也存在Client共用时的解析优先级冲突,验证IP地址与域名多对多时需要频繁修改调整等问题。所以,接下来我们来一起看看怎么在Python和curl的运行时动态地去resolve,以解决上述问题。

Python,通过重写socket底层getaddrinfo方法,将域名与IP地址在运行时动态篡改为预期的映射关系。然后使用httpx,直接对域名发起请求即可。

重写socket底层getaddrinfo方法示例代码:

import ipaddress
import socket


from loguru import logger




class DNS(object):
    DNS_CACHE = dict()


    def __init__(self):
        super(DNS, self).__init__()


        self.socket_get_address_info = socket.getaddrinfo
        socket.getaddrinfo = self.custom_get_address_info


    def add_custom_dns(
            self,
            domain: str,
            port: int,
            ip: str
    ):


        key = (domain.encode("utf-8"), port)
        if ipaddress.ip_address(ip).version == 4:
            value = (
                socket.AddressFamily.AF_.NET,
                socket.SocketKind.SOCK_STREAM,
                socket.IPPROTO_TCP,
                '',
                (ip, port)
            )
        else:
            value = (
                socket.AddressFamily.AF_INET6,
                socket.SocketKind.SOCK_STREAM,
                socket.IPPROTO_TCP,
                '',
                (ip, port, 0, 0)
            )


        self.DNS_CACHE[key] = [value]
        logger.debug(f"DNS_Cache: {self.DNS_CACHE}")


        return None


    def custom_get_address_info(
            self,
            *args
    ):
        logger.debug(
            f"Args: {args}"
        )
        try:
            if isinstance(args[0], str):
                key = (args[0].encode("utf8"), args[1])
            else:
                key = args[:2]
            return self.DNS_CACHE[key]
        except KeyError:
            return self.socket_get_address_info(*args)

curl,使用--resolve参数,域名与IP地址的映射关系仅在当次请求时生效:

curl <url> --resolve <domain>:<port>:

3.参考资料

  1. https://www.python-httpx.org
  2. pypi.org/project/httpx/
  3. requests.readthedocs.io

作者:ten

来源:微信公众号:鹅厂架构

出处
:https://mp.weixin.qq.com/s/xxP-MVgdASZ324MLkv1-Vw



Tags:HTTP请求   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
探索Java的HTTP请求与响应处理机制
Java的HTTP请求与响应处理机制是开发Web应用程序或与Web服务进行交互时非常重要的一部分。下面将详细介绍Java中HTTP请求和响应的基本概念、常见的处理方式以及一些最佳实践...【详细内容】
2023-11-08  Search: HTTP请求  点击:(223)  评论:(0)  加入收藏
Spring Boot是如何处理HTTP请求的?
在Spring Boot中创建基本的REST控制器是个简单的过程。通过使用一些注释,您可以封装所需的逻辑,让Spring Boot处理其余部分。但是,这背后究竟发生了什么?本文将详细介绍Spring B...【详细内容】
2023-09-20  Search: HTTP请求  点击:(214)  评论:(0)  加入收藏
Springboot — 用更优雅的方式发HTTP请求(RestTemplate详解)
RestTemplate是Spring提供的用于访问Rest服务的客户端,RestTemplate提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率。我之前的HTTP开发是用apache的Htt...【详细内容】
2023-09-14  Search: HTTP请求  点击:(317)  评论:(0)  加入收藏
HTTP请求:Requests的进阶使用方法浅析
1 背景上篇文章讲解了 requests 模块的基础使用,其中有 get、put、post 等多种请求方式,使用 data、json 等格式做为请求参数,在请求体中添加请求头部信息的常见信息,如:headers...【详细内容】
2023-06-28  Search: HTTP请求  点击:(175)  评论:(0)  加入收藏
优化自动化接口测试:利用钩子函数增强HTTP请求处理
在自动化接口测试中,我们经常需要发送HTTP请求来模拟用户的操作并验证接口的正确性。够灵活处理请求参数、添加认证信息以及处理依赖参数。这正是钩子函数的用武之地。下面勇...【详细内容】
2023-06-16  Search: HTTP请求  点击:(95)  评论:(0)  加入收藏
Java发送http请求
一,原始方式使用java.net包中的HttpURLConnection类。以下是一个简单的示例代码,用于发送GET请求并获取响应:javaCopy codeimport java.io.BufferedReader;import java.io.Inpu...【详细内容】
2023-05-28  Search: HTTP请求  点击:(352)  评论:(0)  加入收藏
node http请求
对于前端来说,网络请求主要就是用 ajax 的方式去处理。所以本文也会站在前端角度简单讲解 Node 中如何使用 http 模块。前后端对接时,现在常用的请求方法有 GET、POST、PUT、P...【详细内容】
2023-05-22  Search: HTTP请求  点击:(121)  评论:(0)  加入收藏
如何使用Java处理HTTP请求和响应?
Java中有许多成熟的HTTP框架可以使用,例如Spring、Netty等。这些框架提供了各种HTTP处理器和工具类,使得HTTP请求和响应处理变得更加容易和高效。下面是一个简单的Java代码示...【详细内容】
2023-05-17  Search: HTTP请求  点击:(340)  评论:(0)  加入收藏
为了一个HTTP请求问题,差点和iOS干起来
本次斗殴事件起因全部归iOS,为啥这么说,http请求都不会发,瞎写的什么玩意(ps:他应该不会看到...)。在处理本次冲突中,意外发现了另外一个存在已久的bug,我们先说说这个玩意,再说我们...【详细内容】
2023-03-14  Search: HTTP请求  点击:(164)  评论:(0)  加入收藏
HTTP请求工具之“拿来吧你”
导语:在进行网关、CDN类型产品的转发测试过程中,除了普通的HTTP|HTTPS请求,通常我们还会涉及到一些协议以及TLS层面的测试。在敏捷环境下,通常到一定时间段我们的测试工具会五花...【详细内容】
2023-03-01  Search: HTTP请求  点击:(160)  评论:(0)  加入收藏
▌简易百科推荐
如何在Windows 10中查看电脑的名称?这里提供详细步骤
你想在有多台计算机组成的网络上查找你的计算机吗?一种方法是找到你的电脑名称,然后在网络上匹配该名称。下面是如何在Windows 10中使用图形和命令行方法查看你的计算机名称。...【详细内容】
2024-04-10  驾驭信息纵横科技    Tags:Windows 10   点击:(2)  评论:(0)  加入收藏
移动版 Outlook 解锁新技能,可验证登录 OneDrive 等微软服务
IT之家 4 月 9 日消息,微软公司近日发布新闻稿,宣布用户可以使用 Outlook 手机应用,轻松登录 Teams、OneDrive、Microsoft 365 以及 Windows 等微软账号服务。移动端 Outlook...【详细内容】
2024-04-09    IT之家  Tags:Outlook   点击:(0)  评论:(0)  加入收藏
Win10/Win11和 macOS用户反馈:谷歌云服务“捆绑”系统 DNS 设置
IT之家 4 月 6 日消息,谷歌公司承认旗下的 Google One 订阅服务中存在问题,在 Windows 10、Windows 11 以及 macOS 系统上会更改系统 DNS 设置,变更为 8.8.8.8 地址。Google On...【详细内容】
2024-04-08    IT之家  Tags:Win10   点击:(7)  评论:(0)  加入收藏
电脑卡顿怎么重装系统,快看这篇
电脑卡顿时,重装系统确实是一种可能的解决方案。以下是重装系统的详细步骤:备份重要数据:首先,你需要将电脑中的重要文件和数据备份到外部存储设备(如U盘、移动硬盘或云存储)中,以...【详细内容】
2024-04-04  科技数码前锋    Tags:重装系统   点击:(2)  评论:(0)  加入收藏
如何检查电脑的最近历史记录?这里提供详细步骤
如果你怀疑有人在使用你的计算机,并且你想查看他们在做什么,下面是如何查看是否有访问内容的痕迹。如何检查我的计算机的最近历史记录要检查计算机的最近历史记录,应该从web浏...【详细内容】
2024-03-30  驾驭信息纵横科技    Tags:历史记录   点击:(0)  评论:(0)  加入收藏
关于Windows中AppData的相关知识,看这篇文章就可以了
如果AppData文件夹占用了你电脑上的太多空间,则需要清理AppData文件夹。下面是一些帮助你在Windows计算机上进行AppData清理的方法。什么是AppData文件夹AppData文件夹是保存...【详细内容】
2024-03-30  驾驭信息纵横科技    Tags:AppData   点击:(2)  评论:(0)  加入收藏
微软 Edge 浏览器将迎来“内存限制器”功能,用户可自主控制 Edge 内存占用
IT之家 3 月 28 日消息,微软即将为其 Edge 浏览器带来一项实用新功能,据悉该公司正在测试一项内置的内存限制器,这项功能可以让用户限制 Edge 所占用的内存,防止浏览器超出内存...【详细内容】
2024-03-29    IT之家  Tags:Edge   点击:(14)  评论:(0)  加入收藏
一寸照片的大小如何压缩?四个实测效果很好的方法
一寸照片作为生活中常见的尺寸之一,常用于各类证件照与证明文件的制作。然而,受限于其较为狭小的尺寸,上传及打印过程中很容易出现尺寸超限的情况。所以,这个时候就需要对其体积...【详细内容】
2024-03-18  宠物小阿涛    Tags:压缩   点击:(14)  评论:(0)  加入收藏
手机投屏到电脑/电视的方法
方法一:Win10自带的投影功能1、将手机和电脑连接同一个无线网络。2、选择【开始】>【设置】>【系统】>【投影到此电脑】3、将默认的始终关闭的选项更改为所有位置都可用。4、...【详细内容】
2024-03-18    老吴讲I  Tags:投屏   点击:(16)  评论:(0)  加入收藏
微软商店怎么卸载应用 一分钟快速看懂!
微软商店怎么卸载应用 一分钟快速看懂!微软公司(Microsoft Corporation)是一家全球领先的科技企业,总部位于美国华盛顿州的雷德蒙德。成立于1975年,由比尔&middot;盖茨和保罗&mid...【详细内容】
2024-02-27  婷婷说体育    Tags:微软商店   点击:(36)  评论:(0)  加入收藏
站内最新
站内热门
站内头条