Changeset 626
- Timestamp:
- 09/11/05 13:58:26
- Files:
-
- trunk/cherrypy/_cphttptools.py (modified) (2 diffs)
- trunk/cherrypy/_cpwsgi.py (modified) (1 diff)
- trunk/cherrypy/_cpwsgiserver.py (modified) (6 diffs)
- trunk/cherrypy/config.py (modified) (3 diffs)
- trunk/cherrypy/test/test_core.py (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/cherrypy/_cphttptools.py
r624 r626 45 45 46 46 import cherrypy 47 from cherrypy import _cputil, _cpcgifs 47 from cherrypy import _cputil, _cpcgifs, _cperror, _cpwsgiserver 48 48 from cherrypy.lib import cptools 49 49 … … 373 373 # FieldStorage only recognizes POST, so fake it. 374 374 methenv = {'REQUEST_METHOD': "POST"} 375 forms = _cpcgifs.FieldStorage(fp=request.rfile, 375 try: 376 forms = _cpcgifs.FieldStorage(fp=request.rfile, 376 377 headers=lowerHeaderMap, 377 378 environ=methenv, 378 379 keep_blank_values=1) 380 except _cpwsgiserver.MaxSizeExceeded: 381 # Post data is too big 382 raise _cperror.HTTPStatusError(413) 379 383 380 384 if forms.file: trunk/cherrypy/_cpwsgi.py
r605 r626 159 159 conf("server.threadPool"), 160 160 conf("server.socketHost"), 161 config = cherrypy.config 161 162 ) trunk/cherrypy/_cpwsgiserver.py
r579 r626 42 42 monthname = [None, 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 43 43 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] 44 45 class MaxSizeExceeded(Exception): 46 pass 47 48 class SizeCheckWrapper(object): 49 """ Wrapper around the rfile object. For each data reading method, 50 it reads the data but it checks that the size of the data doesn't 51 except a certain limit 52 """ 53 def __init__(self, rfile, maxlen): 54 self.rfile = rfile 55 self.maxlen = maxlen 56 self.bytes_read = 0 57 def _check_length(self): 58 if self.maxlen and self.bytes_read > self.maxlen: 59 raise MaxSizeExceeded() 60 def read(self, size = None): 61 data = self.rfile.read(size) 62 self.bytes_read += len(data) 63 self._check_length() 64 return data 65 def readline(self, size = None): 66 if size is not None: 67 data = self.rfile.readline(size) 68 self.bytes_read += len(data) 69 self._check_length() 70 return data 71 72 # User didn't specify a size ... 73 # We read the line in chunks to make sure it's not a 100MB line ! 74 res = [] 75 while True: 76 data = self.rfile.readline(256) 77 self.bytes_read += len(data) 78 self._check_length() 79 res.append(data) 80 if len(data) < 256: 81 return ''.join(data) 82 def close(self): 83 self.rfile.close() 44 84 45 85 … … 56 96 self.outheaderkeys = None 57 97 self.rfile = self.socket.makefile("r", self.server.bufsize) 98 if self.server.config: 99 mhs = self.server.config.get( 100 'server.maxRequestHeaderSize', 101 500 * 1024) # 500KB by default 102 self.rfile = SizeCheckWrapper(self.rfile, mhs) 58 103 self.wfile = self.socket.makefile("w", self.server.bufsize) 59 104 self.sent_headers = False … … 99 144 self.environ[envname] = v 100 145 self.ready = True 146 147 # Request header is parsed 148 # We prepare the SizeCheckWrapper for the request body 149 if self.server.config: 150 mbs = self.server.config.get( 151 'server.maxRequestBodySize', 152 100 * 1024 * 1024, # 100MB by default 153 path = path) 154 self.rfile.bytes_read = 0 155 self.rfile.maxlen = mbs 101 156 102 157 def start_response(self, status, headers, exc_info = None): … … 181 236 else: 182 237 raise 238 except MaxSizeExceeded: 239 str = "Request Entity Too Large" 240 proto = request.environ.get("SERVER_PROTOCOL", "HTTP/1.0") 241 request.wfile.write("%s 413 %s\r\n" % (proto, str)) 242 request.wfile.write("Content-Length: %s\r\n\r\n" % len(str)) 243 request.wfile.write(str) 244 request.wfile.flush() 183 245 except: 184 246 traceback.print_exc() … … 190 252 version = "CherryPy/2.1.0-beta" 191 253 def __init__(self, bind_addr, wsgi_app, numthreads=10, server_name=None, 192 stderr=sys.stderr, bufsize=-1, max=-1): 254 stderr=sys.stderr, bufsize=-1, max=-1, 255 config = None): 193 256 ''' 194 257 be careful w/ max … … 198 261 self.bind_addr = bind_addr 199 262 self.numthreads = numthreads or 1 263 self.config = config 200 264 if server_name: 201 265 self.server_name = server_name trunk/cherrypy/config.py
r605 r626 55 55 'server.reverseDNS': False, 56 56 'server.threadPool': 0, 57 58 'server.maxRequestSize' : 0, # 0 == unlimited59 57 } 60 58 … … 89 87 _load(file, override) 90 88 91 def get(key, defaultValue=None, returnSection=False ):89 def get(key, defaultValue=None, returnSection=False, path = None): 92 90 """Return the configuration value corresponding to key 93 91 If specified, return defaultValue on lookup failure. If returnSection is … … 96 94 # Look, ma, no Python function calls! Uber-fast. 97 95 98 try: 99 path = cherrypy.request.path 100 except AttributeError: 101 # There's no request.path yet, so use the global settings. 102 path = "global" 103 96 if path is None: 97 try: 98 path = cherrypy.request.path 99 except AttributeError: 100 # There's no request.path yet, so use the global settings. 101 path = "global" 102 104 103 while True: 105 104 if path == "": trunk/cherrypy/test/test_core.py
r624 r626 236 236 return cherrypy.request.body 237 237 238 239 238 class Cookies(Test): 240 239 … … 248 247 cherrypy.response.simpleCookie[name] = cookie.value 249 248 249 class MaxRequestSize(Test): 250 251 def index(self): 252 return "OK" 253 254 def upload(self, file): 255 return "Size: %s" % len(file.file.read()) 250 256 251 257 logFile = os.path.join(localDir, "error.log") … … 633 639 self.assertHeader('Set-Cookie', 'Last=Piranha;') 634 640 641 def testMaxRequestSize(self): 642 self.getPage("/maxrequestsize/index") 643 self.assertBody("OK") 644 cherrypy.config.update({'server.maxRequestHeaderSize': 10}) 645 self.getPage("/maxrequestsize/index") 646 self.assertStatus("413 Request Entity Too Large") 647 self.assertBody("Request Entity Too Large") 648 cherrypy.config.update({'server.maxRequestHeaderSize': 0}) 649 650 # Test upload 651 h = [("Content-type", "multipart/form-data; boundary=x"), 652 ("Content-Length", "110")] 653 b = """--x 654 Content-Disposition: form-data; name="file"; filename="hello.txt" 655 Content-Type: text/plain 656 657 hello 658 --x-- 659 """ 660 self.getPage('/maxrequestsize/upload', h, "POST", b) 661 self.assertBody('Size: 5') 662 cherrypy.config.update({ 663 '/maxrequestsize': {'server.maxRequestBodySize': 3}}) 664 self.getPage('/maxrequestsize/upload', h, "POST", b) 665 self.assertStatus("413 Request Entity Too Large") 666 self.assertInBody("Request Entity Too Large") 635 667 636 668 if __name__ == '__main__':

