首页 > 解决方案 > Python 等效于将 POST 有效负载包装在单引号中

问题描述

这比 Splunk 更像是一个 python 问题,但如果有人这样做会很有帮助……特别是在这里,讨论了在单个 POST 中将多个指标发送到服务器。他们提供的示例是使用 curl 并将整个有效负载包装在单引号 (') 中,例如

curl -k http://<IP address or host name or load balancer name>:8088/services/collector  \
-H "Authorization: Splunk 98a1e071-bc35-410b-8642-78ce7d829083"                         
\
-d '{"time": 1505501013.000,"source":"disk","host":"host_99","fields": 
{"region":"us-west-1","datacenter":"us-west- 1a","rack":"63","os":"Ubuntu16.10","arch":"x64","team":"LON","service":"6","service_version":"0","service_environment":"test","path":"/dev/sda1","fstype":"ext3","_value":999311222774,"metric_name":"total"}}
{"time": 1505511013.000,"source":"disk","host":"host_99","fields": 
{"region":"us-west-1","datacenter":"us-west-1a","rack":"63","os":"Ubuntu16.10","arch":"x64","team":"LON","service":"6","service_version":"0","service_environment":"test","path":"/dev/sda1","fstype":"ext3","_value":1099511627776,"metric_name":"total"}}'

我的问题是如何在 python 中做同样的事情——即你不能像 curl 命令那样将多个 JSON 对象包装在单引号中——这只会使整个有效负载成为一个字符串。是否有其他包装可用于此目的?

所以,这有效:

payload = {"time": 1505501013.000,"source":"disk","host":"host_99","fields": 
{"region":"us-west-1","datacenter":"us-west- 1a","rack":"63","os":"Ubuntu16.10","arch":"x64","team":"LON","service":"6","service_version":"0","service_environment":"test","path":"/dev/sda1","fstype":"ext3","_value":999311222774,"metric_name":"total"}}

但这不会:

payload = {"time": 1505501013.000,"source":"disk","host":"host_99","fields": 
{"region":"us-west-1","datacenter":"us-west- 1a","rack":"63","os":"Ubuntu16.10","arch":"x64","team":"LON","service":"6","service_version":"0","service_environment":"test","path":"/dev/sda1","fstype":"ext3","_value":999311222774,"metric_name":"total"}}
 {"time": 1505511013.000,"source":"disk","host":"host_99","fields": 
{"region":"us-west-1","datacenter":"us-west-1a","rack":"63","os":"Ubuntu16.10","arch":"x64","team":"LON","service":"6","service_version":"0","service_environment":"test","path":"/dev/sda1","fstype":"ext3","_value":1099511627776,"metric_name":"total"}}

仅供参考,那么 POST 看起来像:

 resp = requests.post(splunkurl,json=payload,headers=headers)

标签: pythonjsonsplunk

解决方案


好吧,“多个 json 对象”不是有效的 json,除非它是一个对象列表

通常,python 不关心(就像任何其他网络工具一样),json 只是数据格式,您需要不同的格式。因此,您需要自己构建文本有效负载,即json.dumps(payload1) + json.dumps(payload2),并通过您的网络客户端将其作为“原始”数据发送。

我非常怀疑主流的 http 库是否提供了这种开箱即用的用例。


不确定拒绝投票的原因,即requests库(这是高级网络事实上的标准)对有效负载进行智能处理:

requests.post(url, data={'v1': 1, 'v2': 2})  # will encode it as form data
requests.post(url, json={'v1': 1, 'v2': 2})  # will encode as json
requests.post(url, data="{'v1': 1}{'v2': 2}")  # will send as-is

Json与http本身无关,只是一种序列化数据的方式。大多数客户最终都会使用urllib,这根本不关心,唯一的问题是库是否提供了简单的方法来发送原始数据


推荐阅读