[英]Convert PHP curl POST request with array of parameters to Python code
I want to convert my php code to python code.我想将我的 php 代码转换为 python 代码。
$u = 'http://httpbin.org/post';
$req = array(
'check' => 'command',
'parameters' => array(
0 => array('parameter' => '1', 'description' => '2'),
1 => array('parameter' => '3', 'description' => '4')
)
);
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $u);
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($req));
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
$response = curl_exec($curl);
php test.php
{
"args": {},
"data": "",
"files": {},
"form": {
"check": "command",
"parameters[0][parameter]": "1",
"parameters[0][description]": "2",
"parameters[1][parameter]": "3",
"parameters[1][description]": "4"
},
this code successfully fetching data from remote api, but when i try to write it with Python requests - array of parameters is sending with wrong data.此代码成功地从远程 api 获取数据,但是当我尝试使用 Python 请求编写它时 - 参数数组发送的数据错误。
url = 'http://httpbin.org/post'
req = {'check': 'command', 'parameters': ({'parameter': '1', 'description': '2'}, {'parameter': '3', 'description': '4'})}
try:
fetch = requests.post(url, data = req)
except requests.exceptions.RequestException as e:
print(e)
print(fetch.text)
python3 test.py
{
"args": {},
"data": "",
"files": {},
"form": {
"check": "command",
"parameters": [
"parameter",
"description",
"parameter",
"description"
]
},
"Parameters", sended by my Python script is invalid我的 Python 脚本发送的“参数”无效
PHPs http_build_query
and it's corresponding $_GET
and $_POST
parsing are completely arbitrary in how they work. PHP 的
http_build_query
及其对应的$_GET
和$_POST
解析在它们的工作方式上是完全任意的。 Thus you must implement this functionality yourself.因此,您必须自己实现此功能。
Let's compare the outputs of PHPs http_build_query
to pythons urlencode
(which requests uses internally to build the parameters)让我们将 PHP 的
http_build_query
的输出与 python 的urlencode
进行比较(请求在内部使用它来构建参数)
$req = array(
'check' => 'command',
'parameters' => array(
0 => array('parameter' => '1', 'description' => '2'),
1 => array('parameter' => '3', 'description' => '4')
)
);
$query = http_build_query($req);
$query_parsed = urldecode($query);
echo $query;
echo $query_parsed;
Result:结果:
check=command¶meters%5B0%5D%5Bparameter%5D=1¶meters%5B0%5D%5Bdescription%5D=2¶meters%5B1%5D%5Bparameter%5D=3¶meters%5B1%5D%5Bdescription%5D=4
check=command¶meters[0][parameter]=1¶meters[0][description]=2¶meters[1][parameter]=3¶meters[1][description]=4
from urllib.parse import urlencode, unquote
req = {'check': 'command', 'parameters': ({'parameter': '1', 'description': '2'}, {'parameter': '3', 'description': '4'})}
query = urlencode(req)
query_parsed = unquote(query)
print(query)
print(query_parsed)
Result:结果:
check=command¶meters=%28%7B%27parameter%27%3A+%271%27%2C+%27description%27%3A+%272%27%7D%2C+%7B%27parameter%27%3A+%273%27%2C+%27description%27%3A+%274%27%7D%29
check=command¶meters=({'parameter':+'1',+'description':+'2'},+{'parameter':+'3',+'description':+'4'})
This looks quite a bit different but apparently conforms to the standard and thus httpbin interprets this correctly.这看起来有点不同,但显然符合标准,因此 httpbin 正确解释了这一点。
To make python behave the same as PHP, I've adapted this answer to create the following:为了使 python 的行为与 PHP 相同,我已修改此答案以创建以下内容:
from collections.abc import MutableMapping
from urllib.parse import urlencode, unquote
def flatten(dictionary, parent_key=False, separator='.', separator_suffix=''):
"""
Turn a nested dictionary into a flattened dictionary
:param dictionary: The dictionary to flatten
:param parent_key: The string to prepend to dictionary's keys
:param separator: The string used to separate flattened keys
:return: A flattened dictionary
"""
items = []
for key, value in dictionary.items():
new_key = str(parent_key) + separator + key + separator_suffix if parent_key else key
if isinstance(value, MutableMapping):
items.extend(flatten(value, new_key, separator, separator_suffix).items())
elif isinstance(value, list) or isinstance(value, tuple):
for k, v in enumerate(value):
items.extend(flatten({str(k): v}, new_key, separator, separator_suffix).items())
else:
items.append((new_key, value))
return dict(items)
req = {'check': 'command', 'parameters': ({'parameter': '1', 'description': '2'}, {'parameter': '3', 'description': '4'})}
req = flatten(req, False, '[', ']')
query = urlencode(req)
query_parsed = unquote(query)
print(query)
print(query_parsed)
Which outputs哪个输出
check=command¶meters%5B0%5D%5Bparameter%5D=1¶meters%5B0%5D%5Bdescription%5D=2¶meters%5B1%5D%5Bparameter%5D=3¶meters%5B1%5D%5Bdescription%5D=4
check=command¶meters[0][parameter]=1¶meters[0][description]=2¶meters[1][parameter]=3¶meters[1][description]=4
which seems to be what you want.这似乎是你想要的。
Now you should be able to pass the result of flatten
as data
to get the desired behaviour.现在您应该能够将
flatten
的结果作为data
传递以获得所需的行为。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.