Commits

Robert Brewer committed 2223a68

Backported the (improved) test_post_multipart to the 598 branch.

Comments (0)

Files changed (2)

cherrypy/test/test.py

         'test_tools',
         'test_encoding',
         'test_etags',
+        'test_http',
         'test_httpauth',
         'test_httplib',
         'test_objectmapping',

cherrypy/test/test_http.py

-"""Tests for managing HTTP issues (malformed requests, etc).
-
-Some of these tests check timeouts, etcetera, and therefore take a long
-time to run. Therefore, this module should probably not be included in
-the 'comprehensive' test suite (test.py).
-"""
+"""Tests for managing HTTP issues (malformed requests, etc)."""
 
 from cherrypy.test import test
 test.prefer_parent_path()
 
 import httplib
 import cherrypy
+import mimetypes
+
+
+def encode_multipart_formdata(files):
+    """Return (content_type, body) ready for httplib.HTTP instance.
+    
+    files: a sequence of (name, filename, value) tuples for multipart uploads.
+    """
+    BOUNDARY = '________ThIs_Is_tHe_bouNdaRY_$'
+    L = []
+    for key, filename, value in files:
+        L.append('--' + BOUNDARY)
+        L.append('Content-Disposition: form-data; name="%s"; filename="%s"' %
+                 (key, filename))
+        ct = mimetypes.guess_type(filename)[0] or 'application/octet-stream'
+        L.append('Content-Type: %s' % ct)
+        L.append('')
+        L.append(value)
+    L.append('--' + BOUNDARY + '--')
+    L.append('')
+    body = '\r\n'.join(L)
+    content_type = 'multipart/form-data; boundary=%s' % BOUNDARY
+    return content_type, body
 
 
 def setup_server():
         def index(self, *args, **kwargs):
             return "Hello world!"
         index.exposed = True
+        
+        def post_multipart(self, file):
+            """Return a summary ("a * 1000000\nb * 1000000") of the uploaded file."""
+            contents = file.file.read()
+            summary = []
+            curchar = ""
+            count = 0
+            for c in contents:
+                if c == curchar:
+                    count += 1
+                else:
+                    if count:
+                        summary.append("%s * %d" % (curchar, count))
+                    count = 1
+                    curchar = c
+            if count:
+                summary.append("%s * %d" % (curchar, count))
+            return ", ".join(summary)
+        post_multipart.exposed = True
     
     cherrypy.tree.mount(Root())
-    cherrypy.config.update({'environment': 'test_suite'})
+    cherrypy.config.update({'environment': 'test_suite',
+                            'server.max_request_body_size': 30000000})
 
 
 from cherrypy.test import helper
         c = httplib.HTTPConnection("127.0.0.1:%s" % self.PORT)
         c.request("POST", "/")
         self.assertEqual(c.getresponse().status, 411)
+    
+    def test_post_multipart(self):
+        alphabet = "abcdefghijklmnopqrstuvwxyz"
+        # generate file contents for a large post
+        contents = "".join([c * 1000000 for c in alphabet])
+        
+        # encode as multipart form data
+        files=[('file', 'file.txt', contents)]
+        content_type, body = encode_multipart_formdata(files)
+        
+        # post file
+        if self.scheme == 'https':
+            c = httplib.HTTPS('127.0.0.1:%s' % self.PORT)
+        else:
+            c = httplib.HTTP('127.0.0.1:%s' % self.PORT)
+        c.putrequest('POST', '/post_multipart')
+        c.putheader('Content-Type', content_type)
+        c.putheader('Content-Length', str(len(body)))
+        c.endheaders()
+        c.send(body)
+        
+        errcode, errmsg, headers = c.getreply()
+        self.assertEqual(errcode, 200)
+        
+        response_body = c.file.read()
+        self.assertEquals(", ".join(["%s * 1000000" % c for c in alphabet]),
+                          response_body)
 
 
 if __name__ == '__main__':