API 错误
如何处理来自 FourA API 的错误。
错误响应格式
API 为所有错误返回扁平的 JSON 对象。没有嵌套的 error 对象或错误代码。
{
"error": "Invalid API key"
}
某些错误在顶层包含额外字段,例如 status、service、retryAfter、current 或 limits:
{
"error": "Rate limit exceeded",
"status": 429,
"service": "single",
"retryAfter": 5,
"current": { "concurrency": 12, "rpm": 3000 },
"limits": { "maxConcurrency": 500, "maxRpm": 3000 }
}
跟踪 Request
每个 API response(成功或错误)都包含一个带有该调用 UUID 的 X-Foura-Request-Id header。请在您的端记录它。如果您需要向支持人员咨询特定 request 的情况,该 ID 可以帮助我们找到它。
curl -i -X POST https://eu.api.foura.ai/api/single/ \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"method": "GET", "url": "https://example.com"}'
# HTTP/1.1 200 OK
# X-Foura-Request-Id: 9f1c4e6c-7b2a-4d3e-8a1f-2c9d8e4a3b15
# Content-Type: application/json
# ...
错误类型
400: Bad Request
Request body 缺少必需字段、包含无效值,或者指定了 API 拒绝获取的目标。
{
"error": "Invalid request body format"
}
相同的 400 错误也适用于 SSRF 保护。如果您的 url 解析为私有、环回或其他保留的 IP 范围(RFC 5735、RFC 6598、IPv6 保留块),则该 request 在离开 FourA 的网络之前就会被拒绝:
{
"error": "Target <ip> resolves to a private/reserved IP"
}
解决办法: 检查您的 request 是否包含所有必需字段,URL 是否使用 http:// 或 https://,以及主机是否解析为公共地址。
401: Unauthorized
您的 API key 缺失或无效。
缺失 key:
{
"error": "Missing API key. Include X-API-Key header."
}
无效 key:
{
"error": "Invalid API key"
}
解决办法: 验证您的 X-API-Key header 是否包含有效的 key。如果需要,请从 Dashboard 生成新 key。
429: Rate Limited
您在短时间内发送了太多 request。
{
"error": "Rate limit exceeded",
"status": 429,
"service": "single",
"retryAfter": 5,
"current": { "concurrency": 12, "rpm": 3000 },
"limits": { "maxConcurrency": 500, "maxRpm": 3000 }
}
解决办法: 等待 retryAfter 中指定的秒数,然后再发送更多 request。详情请参阅 Rate Limits。
500: Server Error
我们这边出了问题。
解决办法: 稍后重试该 request。如果错误仍然存在,请检查 status page 或联系支持人员,并提供失败 response 中的 X-Foura-Request-Id。
503: Service Disabled or At Capacity
503 表示服务因维护暂时不可用,或者您已达到并发限制。这两种 response 都包含 retryAfter 字段。并发形式的错误还包括 current 和 limits。
{
"error": "Service disabled",
"status": 503,
"retryAfter": 60
}
解决办法: 等待 retryAfter 秒,然后重试。status page 列出了处于活动状态的维护窗口。
200 OK 内部的目标端失败
并非所有失败都会显示为非 2xx HTTP 状态。当目标网站返回带有错误负载的 HTTP 200 时,FourA 仍会将 body 交付给您,但会将该 request 分类为 application_error。当目标返回您的 validate 规则不接受的非 2xx 状态时,结果为 application_fail,并且 body 将保持不变。
这两种情况都将计费,就像 request 在网络层成功工作一样。Outcomes 参考文档涵盖了完整的分类。
Response 编码
FourA 会自动将 response body 解码为 UTF-8。如果目标提供 windows-1251、gbk、shift_jis、iso-8859-* 或在 Content-Type header 或 HTML <meta charset> 标签中声明的任何其他字符集,您将在 data(single、proxy)或 body(browser)字段中收到干净的 UTF-8 字符串。
对于二进制负载(图像、protobuf、原始音频),请在 request 上设置 returnBuffer: true。返回的 body 将作为 base64 缓冲区,不进行任何字符集转码。
重试策略
一个实用的重试策略:
import time
import requests
def make_request(url, payload, api_key, max_retries=3):
for attempt in range(max_retries):
resp = requests.post(
url,
headers={"X-API-Key": api_key, "Content-Type": "application/json"},
json=payload,
)
if resp.status_code == 200:
return resp.json()
body = resp.json() if resp.headers.get("content-type", "").startswith("application/json") else {}
retry_after = body.get("retryAfter", 2 ** attempt)
request_id = resp.headers.get("X-Foura-Request-Id", "?")
if resp.status_code in (429, 503):
time.sleep(retry_after)
continue
if resp.status_code >= 500:
time.sleep(2 ** attempt)
continue
# 400/401/404 won't fix themselves
raise RuntimeError(f"{resp.status_code} (request {request_id}): {body.get('error')}")
raise RuntimeError(f"Exhausted {max_retries} retries")
相关内容
- Rate Limits:并发和 RPM 详情
- Request Outcomes:七种结果值详解
- Common Issues:症状、原因和解决办法