diff --git a/swift/common/middleware/formpost.py b/swift/common/middleware/formpost.py index 09bf8a1577..dbc2b85d6a 100644 --- a/swift/common/middleware/formpost.py +++ b/swift/common/middleware/formpost.py @@ -278,11 +278,13 @@ class _CappedFileLikeObject(object): self.fp = fp self.max_file_size = max_file_size self.amount_read = 0 + self.file_size_exceeded = False def read(self, size=None): ret = self.fp.read(size) self.amount_read += len(ret) if self.amount_read > self.max_file_size: + self.file_size_exceeded = True raise EOFError('max_file_size exceeded') return ret @@ -290,6 +292,7 @@ class _CappedFileLikeObject(object): ret = self.fp.readline() self.amount_read += len(ret) if self.amount_read > self.max_file_size: + self.file_size_exceeded = True raise EOFError('max_file_size exceeded') return ret @@ -334,7 +337,7 @@ class FormPost(object): status, headers, body = self._translate_form( env, attrs['boundary']) start_response(status, headers) - return body + return [body] except (FormInvalid, EOFError) as err: body = 'FormPost: %s' % err start_response( @@ -492,7 +495,12 @@ class FormPost(object): substatus = [None] subheaders = [None] + wsgi_input = subenv['wsgi.input'] + def _start_response(status, headers, exc_info=None): + if wsgi_input.file_size_exceeded: + raise EOFError("max_file_size exceeded") + substatus[0] = status subheaders[0] = headers diff --git a/test/unit/common/middleware/test_formpost.py b/test/unit/common/middleware/test_formpost.py index 4fa8caa894..338d1129fe 100644 --- a/test/unit/common/middleware/test_formpost.py +++ b/test/unit/common/middleware/test_formpost.py @@ -38,29 +38,34 @@ class FakeApp(object): self.check_no_query_string = check_no_query_string def __call__(self, env, start_response): - if self.check_no_query_string and env.get('QUERY_STRING'): - raise Exception('Query string %s should have been discarded!' % - env['QUERY_STRING']) - body = '' - while True: - chunk = env['wsgi.input'].read() - if not chunk: - break - body += chunk - env['wsgi.input'] = StringIO(body) - self.requests.append(Request.blank('', environ=env)) - if env.get('swift.authorize_override') and \ - env.get('REMOTE_USER') != '.wsgi.pre_authed': - raise Exception( - 'Invalid REMOTE_USER %r with swift.authorize_override' % ( - env.get('REMOTE_USER'),)) - if 'swift.authorize' in env: - resp = env['swift.authorize'](self.requests[-1]) - if resp: - return resp(env, start_response) - status, headers, body = self.status_headers_body_iter.next() - return Response(status=status, headers=headers, - body=body)(env, start_response) + try: + if self.check_no_query_string and env.get('QUERY_STRING'): + raise Exception('Query string %s should have been discarded!' % + env['QUERY_STRING']) + body = '' + while True: + chunk = env['wsgi.input'].read() + if not chunk: + break + body += chunk + env['wsgi.input'] = StringIO(body) + self.requests.append(Request.blank('', environ=env)) + if env.get('swift.authorize_override') and \ + env.get('REMOTE_USER') != '.wsgi.pre_authed': + raise Exception( + 'Invalid REMOTE_USER %r with swift.authorize_override' % ( + env.get('REMOTE_USER'),)) + if 'swift.authorize' in env: + resp = env['swift.authorize'](self.requests[-1]) + if resp: + return resp(env, start_response) + status, headers, body = self.status_headers_body_iter.next() + return Response(status=status, headers=headers, + body=body)(env, start_response) + except EOFError: + start_response('499 Client Disconnect', + [('Content-Type', 'text/plain')]) + return ['Client Disconnect\n'] class TestParseAttrs(unittest.TestCase):