New submission from Martin Panter: According to the documentation, HTTPSConnection.request() should accept arbitrary bytes-like objects, but this is not the case. Currently (since Issue 23756), a “bytes-like object” is defined to be anything that works with Python’s buffer API, as long as it is C-contiguous. These objects can be passed to socket.sendall():
>>> byteslike = (ctypes.c_ubyte * 6).from_buffer_copy(b"DATA\r\n") >>> s = socket.create_connection(("localhost", 80)) >>> s.sendall(byteslike) # Server receives b"DATA\r\n" This is not explicitly documented for socket objects. But since Issue 23539 (3.4+), HTTPConnection.request() does document support for bytes-like objects: >>> h = HTTPConnection("localhost", 80) >>> # Send Content-Length: 6 and body b"DATA\r\n" >>> h.request("POST", "/", body=byteslike) On its own, there is no problem with Python relying on its own undocumented behaviour. But Python’s “ssl” module does not support arbitrary bytes-like objects, and as a result neither does HTTPSConnection: >>> s = ssl.wrap_socket(socket.create_connection(("localhost", 443))) >>> s.sendall(byteslike) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/lib/python3.5/ssl.py", line 886, in sendall v = self.send(data[count:]) File "/usr/lib/python3.5/ssl.py", line 856, in send return self._sslobj.write(data) File "/usr/lib/python3.5/ssl.py", line 581, in write return self._sslobj.write(data) TypeError: a bytes-like object is required, not 'list' >>> c = ssl.create_default_context(cafile="/lib/python3.5/test/keycert.pem") >>> h = HTTPSConnection("localhost", 443, context=c) >>> h.request("POST", "/", body=byteslike) Traceback (most recent call last): File "/usr/lib/python3.5/http/client.py", line 885, in send self.sock.sendall(data) File "/usr/lib/python3.5/ssl.py", line 886, in sendall v = self.send(data[count:]) File "/usr/lib/python3.5/ssl.py", line 856, in send return self._sslobj.write(data) File "/usr/lib/python3.5/ssl.py", line 581, in write return self._sslobj.write(data) TypeError: a bytes-like object is required, not 'list' During handling of the above exception, another exception occurred: Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/lib/python3.5/http/client.py", line 1083, in request self._send_request(method, url, body, headers) File "/usr/lib/python3.5/http/client.py", line 1128, in _send_request self.endheaders(body) File "/usr/lib/python3.5/http/client.py", line 1079, in endheaders self._send_output(message_body) File "/usr/lib/python3.5/http/client.py", line 913, in _send_output self.send(message_body) File "/usr/lib/python3.5/http/client.py", line 892, in send "or an iterable, got %r" % type(data)) TypeError: data should be a bytes-like object or an iterable, got <class '__main__.c_ubyte_Array_6'> This could be fixed in the implementation of SSLSocket.sendall(). But I am not sure if that is an appropriate change for 3.5. Another option would be to adjust the documentation of HTTP(S)Connection in 3.5, either not mentioning bytes-like objects at all, or clarifying that they don’t work with SSL. ---------- assignee: docs@python components: Documentation, Library (Lib) messages: 268707 nosy: docs@python, martin.panter priority: normal severity: normal status: open title: bytes-like objects with socket.sendall(), SSL, and http.client versions: Python 3.5, Python 3.6 _______________________________________ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue27340> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com