CosmosDB Rest API调用返回BadRequest错误排查求助
Cosmos DB REST API 查询返回 BadRequest 错误排查
问题背景
按照官方文档编写Python代码,通过REST API从Cosmos DB集合获取单条JSON文档时,返回如下错误:
{'code': 'BadRequest', 'message': 'One of the input values is invalid.\r\nActivityId: <***>, Windows/10.0.17763 cosmos-netstandard-sdk/3.18.0'}
该查询在Cosmos DB UI中执行正常,但错误信息不足以定位问题,相关代码如下:
def query(self, subscription_id, resource_group_name, name, tenant_id, client_id, client_secret, db_account_name, database_name, collection_name, master_key): # Start of the code to generate the auth token from master key. decoded_master_key = base64.b64decode(master_key) resource_type = 'docs' resource_id = f'dbs/{database_name}/colls/{collection_name}' verb = 'POST' date = format_date_time(mktime(datetime.now().timetuple())) pain_digest_body = "{verb}\n{resource_type}\n{resource_id}\n{date}\n{other}\n".format( verb=(verb.lower() or ''), resource_type=(resource_type.lower() or ""), resource_id=(resource_id or ""), date=date.lower(), other="".lower()) digest_body = pain_digest_body.encode("utf-8") digest = hmac.new(decoded_master_key, digest_body, sha256).digest() signature = base64.encodebytes(digest).decode("utf-8") key_type = 'master' version = '1.0' master_key_authorization_signature = quote(f'type={key_type}&ver={version}&sig={signature[:-1]}') # End of the code to generate the auth token from master key. headers = {'x-ms-documentdb-isquery': 'True', 'x-ms-date': date, 'authorization': master_key_authorization_signature, 'x-ms-max-item-count': '1', 'x-ms-query-enable-crosspartition': 'True', 'Content-Type': 'application/json', 'x-ms-version': '2018-09-17', 'Accept': 'application/json', 'x-ms-documentdb-query-enable-scan': 'True', 'x-ms-documentdb-populatequerymetrics': 'True' } data = { 'query': f'SELECT * FROM c OFFSET 1 LIMIT 1' } url = 'https://{}.documents.azure.com/dbs/{}/colls/{}/docs'.format(db_account_name,database_name, collection_name) response = requests.post(url, headers=headers, data=data, timeout=60) print(response) return response.json()
排查方案及修复
1. 请求体格式错误(最可能原因)
代码中使用requests.post的data=data参数传递查询体,会将字典以application/x-www-form-urlencoded格式编码,但Cosmos DB REST API要求请求体为JSON格式。需改用json=data参数,让requests自动完成JSON序列化,同时确保Content-Type头匹配。
修复后的请求代码:
response = requests.post(url, headers=headers, json=data, timeout=60)
2. 授权签名验证
检查签名生成的关键环节:
- 日期一致性:确保
format_date_time生成的是UTC时区的RFC 1123格式时间(如Fri, 01 Jan 2024 12:00:00 GMT),且与请求头x-ms-date完全一致,不能使用本地时间。 - 签名字符串拼接:确认
pain_digest_body中的换行符为\n,无多余空格;other字段留空符合要求(对应可选的分区键等字段)。 - 签名编码:
base64.encodebytes会在结果末尾添加换行符,signature[:-1]的处理正确,但需确保quote编码后的授权字符串无乱码。
3. 查询体格式规范
按照官方要求,查询请求体需包含parameters字段(即使为空数组),避免格式不兼容:
data = { 'query': 'SELECT * FROM c OFFSET 1 LIMIT 1', 'parameters': [] }
4. API版本升级
当前使用的x-ms-version: 2018-09-17版本较旧,尝试升级到较新的稳定版本(如2021-05-15),减少兼容性问题。
内容的提问来源于stack exchange,提问作者Novice
相关产品推荐
相关产品推荐

