Fix 500 in versioned writes with bad Destination
When this code lived in the proxy, it was protected by an "except HTTPException" clause in proxy.Application.handle_request(). When it moved to middleware, it lost that, and then things like constraints.check_name_format that raised HTTPException would cause 500s. The HTTPException would make it all the way out to catch_errors and get translated to a 500. This commit just wraps a couple try/excepts around the bits in versioned writes that can raise HTTPException. I tried to make it use wsgify so I could get that for free, but that wound up being a real pain because env/start_response are plumbed through pretty much the whole versioned-writes middleware. Closes-Bug: 1483705 Change-Id: Ife165bf709e64f313ed07c779b21914045e51f25
This commit is contained in:
parent
eb62f1b379
commit
7064706b27
@ -119,7 +119,7 @@ from swift.common.utils import get_logger, Timestamp, json, \
|
|||||||
register_swift_info, config_true_value
|
register_swift_info, config_true_value
|
||||||
from swift.common.request_helpers import get_sys_meta_prefix
|
from swift.common.request_helpers import get_sys_meta_prefix
|
||||||
from swift.common.wsgi import WSGIContext, make_pre_authed_request
|
from swift.common.wsgi import WSGIContext, make_pre_authed_request
|
||||||
from swift.common.swob import Request
|
from swift.common.swob import Request, HTTPException
|
||||||
from swift.common.constraints import (
|
from swift.common.constraints import (
|
||||||
check_account_format, check_container_format, check_destination_header)
|
check_account_format, check_container_format, check_destination_header)
|
||||||
from swift.proxy.controllers.base import get_container_info
|
from swift.proxy.controllers.base import get_container_info
|
||||||
@ -468,12 +468,18 @@ class VersionedWritesMiddleware(object):
|
|||||||
# container_info
|
# container_info
|
||||||
allow_versioned_writes = self.conf.get('allow_versioned_writes')
|
allow_versioned_writes = self.conf.get('allow_versioned_writes')
|
||||||
if allow_versioned_writes and container and not obj:
|
if allow_versioned_writes and container and not obj:
|
||||||
return self.container_request(req, start_response,
|
try:
|
||||||
allow_versioned_writes)
|
return self.container_request(req, start_response,
|
||||||
|
allow_versioned_writes)
|
||||||
|
except HTTPException as error_response:
|
||||||
|
return error_response(env, start_response)
|
||||||
elif obj and req.method in ('PUT', 'COPY', 'DELETE'):
|
elif obj and req.method in ('PUT', 'COPY', 'DELETE'):
|
||||||
return self.object_request(
|
try:
|
||||||
req, version, account, container, obj,
|
return self.object_request(
|
||||||
allow_versioned_writes)(env, start_response)
|
req, version, account, container, obj,
|
||||||
|
allow_versioned_writes)(env, start_response)
|
||||||
|
except HTTPException as error_response:
|
||||||
|
return error_response(env, start_response)
|
||||||
else:
|
else:
|
||||||
return self.app(env, start_response)
|
return self.app(env, start_response)
|
||||||
|
|
||||||
|
@ -108,11 +108,8 @@ class VersionedWritesTestCase(unittest.TestCase):
|
|||||||
req = Request.blank('/v1/a/c',
|
req = Request.blank('/v1/a/c',
|
||||||
headers={'X-Versions-Location': 'ver_cont'},
|
headers={'X-Versions-Location': 'ver_cont'},
|
||||||
environ={'REQUEST_METHOD': method})
|
environ={'REQUEST_METHOD': method})
|
||||||
try:
|
status, headers, body = self.call_vw(req)
|
||||||
status, headers, body = self.call_vw(req)
|
self.assertEquals(status, "412 Precondition Failed")
|
||||||
except swob.HTTPException as e:
|
|
||||||
pass
|
|
||||||
self.assertEquals(e.status_int, 412)
|
|
||||||
|
|
||||||
# GET/HEAD performs as normal
|
# GET/HEAD performs as normal
|
||||||
self.app.register('GET', '/v1/a/c', swob.HTTPOk, {}, 'passed')
|
self.app.register('GET', '/v1/a/c', swob.HTTPOk, {}, 'passed')
|
||||||
@ -414,6 +411,17 @@ class VersionedWritesTestCase(unittest.TestCase):
|
|||||||
self.assertEqual(len(self.authorized), 1)
|
self.assertEqual(len(self.authorized), 1)
|
||||||
self.assertRequestEqual(req, self.authorized[0])
|
self.assertRequestEqual(req, self.authorized[0])
|
||||||
|
|
||||||
|
def test_copy_new_version_bogus_account(self):
|
||||||
|
cache = FakeCache({'sysmeta': {'versions-location': 'ver_cont'}})
|
||||||
|
req = Request.blank(
|
||||||
|
'/v1/src_a/src_cont/src_obj',
|
||||||
|
environ={'REQUEST_METHOD': 'COPY', 'swift.cache': cache,
|
||||||
|
'CONTENT_LENGTH': '100'},
|
||||||
|
headers={'Destination': 'tgt_cont/tgt_obj',
|
||||||
|
'Destination-Account': '/im/on/a/boat'})
|
||||||
|
status, headers, body = self.call_vw(req)
|
||||||
|
self.assertEquals(status, '412 Precondition Failed')
|
||||||
|
|
||||||
def test_delete_first_object_success(self):
|
def test_delete_first_object_success(self):
|
||||||
self.app.register(
|
self.app.register(
|
||||||
'DELETE', '/v1/a/c/o', swob.HTTPOk, {}, 'passed')
|
'DELETE', '/v1/a/c/o', swob.HTTPOk, {}, 'passed')
|
||||||
|
Loading…
x
Reference in New Issue
Block a user