diff options
author | Martin v. Löwis <martin@v.loewis.de> | 2006-11-12 10:32:47 +0000 |
---|---|---|
committer | Martin v. Löwis <martin@v.loewis.de> | 2006-11-12 10:32:47 +0000 |
commit | 040a927cd14e799454b246dd1f56fd7f4fdff03a (patch) | |
tree | 1d7e405492eecb89f90faf3751ee0368a81f2a56 | |
parent | 1ee79f16e859fd0a6ea3af64a539b5198b8ab7a3 (diff) | |
download | cpython-git-040a927cd14e799454b246dd1f56fd7f4fdff03a.tar.gz |
Patch #1065257: Support passing open files as body in
HTTPConnection.request().
-rw-r--r-- | Doc/lib/libhttplib.tex | 5 | ||||
-rw-r--r-- | Lib/httplib.py | 26 | ||||
-rw-r--r-- | Lib/test/test_httplib.py | 13 | ||||
-rw-r--r-- | Misc/NEWS | 3 |
4 files changed, 44 insertions, 3 deletions
diff --git a/Doc/lib/libhttplib.tex b/Doc/lib/libhttplib.tex index 049f6c4804..557ee3d0c2 100644 --- a/Doc/lib/libhttplib.tex +++ b/Doc/lib/libhttplib.tex @@ -304,9 +304,14 @@ Example: \code{httplib.responses[httplib.NOT_FOUND]} is \code{'Not Found'}. This will send a request to the server using the HTTP request method \var{method} and the selector \var{url}. If the \var{body} argument is present, it should be a string of data to send after the headers are finished. +Alternatively, it may be an open file object, in which case the +contents of the file is sent; this file object should support +\code{fileno()} and \code{read()} methods. The header Content-Length is automatically set to the correct value. The \var{headers} argument should be a mapping of extra HTTP headers to send with the request. + +\versionchanged[\var{body} can be a file object]{2.6} \end{methoddesc} \begin{methoddesc}{getresponse}{} diff --git a/Lib/httplib.py b/Lib/httplib.py index 5ae5efc916..1e0037f8f8 100644 --- a/Lib/httplib.py +++ b/Lib/httplib.py @@ -704,7 +704,15 @@ class HTTPConnection: if self.debuglevel > 0: print "send:", repr(str) try: - self.sock.sendall(str) + blocksize=8192 + if hasattr(str,'read') : + if self.debuglevel > 0: print "sendIng a read()able" + data=str.read(blocksize) + while data: + self.sock.sendall(data) + data=str.read(blocksize) + else: + self.sock.sendall(str) except socket.error, v: if v[0] == 32: # Broken pipe self.close() @@ -879,7 +887,21 @@ class HTTPConnection: self.putrequest(method, url, **skips) if body and ('content-length' not in header_names): - self.putheader('Content-Length', str(len(body))) + thelen=None + try: + thelen=str(len(body)) + except TypeError, te: + # If this is a file-like object, try to + # fstat its file descriptor + import os + try: + thelen = str(os.fstat(body.fileno()).st_size) + except (AttributeError, OSError): + # Don't send a length if this failed + if self.debuglevel > 0: print "Cannot stat!!" + + if thelen is not None: + self.putheader('Content-Length',thelen) for hdr, value in headers.iteritems(): self.putheader(hdr, value) self.endheaders() diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py index 8d9a706833..90a4e55009 100644 --- a/Lib/test/test_httplib.py +++ b/Lib/test/test_httplib.py @@ -10,9 +10,10 @@ class FakeSocket: def __init__(self, text, fileclass=StringIO.StringIO): self.text = text self.fileclass = fileclass + self.data = '' def sendall(self, data): - self.data = data + self.data += data def makefile(self, mode, bufsize=None): if mode != 'r' and mode != 'rb': @@ -133,6 +134,16 @@ class BasicTest(TestCase): self.fail("Did not expect response from HEAD request") resp.close() + def test_send_file(self): + expected = 'GET /foo HTTP/1.1\r\nHost: example.com\r\n' \ + 'Accept-Encoding: identity\r\nContent-Length:' + + body = open(__file__, 'rb') + conn = httplib.HTTPConnection('example.com') + sock = FakeSocket(body) + conn.sock = sock + conn.request('GET', '/foo', body) + self.assertTrue(sock.data.startswith(expected)) class OfflineTest(TestCase): def test_responses(self): @@ -96,6 +96,9 @@ Core and builtins Library ------- +- Patch #1065257: Support passing open files as body in + HTTPConnection.request(). + - Bug #1569790: mailbox.py: Maildir.get_folder() and MH.get_folder() weren't passing the message factory on to newly created Maildir/MH objects. |