Markus M.
Markus M.

Reputation: 1192

python3 HTTPConnection throws FileNotFoundError

I am trying to create a HTTPConnection using python3 http.client. Here is my code:

import http.client
import base64 
if __name__ == '__main__':
    username = "xx" # enter your username
    password = "xxx" # enter your password
    device_id = "00000000-00000000-00409DFF-FF7660EC" # enter device id of target 
    # Nothing below this line should need to be changed
    # ------------------------------------------------- 

    # create HTTP basic authentication string, this consists of 
    encodestring = '%s:%s' % (username, password)
    auth = base64.encodebytes(encodestring.encode('utf-8'))[:-1]
    # message to send to server
    message = """<sci_request version="1.0"> 
    <send_message> 
      <targets> 
        <device id="%s"/>
      </targets> 
      <rci_request version="1.1">
          <query_state/>
      </rci_request>
    </send_message>
    </sci_request>
    """%(device_id)
    webservice = http.client.HTTPConnection("login.etherios.com ", 80)
    # to what URL to send the request with a given HTTP method
    webservice.putrequest("POST", "/ws/sci")     
    # add the authorization string into the HTTP header
    webservice.putheader("Authorization", "Basic %s" % auth)
    webservice.putheader("Content-type", "text/xml; charset=\"UTF-8\"")
    webservice.putheader("Content-length", "%d" % len(message))
    webservice.endheaders()
    webservice.send(message)
    # get the response
    statuscode, statusmessage, header = webservice.getreply()
    response_body = webservice.getfile().read()
    # print the output to standard out
    print (statuscode, statusmessage)
    print (response_body)

The error message when I run the script is

FileNotFoundError: [Errno 2] No such file or directory

the error points to line 40 (webservice.endheaders()) which I find a bit confusing. Can anybody shed light on the error message?

Here is the full traceback:

In [47]: run import_sensor
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
/usr/lib/python3/dist-packages/IPython/utils/py3compat.py in execfile(fname, glob, loc)
     74     def execfile(fname, glob, loc=None):
     75         loc = loc if (loc is not None) else glob
---> 76         exec(compile(open(fname, 'rb').read(), fname, 'exec'), glob, loc)
     77 
     78     # Refactor print statements in doctests.

/home/markus/python/precirrr-py/precirr/import_sensor.py in <module>()
     38     webservice.putheader("Content-type", "text/xml; charset=\"UTF-8\"")
     39     webservice.putheader("Content-length", "%d" % len(message))
---> 40     webservice.endheaders()
     41     webservice.send(message)
     42     # get the response

/usr/lib/python3.3/http/client.py in endheaders(self, message_body)
   1055         else:
   1056             raise CannotSendHeader()
-> 1057         self._send_output(message_body)
   1058 
   1059     def request(self, method, url, body=None, headers={}):

/usr/lib/python3.3/http/client.py in _send_output(self, message_body)
    900             msg += message_body
    901             message_body = None
--> 902         self.send(msg)
    903         if message_body is not None:
    904             # message_body was not a string (i.e. it is a file), and

/usr/lib/python3.3/http/client.py in send(self, data)
    838         if self.sock is None:
    839             if self.auto_open:
--> 840                 self.connect()
    841             else:
    842                 raise NotConnected()

/usr/lib/python3.3/http/client.py in connect(self)
    816         """Connect to the host and port specified in __init__."""
    817         self.sock = socket.create_connection((self.host,self.port),
--> 818                                              self.timeout, self.source_address)
    819         if self._tunnel_host:
    820             self._tunnel()

/usr/lib/python3.3/socket.py in create_connection(address, timeout, source_address)
    415     host, port = address
    416     err = None
--> 417     for res in getaddrinfo(host, port, 0, SOCK_STREAM):
    418         af, socktype, proto, canonname, sa = res
    419         sock = None

FileNotFoundError: [Errno 2] No such file or directory

Upvotes: 1

Views: 1393

Answers (1)

abarnert
abarnert

Reputation: 365597

The problem is here:

webservice = http.client.HTTPConnection("login.etherios.com ", 80)

That extra space at the end of "login.etherios.com " means it's not a valid DNS name. For example:

>>> socket.getaddrinfo('login.etherios.com', 80, 0, socket.SOCK_STREAM)
[(2, 1, 6, '', ('108.166.22.160', 80))]
>>> socket.getaddrinfo('login.etherios.com ', 80, 0, socket.SOCK_STREAM)
gaierror: [Errno 8] nodename nor servname provided, or not known

(The unfriendly gaierror is being translated to a friendly—but not very accurate—FileNotFoundError farther up the chain, but that's not too important here.)


So, why are you seeing the error come up all the way down in webservice.endheaders()? Well, Python is trying to be smart here. If it opened the socket immediately, then sent one line of data at a time as you provided it, leaving the socket sitting around in between, it would waste CPU and network resources on your machine, probably on the remote server and/or router, maybe even on the internet. It's much better to just open the connection and immediately send the whole request (or, when you have a lot of data, at least up to the end of the headers). So, Python tries to do that for you. Which means that it won't realize you've given it bad information until it actually tries to use it.

Upvotes: 1

Related Questions