Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Curl POST request into pycurl code

I'm trying to convert following curl request into pycurl:

curl -v
-H Accept:application/json \
-H Content-Type:application/json \
-d "{
    name: 'abc',
    path: 'def',
    target: [ 'ghi' ]
}" \
-X POST http://some-url

I have following python code:

import pycurl, json

c = pycurl.Curl()
c.setopt(pycurl.URL, 'http://some-url')
c.setopt(pycurl.HTTPHEADER, ['Accept: application/json'])
data = json.dumps({"name": "abc", "path": "def", "target": "ghi"})
c.setopt(pycurl.POST, 1)
c.setopt(pycurl.POSTFIELDS, data)
c.setopt(pycurl.VERBOSE, 1)
c.perform()
print curl_agent.getinfo(pycurl.RESPONSE_CODE)
c.close()

Executing this I had an error 415: Unsupported media type, so I have changed:

c.setopt(pycurl.HTTPHEADER, ['Accept: application/json'])

into:

c.setopt(pycurl.HTTPHEADER, [ 'Content-Type: application/json' , 'Accept: application/json'])

This time I have 400: Bad request. But bash code with curl works. Do you have any idea what should I fix in python code?

like image 975
Konrad Avatar asked Aug 05 '15 08:08

Konrad


People also ask

Can you use cURL in Python script?

One of the languages it works well with is Python, widely used for its versatility and readability. Together, cURL and Python can help you script API requests, debug complex instances, and retrieve any type of data from web pages.

Is PycURL faster than requests?

Speed - libcurl is very fast and PycURL, being a thin wrapper above libcurl, is very fast as well. PycURL was benchmarked to be several times faster than Requests. Features including multiple protocol support, SSL, authentication and proxy options.

How do you use curl post in Python?

To post JSON data using Curl, you need to set the Content-Type of your request to application/json and pass the JSON data with the -d command line parameter. The JSON content type is set using the -H "Content-Type: application/json" command line parameter. JSON data is passed as a string.

What does cURL do in Python?

In python, a curl is a tool for transferring data requests to and from a server using PycURL. This tool is used for testing REST APIs, downloading files, etc. this PycURL is an interface to the libcURL library in Python, and hence the PycURL is capable of inheriting all the capabilities of libcURL.


2 Answers

In your bash example, the property target is an array, in your Python example it is a string.

Try this:

data = json.dumps({"name": "abc", "path": "def", "target": ["ghi"]})

I also strongly advise you to check out the requests library which has a much nicer API:

import requests
data = {"name": "abc", "path": "def", "target": ["ghi"]}
response = requests.post('http://some-url', json=data)
print response.status_code
like image 115
Daniel Hepper Avatar answered Sep 18 '22 12:09

Daniel Hepper


PycURL is a wrapper on the libcurl library written in C language so its Python API can be bit puzzling. As some people are advocating use of python requests instead I just want to point out that it isn't a perfect replacement. For me, its lack of DNS resolution timeout was a deal breaker. I also find it much slower on my Raspberry Pi. This comparison may be relevant: Python Requests vs PyCurl Performance

So here's something that doesn't evade OP's question:

import pycurl
import json
from cStringIO import StringIO

curl = pycurl.Curl()
curl.setopt(pycurl.URL, 'http://some-url')
curl.setopt(pycurl.HTTPHEADER, ['Accept: application/json',
                                'Content-Type: application/json'])
curl.setopt(pycurl.POST, 1)

# If you want to set a total timeout, say, 3 seconds
curl.setopt(pycurl.TIMEOUT_MS, 3000)

## depending on whether you want to print details on stdout, uncomment either
# curl.setopt(pycurl.VERBOSE, 1) # to print entire request flow
## or
# curl.setopt(pycurl.WRITEFUNCTION, lambda x: None) # to keep stdout clean

# preparing body the way pycurl.READDATA wants it
# NOTE: you may reuse curl object setup at this point
#  if sending POST repeatedly to the url. It will reuse
#  the connection.
body_as_dict = {"name": "abc", "path": "def", "target": "ghi"}
body_as_json_string = json.dumps(body_as_dict) # dict to json
body_as_file_object = StringIO(body_as_json_string)

# prepare and send. See also: pycurl.READFUNCTION to pass function instead
curl.setopt(pycurl.READDATA, body_as_file_object) 
curl.setopt(pycurl.POSTFIELDSIZE, len(body_as_json_string))
curl.perform()

# you may want to check HTTP response code, e.g.
status_code = curl.getinfo(pycurl.RESPONSE_CODE)
if status_code != 200:
    print "Aww Snap :( Server returned HTTP status code {}".format(status_code)

# don't forget to release connection when finished
curl.close()

There are some more interesting features worth checking out in the libcurl curleasy setopts documentation

like image 33
ayush3504 Avatar answered Sep 18 '22 12:09

ayush3504