【问题标题】:Trying to send JSON payload with urllib2, getting HTTPError 400尝试使用 urllib2 发送 JSON 有效负载,得到 HTTPError 400
【发布时间】:2012-12-12 16:01:55
【问题描述】:

这是一个代码示例:

# Not actual payload, but exact same structure.  Verified that payload is correct.
payload = {
    'object': {
        'token': '6867r474850557',
        'contact': {
            'FirstName': 'Jim',
            'LastName': 'Bob',
            'Email': 'email@fmail.com',
            'Phone': '111-111-1111'
        },
        'request': {
            'Subject': 'Hello!',
            'Message': 'Test Message'
        },
        'fields': [ "LastName", "FirstName" ]
    }
}

r = urllib2.Request("https://someawesomeurl.com", json.dumps(payload), {"Content-type": "application/json"})
f = urllib2.urlopen(r)
resp = f.read()

调用 urlopen 失败,错误为 urllib2.HTTPError: HTTP Error 400: Bad Request。我猜我没有正确发送 JSON 有效负载,但我不确定我必须做些什么来纠正它。

编辑 这是我试图在 Python 中实现的有效 PHP 实现:

$url = 'https://someawesomeurl.com';

$body = array (
    'object' => array(
    'token' => '6867r474850557',
        'contact' => array (
            'FirstName' => "Jim",
            'LastName' => "Bob",
            'Email' => "email@fmail.com",
            'Phone' => "111-111-1111"
        ),
        'request' => array (
            'Subject' => "Hello!",
            'Message' => "Test Message"
        ),
    'fields' => array('LastName')
));

$params = json_encode($body);
$curl = curl_init($url);

curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $params);
curl_setopt($curl, CURLOPT_HTTPHEADER, array(  "Content-type: application/json"));

$response = curl_exec($curl);

EDIT #2 urllib2 在发送 JSON 时是否可能正在修改它?我将 urlopen 调用包装在 try/except 块中并打印出 HTTPError's exception message

 [{"message":"Premature end of list at [line:1, column:727]","errorCode":"JSON_PARSER_ERROR"}]

我已经通过 lint 运行 JSON,它返回有效,所以我不知道为什么服务器会抱怨格式错误。

【问题讨论】:

  • 在该页面上尝试了一些建议。将内容长度添加到标头并对有效负载进行 URL 编码而不是使用 json.dumps 会给我同样的错误。
  • 您是否将请求指向一个有效域,该域可以接受您发送的数据。你能在 localhost 上设置一些东西来更好地诊断问题吗?这可能是服务器的更多问题。
  • 是的。我可以通过 PHP(使用 curl)将相同的有效负载发送到相同的地址,并且工作正常。需要 App Engine 的 Python 实现。

标签: python json urllib2


【解决方案1】:

这不适用于 urllib2,您必须“请求”(http 表示人类):

http://pypi.python.org/pypi/requests

文档为您的用例提供示例:http://docs.python-requests.org/en/latest/

我的一个项目中的一个例子:

def query(self, path, **kwargs):
    """the token must be given as GET and args as POST JSON object"""
    encoded_args = urllib.urlencode({"token": self.token})
    url = self.url_tpl % ('/api/%s' % path, encoded_args)
    headers = {'content-type': 'application/json'}

    data = json.dumps(kwargs).encode('utf-8')
    response = requests.post(url, data=data, headers=headers)
    if response.status_code == 200:
        return response.json
    else:
        raise Exception("response status: %s" % response.status_code)

【讨论】:

  • 这对我很有帮助并解决了我尝试以类似方式连接到 SugarCRM 的 API 的问题。引起我注意的一件事是 Sugar 期望“PUT”和 urllib2 只允许“POST”或“GET”,除非您对其进行调整 (stackoverflow.com/questions/111945/…)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-02-02
  • 2014-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-16
相关资源
最近更新 更多