SledgeHammer
SledgeHammer

Reputation: 7736

sending Xml Request

I've spent a total of 30 minutes in python lol, so take that into consideration when you answer lol:

I'm trying to send an HTTP POST request with a body and reading the response. I'm using Python 3.6.5 on Windows 10. This is what I have so far:

import http.client import xml.dom.minidom

HOST = "www.mysite.com"
API_URL = "/service"

def do_request(xml_location):

request = open(xml_location, "r").read()

webservice = http.client.HTTPConnection(HOST)

webservice.request("POST", API_URL)

webservice.putheader("Host", HOST)
webservice.putheader("User-Agent", "Python Post")
webservice.putheader("Content-type", "text/xml; charset=\"UTF-8\"")
webservice.putheader("Content-length", "%d" % len(request))
webservice.endheaders()

webservice.send(request)

statuscode, statusmessage, header = webservice.getreply()

result = webservice.getfile().read()
resultxml = xml.dom.minidom.parseString(result)

print (statuscode, statusmessage, header)
print (resultxml.toprettyxml())

with open("output-%s" % xml_location, "w") as xmlfile:
    xmlfile.write(resultxml.toprettyxml())

do_request("test.xml")

test.xml contains the XML request. When I run, I get an error:

Traceback (most recent call last):
  File "C:\Users\xxx\Documents\test.py", line 33, in <module>
    do_request("test.xml")
  File "C:\Users\xxx\Documents\test.py", line 14, in do_request
    webservice.putheader("Host", HOST)
  File "C:\Users\xxx\AppData\Local\Programs\Python\Python36\lib\http\client.py", line 1201, in putheader
    raise CannotSendHeader()
http.client.CannotSendHeader

Upvotes: 0

Views: 1383

Answers (1)

abarnert
abarnert

Reputation: 366103

Your problem is that you mixed up the request and putrequest methods. (Not surprisingly, given the brevity and sparsity of the documentation… most modules in Python are documented a lot better than this, so don't let that worry you about the future.)

The request method is a convenience function that adds the request line, all the headers, and the data all in one go. After you've done that, it's way too late to add a header, hence the error message.

So, you can fix it either way.


(1) Change it to use putrequest. I realize there's no example using putrequest or putheader anywhere in the docs, but it looks like this:

webservice.putrequest("POST", API_URL)

webservice.putheader("Host", HOST)
webservice.putheader("User-Agent", "Python Post")
webservice.putheader("Content-type", "text/xml; charset=\"UTF-8\"")
webservice.putheader("Content-length", "%d" % len(request))
webservice.endheaders()

webservice.send(request)

(2) Change it to use request. This is what all the examples in the docs do; you just need to build up a dict of headers to pass to it:

headers = {
    "Host": HOST,
    "User-Agent": "Python Post",
    "Content-type", "text/xml; charset=\"UTF-8\"",
    "Content-length", "%d" % len(request)
}
webservice.request("POST", API_URL, headers=headers, body=request)

(3) Read this at the top of the docs:

This module defines classes which implement the client side of the HTTP and HTTPS protocols. It is normally not used directly — the module urllib.request uses it to handle URLs that use HTTP and HTTPS.

See also The Requests package is recommended for a higher-level HTTP client interface.

For most real-life cases, you want to use requests if you can use a third-party library, and urllib.request if you can't. They're both simpler, and better documented.

Upvotes: 1

Related Questions