如何格式化curlify库生成的请求结果以提升可读性?
问题
技术栈:Python、GraphQL、Allure Reports、Requests
我需要将请求详情附加到Allure测试报告中,目前用curlify库生成curl命令,但生成的结果过于紧凑,可读性很差。
原代码:
import curlify def api_request(method='POST', **kwargs): with allure.step(f"{method.upper()}{base_url}"): with sessions.Session() as session: response = session.request(method=method, url=base_url, **kwargs) message = curlify.to_curl(response.request) allure.attach( body=message.encode("utf-8"), name="Curl", attachment_type=AttachmentType.TEXT, extension='txt' )
当前生成的curl命令样式:
curl -X POST -H 'Accept: */*' -H 'Accept-Encoding: gzip, deflate' -H 'Connection: keep-alive' -H 'Content-Length: 318' -H 'Content-Type: application/json' -H 'User-Agent: python-requests/2.31.0' -d '{"query": "\n mutation Mutation($email: String!, $password: String!) {\n tokenAuth(email: $email, password: $password) {\n token\n refreshToken\n refreshExpiresIn\n __typename\n }\n }\n ", "variables": {"email": "ABC", "password": "ABC"}}' https://url/api/v2/graphql/
期望的curl命令样式(核心是格式化query部分):
curl -X POST -H 'Accept: */*' -H 'Accept-Encoding: gzip, deflate' -H 'Connection: keep-alive' -H 'Content-Length: 318' -H 'Content-Type: application/json' -H 'User-Agent: python-requests/2.31.0' -d ' {"query": " mutation Mutation($email: String!, $password: String!) { tokenAuth(email: $email, password: $password) { token refreshToken refreshExpiresIn __typename } } ", "variables": {"email": "ABC", "password": "ABC"}}' https://url/api/v2/graphql/
我试过用json.dumps(response.json(), ensure_ascii=False, indent=4).encode("utf-8")转换JSON,但没成功,求解决办法。
解决方案
核心思路是先解析请求体中的GraphQL内容,格式化后再重新生成curl命令,避免直接使用curlify生成的紧凑结果。
方案一:直接从请求参数处理(更可靠)
从请求的json参数中获取原始请求体,格式化GraphQL query后,替换curl命令中的-d参数内容:
import curlify import json import textwrap import re from requests import sessions import allure from allure_commons.types import AttachmentType def format_graphql_query(query): # 去掉多余缩进,再调整query的格式 dedented_query = textwrap.dedent(query).strip() # 给大括号添加换行和缩进,让结构更清晰 formatted_query = dedented_query.replace('{', ' {\n ').replace('}', '\n}').replace(',', ',\n ') return formatted_query def api_request(method='POST', **kwargs): with allure.step(f"{method.upper()} {base_url}"): with sessions.Session() as session: response = session.request(method=method, url=base_url, **kwargs) formatted_body = None # 处理json参数传递的请求体 if 'json' in kwargs: request_body = kwargs['json'].copy() if 'query' in request_body: request_body['query'] = format_graphql_query(request_body['query']) # 格式化整个JSON请求体 formatted_body = json.dumps(request_body, ensure_ascii=False, indent=2) # 生成基础curl命令并替换-d参数 curl_command = curlify.to_curl(response.request) if formatted_body: # 转义单引号,避免curl命令语法错误 escaped_body = formatted_body.replace("'", "\\'") # 替换原有的-d参数内容 curl_command = re.sub(r"-d '.*?'", f"-d '{escaped_body}'", curl_command, flags=re.DOTALL) allure.attach( body=curl_command.encode("utf-8"), name="Formatted Curl", attachment_type=AttachmentType.TEXT, extension='txt' ) return response
方案二:解析curlify生成的命令(兼容现有逻辑)
如果不想改动请求参数的处理逻辑,可以直接解析curlify生成的命令,提取并格式化-d参数中的JSON内容:
import curlify import json import textwrap import re from requests import sessions import allure from allure_commons.types import AttachmentType def format_graphql_query(query): dedented_query = textwrap.dedent(query).strip() formatted_query = dedented_query.replace('{', ' {\n ').replace('}', '\n}').replace(',', ',\n ') return formatted_query def parse_and_format_curl(curl_str): # 提取-d参数后的JSON内容 match = re.search(r"-d '(.*?)' (?=\S+|$)", curl_str, flags=re.DOTALL) if not match: return curl_str body_str = match.group(1) # 还原转义的单引号 body_str = body_str.replace("\\'", "'") try: body = json.loads(body_str) if 'query' in body: body['query'] = format_graphql_query(body['query']) # 格式化JSON formatted_body = json.dumps(body, ensure_ascii=False, indent=2) # 重新转义单引号用于curl命令 formatted_body_escaped = formatted_body.replace("'", "\\'") # 替换原curl命令中的-d内容 return re.sub(r"-d '.*?'", f"-d '{formatted_body_escaped}'", curl_str, flags=re.DOTALL) except json.JSONDecodeError: # 非JSON格式则返回原命令 return curl_str def api_request(method='POST', **kwargs): with allure.step(f"{method.upper()}{base_url}"): with sessions.Session() as session: response = session.request(method=method, url=base_url, **kwargs) raw_curl = curlify.to_curl(response.request) formatted_curl = parse_and_format_curl(raw_curl) allure.attach( body=formatted_curl.encode("utf-8"), name="Formatted Curl", attachment_type=AttachmentType.TEXT, extension='txt' ) return response
说明
format_graphql_query函数专门处理GraphQL query的格式化,通过调整换行和缩进让结构更清晰,可根据自己的需求修改格式规则。- 如果请求体是通过
data参数传递的JSON字符串,需要在代码中先将data解析为JSON对象再处理。
内容的提问来源于stack exchange,提问作者Katrin T
相关产品推荐
相关产品推荐

