title: Posting raw data with Python
body: <p>I'm playing around with the Google Checkout API and I want to pull it into a Django app. I need to post data to Google using basic http authentication. I've been testing this with <code>curl</code> like this:</p>
  
  <pre><code>curl -d "$(cat mytest.xml)" -u username:password https://url
  </code></pre>
  
  <p>And that posts the content of my test XML file to Google. And it works fine!</p>
  
  <p>But I'm having problems porting that simple line to Python. I've managed several different ways (httplib2, urllib2, pycurl) of connecting with a password and posting something but the respose is always 400 BAD REQUEST.</p>
  
  <p>Is there a python equivalent for posting block of text to a HTTP Basic auth server? I'm running out of walls to bang my head against.</p>
  
  <hr>
  
  <p>Apologies for not adding any code. Here are some of my greatest hits. In each, <code>DATA</code> is an XML string. <code>URL</code>, <code>USERNAME</code> and <code>PASSWORD</code> are constant.</p>
  
  <pre><code>req = urllib2.Request(URL)
  req.add_header("Authorization", "Basic %s" % base64.encodestring('%s:%s'%(USERNAME, PASSWORD)))
  u = urllib2.urlopen(req, DATA)
  </code></pre>
  
  <p>Gives me a lovely <code>HTTP Error 400: Bad Request</code></p>
  
  <hr>
  
  <pre><code>passman = urllib2.HTTPPasswordMgrWithDefaultRealm()
  passman.add_password(None, URL, USERNAME, PASSWORD)
  authhandler = urllib2.HTTPBasicAuthHandler(passman)
  opener = urllib2.build_opener(authhandler)
  urllib2.install_opener(opener)
  pagehandle = urllib2.urlopen(URL, DATA)
  </code></pre>
  
  <p>Gives <code>HTTP Error 401: Unauthorized</code></p>
  
  <hr>
  
  <pre><code>pycurl.global_init(pycurl.GLOBAL_DEFAULT)
  c = pycurl.Curl()
  c.setopt(pycurl.URL, URL)
  c.setopt(pycurl.USERPWD, "%s:%s" % (USERNAME,PASSWORD))
  c.setopt(pycurl.POST, 1)
  c.setopt(pycurl.HTTPHEADER, ["Content-type: text/xml"])
  c.setopt(pycurl.POSTFIELDS, DATA)
  b = StringIO.StringIO()
  c.setopt(pycurl.WRITEFUNCTION, b.write)
  c.perform()
  </code></pre>
  
  <p>Seems to struggle with passing the <code>DATA</code> string as a POSTFIELD. I've tried <code>urllib.urlencode()</code>ing DATA in several different ways but </p>
  
  <hr>
  
  <pre><code>h = httplib2.Http()
  h.add_credentials(USERNAME, PASSWORD)
  print = h.request(URL, "POST", body=base64.encodestring(DATA))
  </code></pre>
  
  <p>The credentials don't seem to do anything - I get an unauthorised message back from Google.</p>
  
  <p>There are more but they're all based on these.</p>