summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin v. Löwis <martin@v.loewis.de>2006-11-12 10:32:47 +0000
committerMartin v. Löwis <martin@v.loewis.de>2006-11-12 10:32:47 +0000
commit040a927cd14e799454b246dd1f56fd7f4fdff03a (patch)
tree1d7e405492eecb89f90faf3751ee0368a81f2a56
parent1ee79f16e859fd0a6ea3af64a539b5198b8ab7a3 (diff)
downloadcpython-git-040a927cd14e799454b246dd1f56fd7f4fdff03a.tar.gz
Patch #1065257: Support passing open files as body in
HTTPConnection.request().
-rw-r--r--Doc/lib/libhttplib.tex5
-rw-r--r--Lib/httplib.py26
-rw-r--r--Lib/test/test_httplib.py13
-rw-r--r--Misc/NEWS3
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):
diff --git a/Misc/NEWS b/Misc/NEWS
index fdff1c6401..3062bd528a 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -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.