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

FastAPI+Ariadne GraphQL服务中,httpx发送Mutation请求返回400错误的正确请求方式咨询

FastAPI+Ariadne GraphQL服务中,httpx发送Mutation请求返回400错误的正确请求方式咨询

看起来你遇到的问题挺典型的——明明在Playground和curl里都能正常调用的Mutation,换成httpx的POST请求就返回400错误,而且GET请求的Query还能正常工作。我帮你梳理几个可能的解决方向,你可以逐个试试:

1. 确保请求体包含operationName字段

虽然GraphQL规范里operationName不是强制要求,但部分服务端实现(包括Ariadne的某些场景)会在query中明确命名操作时要求这个字段。你在curl里可能隐式包含了它,而httpx请求里漏掉了。修改你的请求代码,添加这个字段试试:

import httpx

query = """
mutation CleanText($context: ExecutionContextInput!, $state: CleanTextInput!) {
  cleanText(context: $context, state: $state) {
    response {
      text
    }
  }
}
"""
variables = {
    "context": {"executionId": "123"},
    "state": {"text": "Hello World!!"}
}

# 添加operationName字段,和你的mutation名称一致
payload = {
    "query": query,
    "variables": variables,
    "operationName": "CleanText"
}

resp = httpx.post(
    "http://localhost:8000/graphql",
    json=payload
)

print(resp.status_code)
print(resp.text)

2. 对比httpx和curl的请求体差异

既然curl能正常工作,你可以先把httpx要发送的请求体打印出来,和curl的请求体做精确对比,看看有没有序列化差异或者格式问题:

import json
import httpx

query = """
mutation CleanText($context: ExecutionContextInput!, $state: CleanTextInput!) {
  cleanText(context: $context, state: $state) {
    response {
      text
    }
  }
}
"""
variables = {
    "context": {"executionId": "123"},
    "state": {"text": "Hello World!!"}
}

payload = {"query": query, "variables": variables, "operationName": "CleanText"}
# 打印序列化后的请求体,和curl里的内容对比
print(json.dumps(payload, indent=2))

resp = httpx.post(
    "http://localhost:8000/graphql",
    json=payload
)

如果发现差异,比如字符串转义、换行符处理等问题,可以手动构造请求体字符串,用content参数发送,模拟curl的行为:

resp = httpx.post(
    "http://localhost:8000/graphql",
    content=json.dumps(payload),
    headers={"Content-Type": "application/json"}
)

3. 升级httpx到最新版本

旧版本的httpx可能在JSON序列化或者请求头处理上存在bug,尝试升级到最新版本:

pip install --upgrade httpx

4. 检查服务端的请求日志

如果上面的方法都没用,你可以在FastAPI服务端添加请求日志,看看收到的httpx请求到底是什么样的,对比curl的请求,定位差异点。比如在FastAPI中添加简单的日志中间件:

from fastapi import FastAPI, Request
import logging

app = FastAPI()

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

@app.middleware("http")
async def log_requests(request: Request, call_next):
    logger.info(f"Received request: {await request.body()}")
    response = await call_next(request)
    return response

# 你的Ariadne GraphQL配置代码...

这样就能在服务端日志里看到httpx发送的原始请求体,和curl的请求体对比,就能快速找到问题所在。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 07:43:01