You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何格式化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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 01:14:52