简体   繁体   English

将带有参数数组的 PHP curl POST 请求转换为 Python 代码

[英]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进行比较(请求在内部使用它来构建参数)

PHP PHP

$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&parameters%5B0%5D%5Bparameter%5D=1&parameters%5B0%5D%5Bdescription%5D=2&parameters%5B1%5D%5Bparameter%5D=3&parameters%5B1%5D%5Bdescription%5D=4
check=command&parameters[0][parameter]=1&parameters[0][description]=2&parameters[1][parameter]=3&parameters[1][description]=4

Python Python

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&parameters=%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&parameters=({'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&parameters%5B0%5D%5Bparameter%5D=1&parameters%5B0%5D%5Bdescription%5D=2&parameters%5B1%5D%5Bparameter%5D=3&parameters%5B1%5D%5Bdescription%5D=4
check=command&parameters[0][parameter]=1&parameters[0][description]=2&parameters[1][parameter]=3&parameters[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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM