cURL和python请求之间不兼容

时间:2017-10-31 16:34:03

标签: python json curl python-requests

我有以下curl命令,用于连接tplink url(打开智能插件)并按预期工作:

curl  --request POST "https://wap.tplinkcloud.com/?token=[token] HTTP/1.1" \
--data '{"method":"passthrough", "params": {"deviceId": "[deviceid]", "requestData": "{\"system\":{\"set_relay_state\":{\"state\":1}}}" }}' \
--header "Content-Type: application/json"

上面的示例按预期执行(我的tplink smartplug打开)。当试图转换为python请求时,我正在使用它:

url = "https://wap.tplinkcloud.com?token=[token]  HTTP/1.1"

data = "{\"method\":\"passthrough\", \"params\": {\"deviceId\": \"[deviceid]\", \"requestData\": \"{\\\"system\\\":{\\\"set_relay_state\\\":{\\\"state\\\":1}}}\" }}"

headers = {'content-type': 'application/json', 'Accept-Charset': 'UTF-8'}

r = requests.post(url, data=data, headers=headers)
print r.text

我的输出是:

{"error_code":-20651,"msg":"Token expired"}

两个请求都使用相同的令牌和设备ID。

我在两个请求中都使用了httpbin.org,这是我看到的比较:

cURL:

{
  "args": {}, 
  "data": "{\"method\":\"passthrough\", \"params\": {\"deviceId\": \"[deviceid]\", \"requestData\": \"{\\\"system\\\":{\\\"set_relay_state\\\":{\\\"state\\\":1}}}\" }}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Accept": "*/*", 
    "Connection": "close", 
    "Content-Length": "160", 
    "Content-Type": "application/json", 
    "Host": "httpbin.org", 
    "User-Agent": "curl/7.54.0"
  }, 
  "json": {
    "method": "passthrough", 
    "params": {
      "deviceId": "[deviceid]", 
      "requestData": "{\"system\":{\"set_relay_state\":{\"state\":1}}}"
    }
  }, 
  "origin": "[myip]", 
  "url": "http://httpbin.org/post"
}

的Python:

{
  "args": {}, 
  "data": "{\"method\":\"passthrough\", \"params\": {\"deviceId\": \"[deviceid]\", \"requestData\": \"{\\\"system\\\":{\\\"set_relay_state\\\":{\\\"state\\\":1}}}\" }}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Charset": "UTF-8", 
    "Accept-Encoding": "gzip, deflate", 
    "Connection": "close", 
    "Content-Length": "160", 
    "Content-Type": "application/json", 
    "Host": "httpbin.org", 
    "User-Agent": "python-requests/2.18.4"
  }, 
  "json": {
    "method": "passthrough", 
    "params": {
      "deviceId": "[deviceid]", 
      "requestData": "{\"system\":{\"set_relay_state\":{\"state\":1}}}"
    }
  }, 
  "origin": "[myip]", 
  "url": "http://httpbin.org/post"
}

有什么明显的事情我做错了吗?也许我有头问题?

1 个答案:

答案 0 :(得分:0)

是的,你错过了一些明显的东西。

url = "https://wap.tplinkcloud.com?token=[token]  HTTP/1.1"

不是正确的网址。 HTTP/1.1将被解释为令牌的一部分。

一般情况下,我不建议使用JSON字符串文字。使用相应的数据结构并在数据传输时转换为JSON,即在发出HTTP请求或写入文件或数据库之前。至少,这可以确保结构错误(否则会在字符串中不透明)成为编译器错误。

URL参数也是如此,requests模块将透明地处理正确的编码。

import requests
import json

url = "https://wap.tplinkcloud.com"
headers = {"Content-Type": "application/json", "Accept-Charset": "UTF-8"}
params = {"token": "[token]"}

request_data = {"system": {"set_relay_state":{"state":1}}}
data = {
    "method": "passthrough",
    "params": {
        "deviceId": "[deviceid]",
        "requestData": json.dumps(request_data)
    }
}

response = requests.post(url, params=params, data=json.dumps(data), headers=headers)
print response.text