使用pdpyras请求PagerDuty API时字符串拼接出现非法字符报400错误
报错根因
1. 末尾%0A的来源
os.popen(...).read() 会完整捕获命令行的标准输出,包括date命令输出末尾自带的换行符。你打印changedate时输出后空的那一行,就是这个肉眼不可见的换行符,拼接到URL后被自动编码为%0A,是当前400报错的直接原因。
之前硬编码URL能正常使用,本质是硬编码字符串里没有这类隐藏的非法字符,并不是手工拼接URL的方式本身没有隐患,只要拼接的字符串混入了换行、空格这类不可见字符,就会触发API校验失败。
2. 方括号编码异常的来源
你手工拼接带include[]的查询字符串时,pdpyras底层的请求库会对URL中的特殊字符做自动转义,把方括号编码为%5B%5D;且后续修改代码时把params参数传成了手工拼接好的字符串,不符合pdpyras的入参规范,进一步导致URL格式不符合API要求。
修复方案
- 给
changedate增加首尾空白字符去除处理,从根源删掉末尾的换行符,直接在read()方法后接.strip()即可。 - 不要手工拼接查询字符串,
params参数必须传入字典格式的结构化键值对,由pdpyras自动处理参数编码,避免手写转义错误,同时库会自动过滤参数值里的非法字符。 - (可选优化)替换系统命令调用,改用Python内置datetime模块生成时间戳,跨平台兼容性更好,也不会出现命令输出带换行的问题。
修复后代码示例
import os from pdpyras import APISession session = APISession(api_token) # 保留原系统命令获取时间的逻辑,增加strip去掉末尾换行 changedate = os.popen("date -u -d '24 hours ago' +'%FT%T%.2Z'").read().strip() # 用字典传递查询参数,由库自动处理合规编码 change_dump = session.rget( "change_events", params={ "include[]": "integration", "since": changedate } ) print(change_dump[0])
如果要优化跨平台兼容性,可替换系统命令获取时间的逻辑,改用纯Python实现:
from datetime import datetime, timedelta, timezone # 生成UTC时区下24小时前的时间,格式符合PagerDuty API要求 now_utc = datetime.now(timezone.utc) changedate = (now_utc - timedelta(hours=24)).strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + "Z"
注:pdpyras的
params入参不要传拼接好的字符串,库会自动对字典格式的参数做合规的URL编码,不需要手动处理方括号、特殊符号的转义,也能避免换行、空格这类意外混入的字符污染请求URL。
内容的提问来源于stack exchange,提问作者Saha
相关产品推荐
相关产品推荐

