Sending data Curl/Json in Python

2020-03-24 06:54发布

问题:

I`m trying to make those 2 requests in python:

Request 1:

 curl -X POST -H "Content-Type: application/json" -d '{ "auth_token": "auth1", "widget":   "id1", "title": "Something1",  "text": "Some text", "moreinfo": "Subtitle" }'   serverip

Request 2:

 vsphere_dict = {}
 vsphere_dict['server_name'] = "servername"
 vsphere_dict['api_version'] = apiVersion
 vsphere_dict['guest_count'] = guestCount
 vsphere_dict['guest_on']    = guestOnLen
 vsphere_dict['guest_off']   = guestOffLen

 #Convert output to Json to be sent
 data = json.dumps(vsphere_dict)

 curl -X POST -H "Content-Type: application/json" -d 'data' serverip

Neither of them seems to work. Is there any way I can send them in Python?

Update:

The part that I cannot handle is the pass auth and widget. I have tried the following without success:

import urllib2
import urllib

vsphere_dict = dict(
    server_name="servername",
    api_version="apiVersion",
    guest_count="guestCount",
    guest_on="guestOnLen",
    guest_off="guestOffLen",
)

url = "http://ip:port"

auth = "authid89"
widget = "widgetid1"

# create request object, set url and post data
req = urllib2.Request(auth,url, data=urllib.urlencode(vsphere_dict))
# set header
req.add_header('Content-Type', 'application/json')
# send request
response = urllib2.urlopen(req)**

Resulting in "urllib2.HTTPError: HTTP Error 500: Internal Server Error"

Any ideas how I can pass the auth and widget correctly?

UPDATE:

To see what is different I have started a nc server locally. Here are the results:

Correct curl request using this code:

 curl -X POST -H "Content-Type: application/json" -d '{ "auth_token": "auth", "widget": "widgetid", "title": "Something", "text": "Some text", "moreinfo": "Subtitle" }' http://localhost:8123

sends this which does work:

 POST / HTTP/1.1
 User-Agent: curl/7.21.0 (i386-redhat-linux-gnu) libcurl/7.21.0 NSS/3.12.10.0 zlib/1.2.5  libidn/1.18 libssh2/1.2.4
 Host: localhst:8123
 Accept: */*
 Content-Type: application/json
 Content-Length: 165

 { "auth_token": "token", "widget": "widgetid", "title": "Something", "text": "Some text", "moreinfo": "Subtitle" }

And request using this code

  import requests
  import simplejson as json

  url = "http://localhost:8123"
  data = {'auth_token': 'auth1', 'widget': 'id1', 'title': 'Something1', 'text': 'Some   text', 'moreinfo': 'Subtitle'}
  headers = {'Content-type': 'application/json'}
  r = requests.post(url, data=json.dumps(data), headers=headers)

sends this which does not work:

 POST / HTTP/1.1
 Host: localhst:8123
 Content-Length: 108
 Content-type: application/json
 Accept-Encoding: gzip, deflate, compress
 Accept: */*
 User-Agent: python-requests/2.0.1 CPython/2.7.0 Linux/2.6.35.14-106.fc14.i686

 {"text": "Some text", "auth_token": "auth1", "moreinfo": "Subtitle", "widget": "id1",  "title": "Something1"}

回答1:

Requests provides you with the simplest and yet (very) powerful way to deal with HTTP requests in Python.

Maybe try something like this:

import requests
import simplejson as json

url = "http://ip:port"
data = {'auth_token': 'auth1', 'widget': 'id1', 'title': 'Something1', 'text': 'Some text', 'moreinfo': 'Subtitle'}
headers = {'Content-type': 'application/json'}
r = requests.post(url, data=json.dumps(data), headers=headers)

If the API requests authentication:

r = requests.post(url, data=json.dumps(data), headers=headers, auth=('user', 'pass'))

See [Requests auth] for details.



回答2:

Well sure, using Python-Requests which is a Python library for sending requests like Curl. You can take a look at the Complicated Post Requests section.

Or, if you'd like to use curl inside of Python, you can use pyCurl.



回答3:

why not use urllib2?

import urllib2
import urllib

vsphere_dict = dict(
    server_name="servername",
    api_version=apiVersion,
    guest_count=guestCount,
    guest_on=guestOnLen,
    guest_off=guestOffLen,
)
# create request object, set url and post data
req = urllib2.Request(some_url, data=urllib.urlencode(vsphere_dict))
# set header
req.add_header('Content-Type', 'application/json')
# send request
response = urllib2.urlopen(req)

UPD:

sorry, by i not understand that is auth and widget. Maybe this is also POST data? HTTP Error 500 - can mean that server received not all POST parameters.



回答4:

In the example from the Dashing website, they use:

curl -d '{ "auth_token": "YOUR_AUTH_TOKEN", "current": 100 }' http://localhost:3030/widgets/karma

From the cURL man page, maybe you need to post it as form-urlencoded?

-d, --data

(HTTP) Sends the specified data in a POST request to the HTTP server, in the same way that a browser does when a user has filled in an HTML form and presses the submit button. This will cause curl to pass the data to the server using the content-type application/x-www-form-urlencoded. Compare to -F, --form.

-d, --data is the same as --data-ascii. To post data purely binary, you should instead use the --data-binary option. To URL-encode the value of a form field you may use --data-urlencode.

If any of these options is used more than once on the same command line, the data pieces specified will be merged together with a separating &-symbol. Thus, using '-d name=daniel -d skill=lousy' would generate a post chunk that looks like 'name=daniel&skill=lousy'.

If you start the data with the letter @, the rest should be a file name to read the data from, or - if you want curl to read the data from stdin. Multiple files can also be specified. Posting data from a file named 'foobar' would thus be done with --data @foobar. When --data is told to read from a file like that, carriage returns and newlines will be stripped out.

You might also want to try python-requests http://requests.readthedocs.org/en/latest/user/quickstart/#more-complicated-post-requests

Update: I got it to work

import requests
import json

payload = {'auth_token': 'YOUR_AUTH_TOKEN', 'title': "pythontest"}
r = requests.post("http://localhost:3030/widgets/welcome", data=json.dumps(payload))

print r.text

You need to post the json like a form.