urllib2 POST problem

darran darran at edmstudio.com
Wed Sep 19 15:58:38 EDT 2007


I'm struggling with using urllib2 to access the Harvest time-tracking
web service (http://www.getharvest.com/api).  GET is working fine.
POST is giving me a problem.  Here is an example that creates a new
time-tracking entry using curl.

$ curl http://subdomain.harvestapp.com/daily/add -H 'Accept:
application/xml' \
  -H 'Content-Type: application/xml' \
  -u myusername:mypassword \
  -d '<request><notes>testing API</notes><hours>3.5</
hours><project_id>65750</project_id><task_id>79702</
task_id><spent_at>Thu, 13 Sep 2007</spent_at></request>'

Here's a selection of info from running the above with --verbose
output:

* About to connect() to edmstudio.harvestapp.com port 80
> POST /daily/add HTTP/1.1
> Authorization: Basic xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
> Accept: application/xml
> Content-Type: application/xml
> Content-Length: 154
>
> <request><notes>testing API</notes><hours>3.5</hours><project_id>65750</project_id><task_id>79702</task_id><spent_at>Thu, 13 Sep 2007</spent_at></request>HTTP/1.1 201 Created

Notice that 1) it is a POST, and 2) the data is going across as an
unencoded (xml) string.  Now here is my attempt to achieve this with
python's urllib2:

entry = "<request><notes>testing API</notes><hours>3.5</
hours><project_id>65750</project_id><task_id>79702</
task_id><spent_at>Thu, 13 Sep 2007</spent_at></request>"

import urllib2
import base64
opener = urllib2.build_opener()
opener.addheaders = [
    ('Content-Type', 'application/xml'),
    ('Accept', 'application/xml'),
    ('Authorization', 'Basic %s' \
     % base64.encodestring('%s:%s' % (myusername, mypassword)))]

# this GET works just fine - proof that authentication is correct
req = urllib2.Request(url='http://subdomain.harvestapp.com/daily')
response = opener.open(req)
print response.read()

# this POST (same data as the above curl example) fails with an
internal server error (500)
req = urllib2.Request(url='http://subdomain.harvestapp.com/daily/add',
data=entry)
response = opener.open(req)
print response.read()

I'm stumped.  As always, any help is much appreciated.




More information about the Python-list mailing list