Fix a socket leak in copy middleware

When the "copy" middleware tries to copy a segmented object which is
bigger than max_file_size, it immediatly returns "413 Request Entity Too
Large". But at that point, connections have already been established by
the proxy server to the object servers. These connections must be closed
before returning.

Closes-Bug: #1698207
Change-Id: I430c48c4a81e8392fa271160bcbc1817ef0a88f7
This commit is contained in:
Romain LE DISEZ 2017-06-15 22:09:45 +02:00
parent 6181351a65
commit a7c8becd4e
2 changed files with 10 additions and 3 deletions

View File

@ -413,9 +413,11 @@ class ServerSideCopyMiddleware(object):
# which currently only happens because there are more than
# CONTAINER_LISTING_LIMIT segments in a segmented object. In
# this case, we're going to refuse to do the server-side copy.
close_if_possible(source_resp.app_iter)
return HTTPRequestEntityTooLarge(request=req)
if source_resp.content_length > MAX_FILE_SIZE:
close_if_possible(source_resp.app_iter)
return HTTPRequestEntityTooLarge(request=req)
return source_resp
@ -459,7 +461,6 @@ class ServerSideCopyMiddleware(object):
ssc_ctx = ServerSideCopyWebContext(self.app, self.logger)
source_resp = self._get_source_object(ssc_ctx, source_path, req)
if source_resp.status_int >= HTTP_MULTIPLE_CHOICES:
close_if_possible(source_resp.app_iter)
return source_resp(source_resp.environ, start_response)
# Create a new Request object based on the original request instance.

View File

@ -27,6 +27,7 @@ from swift.common import swob
from swift.common.middleware import copy
from swift.common.storage_policy import POLICIES
from swift.common.swob import Request, HTTPException
from swift.common.utils import closing_if_possible
from test.unit import patch_policies, debug_logger, FakeMemcache, FakeRing
from test.unit.common.middleware.helpers import FakeSwift
from test.unit.proxy.controllers.test_obj import set_http_connect, \
@ -97,6 +98,9 @@ class TestServerSideCopyMiddleware(unittest.TestCase):
})(self.app)
self.ssc.logger = self.app.logger
def tearDown(self):
self.assertEqual(self.app.unclosed_requests, {})
def call_app(self, req, app=None, expect_exception=False):
if app is None:
app = self.app
@ -122,8 +126,10 @@ class TestServerSideCopyMiddleware(unittest.TestCase):
body = ''
caught_exc = None
try:
for chunk in body_iter:
body += chunk
# appease the close-checker
with closing_if_possible(body_iter):
for chunk in body_iter:
body += chunk
except Exception as exc:
if expect_exception:
caught_exc = exc