Catch swob responses that are raised.
This lets us get rid of some really repetitive exception conversion code, like everybody that called common.utils.get_param() had to catch a UnicodeDecodeError and turn that into returning HTTPBadRequest. Now get_param() just raises HTTPBadRequest directly, and the __call__ methods in the account/container/object servers catch and return it. All that "except UnicodeDecodeError" stuff goes away. Refactored the path splitting and device validation in the object server too. There are other things that can benefit from this as well, but this patch is big enough. Change-Id: I2be96ef757d04bfd6af180cd9c92393c841db21f
This commit is contained in:
parent
541c189533
commit
df7fc9658b
@ -25,7 +25,8 @@ import swift.common.db
|
||||
from swift.account.utils import account_listing_response, \
|
||||
account_listing_content_type
|
||||
from swift.common.db import AccountBroker, DatabaseConnectionError
|
||||
from swift.common.utils import get_logger, get_param, hash_path, public, \
|
||||
from swift.common.request_helpers import get_param
|
||||
from swift.common.utils import get_logger, hash_path, public, \
|
||||
normalize_timestamp, storage_directory, config_true_value, \
|
||||
validate_device_partition, json, timing_stats, replication
|
||||
from swift.common.constraints import ACCOUNT_LISTING_LIMIT, \
|
||||
@ -35,7 +36,7 @@ from swift.common.swob import HTTPAccepted, HTTPBadRequest, \
|
||||
HTTPCreated, HTTPForbidden, HTTPInternalServerError, \
|
||||
HTTPMethodNotAllowed, HTTPNoContent, HTTPNotFound, \
|
||||
HTTPPreconditionFailed, HTTPConflict, Request, \
|
||||
HTTPInsufficientStorage, HTTPNotAcceptable
|
||||
HTTPInsufficientStorage, HTTPNotAcceptable, HTTPException
|
||||
|
||||
|
||||
DATADIR = 'accounts'
|
||||
@ -176,11 +177,7 @@ class AccountController(object):
|
||||
except ValueError, err:
|
||||
return HTTPBadRequest(body=str(err), content_type='text/plain',
|
||||
request=req)
|
||||
try:
|
||||
query_format = get_param(req, 'format')
|
||||
except UnicodeDecodeError:
|
||||
return HTTPBadRequest(body='parameters not utf8',
|
||||
content_type='text/plain', request=req)
|
||||
query_format = get_param(req, 'format')
|
||||
if query_format:
|
||||
req.accept = FORMAT2CONTENT_TYPE.get(
|
||||
query_format.lower(), FORMAT2CONTENT_TYPE['plain'])
|
||||
@ -218,25 +215,21 @@ class AccountController(object):
|
||||
except ValueError, err:
|
||||
return HTTPBadRequest(body=str(err), content_type='text/plain',
|
||||
request=req)
|
||||
try:
|
||||
prefix = get_param(req, 'prefix')
|
||||
delimiter = get_param(req, 'delimiter')
|
||||
if delimiter and (len(delimiter) > 1 or ord(delimiter) > 254):
|
||||
# delimiters can be made more flexible later
|
||||
return HTTPPreconditionFailed(body='Bad delimiter')
|
||||
limit = ACCOUNT_LISTING_LIMIT
|
||||
given_limit = get_param(req, 'limit')
|
||||
if given_limit and given_limit.isdigit():
|
||||
limit = int(given_limit)
|
||||
if limit > ACCOUNT_LISTING_LIMIT:
|
||||
return HTTPPreconditionFailed(request=req,
|
||||
body='Maximum limit is %d' %
|
||||
ACCOUNT_LISTING_LIMIT)
|
||||
marker = get_param(req, 'marker', '')
|
||||
end_marker = get_param(req, 'end_marker')
|
||||
except UnicodeDecodeError, err:
|
||||
return HTTPBadRequest(body='parameters not utf8',
|
||||
content_type='text/plain', request=req)
|
||||
prefix = get_param(req, 'prefix')
|
||||
delimiter = get_param(req, 'delimiter')
|
||||
if delimiter and (len(delimiter) > 1 or ord(delimiter) > 254):
|
||||
# delimiters can be made more flexible later
|
||||
return HTTPPreconditionFailed(body='Bad delimiter')
|
||||
limit = ACCOUNT_LISTING_LIMIT
|
||||
given_limit = get_param(req, 'limit')
|
||||
if given_limit and given_limit.isdigit():
|
||||
limit = int(given_limit)
|
||||
if limit > ACCOUNT_LISTING_LIMIT:
|
||||
return HTTPPreconditionFailed(request=req,
|
||||
body='Maximum limit is %d' %
|
||||
ACCOUNT_LISTING_LIMIT)
|
||||
marker = get_param(req, 'marker', '')
|
||||
end_marker = get_param(req, 'end_marker')
|
||||
out_content_type, error = account_listing_content_type(req)
|
||||
if error:
|
||||
return error
|
||||
@ -326,6 +319,8 @@ class AccountController(object):
|
||||
res = HTTPMethodNotAllowed()
|
||||
else:
|
||||
res = method(req)
|
||||
except HTTPException as error_response:
|
||||
res = error_response
|
||||
except (Exception, Timeout):
|
||||
self.logger.exception(_('ERROR __call__ error with %(method)s'
|
||||
' %(path)s '),
|
||||
|
@ -17,9 +17,9 @@ import time
|
||||
from xml.sax import saxutils
|
||||
|
||||
from swift.common.constraints import FORMAT2CONTENT_TYPE
|
||||
from swift.common.swob import HTTPOk, HTTPNoContent, HTTPNotAcceptable, \
|
||||
HTTPBadRequest
|
||||
from swift.common.utils import get_param, json, normalize_timestamp
|
||||
from swift.common.swob import HTTPOk, HTTPNoContent, HTTPNotAcceptable
|
||||
from swift.common.request_helpers import get_param
|
||||
from swift.common.utils import json, normalize_timestamp
|
||||
|
||||
|
||||
class FakeAccountBroker(object):
|
||||
@ -50,11 +50,7 @@ def account_listing_content_type(req):
|
||||
Returns a 2-tuple: (content_type, error). Only one of them will be set;
|
||||
the other will be None.
|
||||
"""
|
||||
try:
|
||||
query_format = get_param(req, 'format')
|
||||
except UnicodeDecodeError:
|
||||
return (None, HTTPBadRequest(body='parameters not utf8',
|
||||
content_type='text/plain', request=req))
|
||||
query_format = get_param(req, 'format')
|
||||
if query_format:
|
||||
req.accept = FORMAT2CONTENT_TYPE.get(query_format.lower(),
|
||||
FORMAT2CONTENT_TYPE['plain'])
|
||||
|
47
swift/common/request_helpers.py
Normal file
47
swift/common/request_helpers.py
Normal file
@ -0,0 +1,47 @@
|
||||
# Copyright (c) 2010-2013 OpenStack, LLC.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""
|
||||
Miscellaneous utility functions for use in generating responses.
|
||||
|
||||
Why not swift.common.utils, you ask? Because this way we can import things
|
||||
from swob in here without creating circular imports.
|
||||
"""
|
||||
|
||||
|
||||
from swift.common.swob import HTTPBadRequest
|
||||
|
||||
|
||||
def get_param(req, name, default=None):
|
||||
"""
|
||||
Get parameters from an HTTP request ensuring proper handling UTF-8
|
||||
encoding.
|
||||
|
||||
:param req: request object
|
||||
:param name: parameter name
|
||||
:param default: result to return if the parameter is not found
|
||||
:returns: HTTP request parameter value
|
||||
(as UTF-8 encoded str, not unicode object)
|
||||
:raises: HTTPBadRequest if param not valid UTF-8 byte sequence
|
||||
"""
|
||||
value = req.params.get(name, default)
|
||||
if value and not isinstance(value, unicode):
|
||||
try:
|
||||
value.decode('utf8') # Ensure UTF8ness
|
||||
except UnicodeDecodeError:
|
||||
raise HTTPBadRequest(
|
||||
request=req, content_type='text/plain',
|
||||
body='"%s" parameter not valid UTF-8' % name)
|
||||
return value
|
@ -170,22 +170,6 @@ def load_libc_function(func_name, log_error=True):
|
||||
return noop_libc_function
|
||||
|
||||
|
||||
def get_param(req, name, default=None):
|
||||
"""
|
||||
Get parameters from an HTTP request ensuring proper handling UTF-8
|
||||
encoding.
|
||||
|
||||
:param req: request object
|
||||
:param name: parameter name
|
||||
:param default: result to return if the parameter is not found
|
||||
:returns: HTTP request parameter value
|
||||
"""
|
||||
value = req.params.get(name, default)
|
||||
if value and not isinstance(value, unicode):
|
||||
value.decode('utf8') # Ensure UTF8ness
|
||||
return value
|
||||
|
||||
|
||||
def generate_trans_id(trans_id_suffix):
|
||||
return 'tx%s-%010x%s' % (
|
||||
uuid.uuid4().hex[:21], time.time(), trans_id_suffix)
|
||||
|
@ -25,7 +25,8 @@ from eventlet import Timeout
|
||||
|
||||
import swift.common.db
|
||||
from swift.common.db import ContainerBroker
|
||||
from swift.common.utils import get_logger, get_param, hash_path, public, \
|
||||
from swift.common.request_helpers import get_param
|
||||
from swift.common.utils import get_logger, hash_path, public, \
|
||||
normalize_timestamp, storage_directory, validate_sync_to, \
|
||||
config_true_value, validate_device_partition, json, timing_stats, \
|
||||
replication
|
||||
@ -38,7 +39,7 @@ from swift.common.http import HTTP_NOT_FOUND, is_success
|
||||
from swift.common.swob import HTTPAccepted, HTTPBadRequest, HTTPConflict, \
|
||||
HTTPCreated, HTTPInternalServerError, HTTPNoContent, HTTPNotFound, \
|
||||
HTTPPreconditionFailed, HTTPMethodNotAllowed, Request, Response, \
|
||||
HTTPInsufficientStorage, HTTPNotAcceptable, HeaderKeyDict
|
||||
HTTPInsufficientStorage, HTTPNotAcceptable, HTTPException, HeaderKeyDict
|
||||
|
||||
DATADIR = 'containers'
|
||||
|
||||
@ -298,11 +299,7 @@ class ContainerController(object):
|
||||
except ValueError, err:
|
||||
return HTTPBadRequest(body=str(err), content_type='text/plain',
|
||||
request=req)
|
||||
try:
|
||||
query_format = get_param(req, 'format')
|
||||
except UnicodeDecodeError:
|
||||
return HTTPBadRequest(body='parameters not utf8',
|
||||
content_type='text/plain', request=req)
|
||||
query_format = get_param(req, 'format')
|
||||
if query_format:
|
||||
req.accept = FORMAT2CONTENT_TYPE.get(
|
||||
query_format.lower(), FORMAT2CONTENT_TYPE['plain'])
|
||||
@ -362,27 +359,23 @@ class ContainerController(object):
|
||||
except ValueError, err:
|
||||
return HTTPBadRequest(body=str(err), content_type='text/plain',
|
||||
request=req)
|
||||
try:
|
||||
path = get_param(req, 'path')
|
||||
prefix = get_param(req, 'prefix')
|
||||
delimiter = get_param(req, 'delimiter')
|
||||
if delimiter and (len(delimiter) > 1 or ord(delimiter) > 254):
|
||||
# delimiters can be made more flexible later
|
||||
return HTTPPreconditionFailed(body='Bad delimiter')
|
||||
marker = get_param(req, 'marker', '')
|
||||
end_marker = get_param(req, 'end_marker')
|
||||
limit = CONTAINER_LISTING_LIMIT
|
||||
given_limit = get_param(req, 'limit')
|
||||
if given_limit and given_limit.isdigit():
|
||||
limit = int(given_limit)
|
||||
if limit > CONTAINER_LISTING_LIMIT:
|
||||
return HTTPPreconditionFailed(
|
||||
request=req,
|
||||
body='Maximum limit is %d' % CONTAINER_LISTING_LIMIT)
|
||||
query_format = get_param(req, 'format')
|
||||
except UnicodeDecodeError, err:
|
||||
return HTTPBadRequest(body='parameters not utf8',
|
||||
content_type='text/plain', request=req)
|
||||
path = get_param(req, 'path')
|
||||
prefix = get_param(req, 'prefix')
|
||||
delimiter = get_param(req, 'delimiter')
|
||||
if delimiter and (len(delimiter) > 1 or ord(delimiter) > 254):
|
||||
# delimiters can be made more flexible later
|
||||
return HTTPPreconditionFailed(body='Bad delimiter')
|
||||
marker = get_param(req, 'marker', '')
|
||||
end_marker = get_param(req, 'end_marker')
|
||||
limit = CONTAINER_LISTING_LIMIT
|
||||
given_limit = get_param(req, 'limit')
|
||||
if given_limit and given_limit.isdigit():
|
||||
limit = int(given_limit)
|
||||
if limit > CONTAINER_LISTING_LIMIT:
|
||||
return HTTPPreconditionFailed(
|
||||
request=req,
|
||||
body='Maximum limit is %d' % CONTAINER_LISTING_LIMIT)
|
||||
query_format = get_param(req, 'format')
|
||||
if query_format:
|
||||
req.accept = FORMAT2CONTENT_TYPE.get(query_format.lower(),
|
||||
FORMAT2CONTENT_TYPE['plain'])
|
||||
@ -548,6 +541,8 @@ class ContainerController(object):
|
||||
res = HTTPMethodNotAllowed()
|
||||
else:
|
||||
res = method(req)
|
||||
except HTTPException as error_response:
|
||||
res = error_response
|
||||
except (Exception, Timeout):
|
||||
self.logger.exception(_(
|
||||
'ERROR __call__ error with %(method)s %(path)s '),
|
||||
|
@ -43,7 +43,7 @@ from swift.common.swob import HTTPAccepted, HTTPBadRequest, HTTPCreated, \
|
||||
HTTPInternalServerError, HTTPNoContent, HTTPNotFound, HTTPNotModified, \
|
||||
HTTPPreconditionFailed, HTTPRequestTimeout, HTTPUnprocessableEntity, \
|
||||
HTTPClientDisconnect, HTTPMethodNotAllowed, Request, Response, UTC, \
|
||||
HTTPInsufficientStorage, HTTPForbidden, HeaderKeyDict
|
||||
HTTPInsufficientStorage, HTTPForbidden, HTTPException, HeaderKeyDict
|
||||
from swift.obj.diskfile import DiskFile
|
||||
|
||||
|
||||
@ -276,17 +276,27 @@ class ObjectController(object):
|
||||
'%s-%s/%s/%s' % (delete_at, account, container, obj),
|
||||
host, partition, contdevice, headers_out, objdevice)
|
||||
|
||||
def _parse_path(self, request, minsegs=5, maxsegs=5):
|
||||
"""
|
||||
Utility function to split and validate the request path.
|
||||
|
||||
:returns: result of split_path if everything's okay
|
||||
:raises: HTTPBadRequest if something's not okay
|
||||
"""
|
||||
try:
|
||||
segs = split_path(unquote(request.path), minsegs, maxsegs, True)
|
||||
validate_device_partition(segs[0], segs[1])
|
||||
return segs
|
||||
except ValueError as err:
|
||||
raise HTTPBadRequest(body=str(err), request=request,
|
||||
content_type='text/plain')
|
||||
|
||||
@public
|
||||
@timing_stats()
|
||||
def POST(self, request):
|
||||
"""Handle HTTP POST requests for the Swift Object Server."""
|
||||
try:
|
||||
device, partition, account, container, obj = \
|
||||
split_path(unquote(request.path), 5, 5, True)
|
||||
validate_device_partition(device, partition)
|
||||
except ValueError, err:
|
||||
return HTTPBadRequest(body=str(err), request=request,
|
||||
content_type='text/plain')
|
||||
device, partition, account, container, obj = self._parse_path(request)
|
||||
|
||||
if 'x-timestamp' not in request.headers or \
|
||||
not check_float(request.headers['x-timestamp']):
|
||||
return HTTPBadRequest(body='Missing timestamp', request=request,
|
||||
@ -329,13 +339,8 @@ class ObjectController(object):
|
||||
@timing_stats()
|
||||
def PUT(self, request):
|
||||
"""Handle HTTP PUT requests for the Swift Object Server."""
|
||||
try:
|
||||
device, partition, account, container, obj = \
|
||||
split_path(unquote(request.path), 5, 5, True)
|
||||
validate_device_partition(device, partition)
|
||||
except ValueError, err:
|
||||
return HTTPBadRequest(body=str(err), request=request,
|
||||
content_type='text/plain')
|
||||
device, partition, account, container, obj = self._parse_path(request)
|
||||
|
||||
if 'x-timestamp' not in request.headers or \
|
||||
not check_float(request.headers['x-timestamp']):
|
||||
return HTTPBadRequest(body='Missing timestamp', request=request,
|
||||
@ -428,13 +433,8 @@ class ObjectController(object):
|
||||
@timing_stats()
|
||||
def GET(self, request):
|
||||
"""Handle HTTP GET requests for the Swift Object Server."""
|
||||
try:
|
||||
device, partition, account, container, obj = \
|
||||
split_path(unquote(request.path), 5, 5, True)
|
||||
validate_device_partition(device, partition)
|
||||
except ValueError, err:
|
||||
return HTTPBadRequest(body=str(err), request=request,
|
||||
content_type='text/plain')
|
||||
device, partition, account, container, obj = self._parse_path(request)
|
||||
|
||||
try:
|
||||
disk_file = self._diskfile(device, partition, account, container,
|
||||
obj, keep_data_fp=True, iter_hook=sleep)
|
||||
@ -507,15 +507,8 @@ class ObjectController(object):
|
||||
@timing_stats(sample_rate=0.8)
|
||||
def HEAD(self, request):
|
||||
"""Handle HTTP HEAD requests for the Swift Object Server."""
|
||||
try:
|
||||
device, partition, account, container, obj = \
|
||||
split_path(unquote(request.path), 5, 5, True)
|
||||
validate_device_partition(device, partition)
|
||||
except ValueError, err:
|
||||
resp = HTTPBadRequest(request=request)
|
||||
resp.content_type = 'text/plain'
|
||||
resp.body = str(err)
|
||||
return resp
|
||||
device, partition, account, container, obj = self._parse_path(request)
|
||||
|
||||
try:
|
||||
disk_file = self._diskfile(device, partition, account, container,
|
||||
obj)
|
||||
@ -601,13 +594,8 @@ class ObjectController(object):
|
||||
Handle REPLICATE requests for the Swift Object Server. This is used
|
||||
by the object replicator to get hashes for directories.
|
||||
"""
|
||||
try:
|
||||
device, partition, suffix = split_path(
|
||||
unquote(request.path), 2, 3, True)
|
||||
validate_device_partition(device, partition)
|
||||
except ValueError, e:
|
||||
return HTTPBadRequest(body=str(e), request=request,
|
||||
content_type='text/plain')
|
||||
device, partition, suffix = self._parse_path(request, 2, 3)
|
||||
|
||||
if self.mount_check and not check_mount(self.devices, device):
|
||||
return HTTPInsufficientStorage(drive=device, request=request)
|
||||
path = os.path.join(self.devices, device, DATADIR, partition)
|
||||
@ -642,6 +630,8 @@ class ObjectController(object):
|
||||
res = method(req)
|
||||
except DiskFileCollision:
|
||||
res = HTTPForbidden(request=req)
|
||||
except HTTPException as error_response:
|
||||
res = error_response
|
||||
except (Exception, Timeout):
|
||||
self.logger.exception(_(
|
||||
'ERROR __call__ error with %(method)s'
|
||||
|
@ -145,9 +145,9 @@ class TestAccountController(unittest.TestCase):
|
||||
self.controller.PUT(req)
|
||||
req = Request.blank('/sda1/p/a', environ={'REQUEST_METHOD': 'DELETE',
|
||||
'HTTP_X_TIMESTAMP': '1'})
|
||||
resp = self.controller.DELETE(req)
|
||||
resp = req.get_response(self.controller)
|
||||
req = Request.blank('/sda1/p/a', environ={'REQUEST_METHOD': 'HEAD'})
|
||||
resp = self.controller.HEAD(req)
|
||||
resp = req.get_response(self.controller)
|
||||
self.assertEquals(resp.status_int, 404)
|
||||
self.assertEquals(resp.headers['X-Account-Status'], 'Deleted')
|
||||
|
||||
@ -231,7 +231,7 @@ class TestAccountController(unittest.TestCase):
|
||||
format = '%D1%BD%8A9' # invalid UTF-8; should be %E1%BD%8A9 (E -> D)
|
||||
req = Request.blank('/sda1/p/a?format=' + format,
|
||||
environ={'REQUEST_METHOD': 'HEAD'})
|
||||
resp = self.controller.HEAD(req)
|
||||
resp = req.get_response(self.controller)
|
||||
self.assertEquals(resp.status_int, 400)
|
||||
|
||||
def test_PUT_not_found(self):
|
||||
@ -1251,7 +1251,7 @@ class TestAccountController(unittest.TestCase):
|
||||
for format in ('xml', 'json'):
|
||||
req = Request.blank('/sda1/p/a?format=%s' % format,
|
||||
environ={'REQUEST_METHOD': 'GET'})
|
||||
resp = self.controller.GET(req)
|
||||
resp = req.get_response(self.controller)
|
||||
self.assertEquals(resp.status_int, 200)
|
||||
|
||||
def test_params_utf8(self):
|
||||
@ -1260,7 +1260,7 @@ class TestAccountController(unittest.TestCase):
|
||||
'format'):
|
||||
req = Request.blank('/sda1/p/a?%s=\xce' % param,
|
||||
environ={'REQUEST_METHOD': 'GET'})
|
||||
resp = self.controller.GET(req)
|
||||
resp = req.get_response(self.controller)
|
||||
self.assertEquals(resp.status_int, 400,
|
||||
"%d on param %s" % (resp.status_int, param))
|
||||
# Good UTF8 sequence for delimiter, too long (1 byte delimiters only)
|
||||
|
@ -147,7 +147,7 @@ class TestContainerController(unittest.TestCase):
|
||||
format = '%D1%BD%8A9' # invalid UTF-8; should be %E1%BD%8A9 (E -> D)
|
||||
req = Request.blank('/sda1/p/a/c?format=' + format,
|
||||
environ={'REQUEST_METHOD': 'HEAD'})
|
||||
resp = self.controller.HEAD(req)
|
||||
resp = req.get_response(self.controller)
|
||||
self.assertEquals(resp.status_int, 400)
|
||||
|
||||
def test_PUT(self):
|
||||
@ -1245,7 +1245,7 @@ class TestContainerController(unittest.TestCase):
|
||||
'end_marker', 'format'):
|
||||
req = Request.blank('/sda1/p/a/c?%s=\xce' % param,
|
||||
environ={'REQUEST_METHOD': 'GET'})
|
||||
resp = self.controller.GET(req)
|
||||
resp = req.get_response(self.controller)
|
||||
self.assertEquals(resp.status_int, 400,
|
||||
"%d on param %s" % (resp.status_int, param))
|
||||
# Good UTF8 sequence for delimiter, too long (1 byte delimiters only)
|
||||
|
@ -231,7 +231,7 @@ class TestObjectController(unittest.TestCase):
|
||||
'X-Object-Meta-1': 'One',
|
||||
'X-Object-Meta-2': 'Two',
|
||||
'Content-Type': 'text/plain'})
|
||||
resp = self.object_controller.POST(req)
|
||||
resp = req.get_response(self.object_controller)
|
||||
self.assertEquals(resp.status_int, 404)
|
||||
|
||||
def test_POST_invalid_path(self):
|
||||
@ -241,7 +241,7 @@ class TestObjectController(unittest.TestCase):
|
||||
'X-Object-Meta-1': 'One',
|
||||
'X-Object-Meta-2': 'Two',
|
||||
'Content-Type': 'text/plain'})
|
||||
resp = self.object_controller.POST(req)
|
||||
resp = req.get_response(self.object_controller)
|
||||
self.assertEquals(resp.status_int, 400)
|
||||
|
||||
def test_POST_container_connection(self):
|
||||
@ -341,13 +341,13 @@ class TestObjectController(unittest.TestCase):
|
||||
|
||||
def test_PUT_invalid_path(self):
|
||||
req = Request.blank('/sda1/p/a/c', environ={'REQUEST_METHOD': 'PUT'})
|
||||
resp = self.object_controller.PUT(req)
|
||||
resp = req.get_response(self.object_controller)
|
||||
self.assertEquals(resp.status_int, 400)
|
||||
|
||||
def test_PUT_no_timestamp(self):
|
||||
req = Request.blank('/sda1/p/a/c/o', environ={'REQUEST_METHOD': 'PUT',
|
||||
'CONTENT_LENGTH': '0'})
|
||||
resp = self.object_controller.PUT(req)
|
||||
resp = req.get_response(self.object_controller)
|
||||
self.assertEquals(resp.status_int, 400)
|
||||
|
||||
def test_PUT_no_content_type(self):
|
||||
@ -355,7 +355,7 @@ class TestObjectController(unittest.TestCase):
|
||||
headers={'X-Timestamp': normalize_timestamp(time()),
|
||||
'Content-Length': '6'})
|
||||
req.body = 'VERIFY'
|
||||
resp = self.object_controller.PUT(req)
|
||||
resp = req.get_response(self.object_controller)
|
||||
self.assertEquals(resp.status_int, 400)
|
||||
|
||||
def test_PUT_invalid_content_type(self):
|
||||
@ -364,7 +364,7 @@ class TestObjectController(unittest.TestCase):
|
||||
'Content-Length': '6',
|
||||
'Content-Type': '\xff\xff'})
|
||||
req.body = 'VERIFY'
|
||||
resp = self.object_controller.PUT(req)
|
||||
resp = req.get_response(self.object_controller)
|
||||
self.assertEquals(resp.status_int, 400)
|
||||
self.assert_('Content-Type' in resp.body)
|
||||
|
||||
@ -374,7 +374,7 @@ class TestObjectController(unittest.TestCase):
|
||||
'Content-Type': 'application/octet-stream'})
|
||||
req.body = 'VERIFY'
|
||||
del req.headers['Content-Length']
|
||||
resp = self.object_controller.PUT(req)
|
||||
resp = req.get_response(self.object_controller)
|
||||
self.assertEquals(resp.status_int, 411)
|
||||
|
||||
def test_PUT_zero_content_length(self):
|
||||
@ -383,7 +383,7 @@ class TestObjectController(unittest.TestCase):
|
||||
'Content-Type': 'application/octet-stream'})
|
||||
req.body = ''
|
||||
self.assertEquals(req.headers['Content-Length'], '0')
|
||||
resp = self.object_controller.PUT(req)
|
||||
resp = req.get_response(self.object_controller)
|
||||
self.assertEquals(resp.status_int, 201)
|
||||
|
||||
def test_PUT_common(self):
|
||||
@ -393,7 +393,7 @@ class TestObjectController(unittest.TestCase):
|
||||
'Content-Length': '6',
|
||||
'Content-Type': 'application/octet-stream'})
|
||||
req.body = 'VERIFY'
|
||||
resp = self.object_controller.PUT(req)
|
||||
resp = req.get_response(self.object_controller)
|
||||
self.assertEquals(resp.status_int, 201)
|
||||
objfile = os.path.join(self.testdir, 'sda1',
|
||||
storage_directory(object_server.DATADIR, 'p',
|
||||
@ -414,7 +414,7 @@ class TestObjectController(unittest.TestCase):
|
||||
'Content-Length': '6',
|
||||
'Content-Type': 'application/octet-stream'})
|
||||
req.body = 'VERIFY'
|
||||
resp = self.object_controller.PUT(req)
|
||||
resp = req.get_response(self.object_controller)
|
||||
self.assertEquals(resp.status_int, 201)
|
||||
sleep(.00001)
|
||||
timestamp = normalize_timestamp(time())
|
||||
@ -423,7 +423,7 @@ class TestObjectController(unittest.TestCase):
|
||||
'Content-Type': 'text/plain',
|
||||
'Content-Encoding': 'gzip'})
|
||||
req.body = 'VERIFY TWO'
|
||||
resp = self.object_controller.PUT(req)
|
||||
resp = req.get_response(self.object_controller)
|
||||
self.assertEquals(resp.status_int, 201)
|
||||
objfile = os.path.join(self.testdir, 'sda1',
|
||||
storage_directory(object_server.DATADIR, 'p',
|
||||
@ -444,7 +444,7 @@ class TestObjectController(unittest.TestCase):
|
||||
headers={'X-Timestamp': normalize_timestamp(time()),
|
||||
'Content-Type': 'text/plain'})
|
||||
req.body = 'test'
|
||||
resp = self.object_controller.PUT(req)
|
||||
resp = req.get_response(self.object_controller)
|
||||
self.assertEquals(resp.status_int, 201)
|
||||
|
||||
def test_PUT_invalid_etag(self):
|
||||
@ -453,7 +453,7 @@ class TestObjectController(unittest.TestCase):
|
||||
'Content-Type': 'text/plain',
|
||||
'ETag': 'invalid'})
|
||||
req.body = 'test'
|
||||
resp = self.object_controller.PUT(req)
|
||||
resp = req.get_response(self.object_controller)
|
||||
self.assertEquals(resp.status_int, 422)
|
||||
|
||||
def test_PUT_user_metadata(self):
|
||||
@ -465,7 +465,7 @@ class TestObjectController(unittest.TestCase):
|
||||
'X-Object-Meta-1': 'One',
|
||||
'X-Object-Meta-Two': 'Two'})
|
||||
req.body = 'VERIFY THREE'
|
||||
resp = self.object_controller.PUT(req)
|
||||
resp = req.get_response(self.object_controller)
|
||||
self.assertEquals(resp.status_int, 201)
|
||||
objfile = os.path.join(self.testdir, 'sda1',
|
||||
storage_directory(object_server.DATADIR, 'p',
|
||||
@ -551,12 +551,12 @@ class TestObjectController(unittest.TestCase):
|
||||
|
||||
def test_HEAD(self):
|
||||
""" Test swift.object_server.ObjectController.HEAD """
|
||||
req = Request.blank('/sda1/p/a/c')
|
||||
resp = self.object_controller.HEAD(req)
|
||||
req = Request.blank('/sda1/p/a/c', environ={'REQUEST_METHOD': 'HEAD'})
|
||||
resp = req.get_response(self.object_controller)
|
||||
self.assertEquals(resp.status_int, 400)
|
||||
|
||||
req = Request.blank('/sda1/p/a/c/o')
|
||||
resp = self.object_controller.HEAD(req)
|
||||
req = Request.blank('/sda1/p/a/c/o', environ={'REQUEST_METHOD': 'HEAD'})
|
||||
resp = req.get_response(self.object_controller)
|
||||
self.assertEquals(resp.status_int, 404)
|
||||
|
||||
timestamp = normalize_timestamp(time())
|
||||
@ -566,11 +566,11 @@ class TestObjectController(unittest.TestCase):
|
||||
'X-Object-Meta-1': 'One',
|
||||
'X-Object-Meta-Two': 'Two'})
|
||||
req.body = 'VERIFY'
|
||||
resp = self.object_controller.PUT(req)
|
||||
resp = req.get_response(self.object_controller)
|
||||
self.assertEquals(resp.status_int, 201)
|
||||
|
||||
req = Request.blank('/sda1/p/a/c/o')
|
||||
resp = self.object_controller.HEAD(req)
|
||||
req = Request.blank('/sda1/p/a/c/o', environ={'REQUEST_METHOD': 'HEAD'})
|
||||
resp = req.get_response(self.object_controller)
|
||||
self.assertEquals(resp.status_int, 200)
|
||||
self.assertEquals(resp.content_length, 6)
|
||||
self.assertEquals(resp.content_type, 'application/x-test')
|
||||
@ -587,8 +587,8 @@ class TestObjectController(unittest.TestCase):
|
||||
hash_path('a', 'c', 'o')),
|
||||
timestamp + '.data')
|
||||
os.unlink(objfile)
|
||||
req = Request.blank('/sda1/p/a/c/o')
|
||||
resp = self.object_controller.HEAD(req)
|
||||
req = Request.blank('/sda1/p/a/c/o', environ={'REQUEST_METHOD': 'HEAD'})
|
||||
resp = req.get_response(self.object_controller)
|
||||
self.assertEquals(resp.status_int, 404)
|
||||
|
||||
sleep(.00001)
|
||||
@ -599,7 +599,7 @@ class TestObjectController(unittest.TestCase):
|
||||
'Content-Type': 'application/octet-stream',
|
||||
'Content-length': '6'})
|
||||
req.body = 'VERIFY'
|
||||
resp = self.object_controller.PUT(req)
|
||||
resp = req.get_response(self.object_controller)
|
||||
self.assertEquals(resp.status_int, 201)
|
||||
|
||||
sleep(.00001)
|
||||
@ -607,11 +607,11 @@ class TestObjectController(unittest.TestCase):
|
||||
req = Request.blank('/sda1/p/a/c/o',
|
||||
environ={'REQUEST_METHOD': 'DELETE'},
|
||||
headers={'X-Timestamp': timestamp})
|
||||
resp = self.object_controller.DELETE(req)
|
||||
resp = req.get_response(self.object_controller)
|
||||
self.assertEquals(resp.status_int, 204)
|
||||
|
||||
req = Request.blank('/sda1/p/a/c/o')
|
||||
resp = self.object_controller.HEAD(req)
|
||||
req = Request.blank('/sda1/p/a/c/o', environ={'REQUEST_METHOD': 'HEAD'})
|
||||
resp = req.get_response(self.object_controller)
|
||||
self.assertEquals(resp.status_int, 404)
|
||||
|
||||
def test_HEAD_quarantine_zbyte(self):
|
||||
@ -621,7 +621,7 @@ class TestObjectController(unittest.TestCase):
|
||||
headers={'X-Timestamp': timestamp,
|
||||
'Content-Type': 'application/x-test'})
|
||||
req.body = 'VERIFY'
|
||||
resp = self.object_controller.PUT(req)
|
||||
resp = req.get_response(self.object_controller)
|
||||
self.assertEquals(resp.status_int, 201)
|
||||
file = diskfile.DiskFile(self.testdir, 'sda1', 'p', 'a', 'c', 'o',
|
||||
FakeLogger(), keep_data_fp=True)
|
||||
@ -634,8 +634,8 @@ class TestObjectController(unittest.TestCase):
|
||||
diskfile.write_metadata(fp, metadata)
|
||||
|
||||
self.assertEquals(os.listdir(file.datadir)[0], file_name)
|
||||
req = Request.blank('/sda1/p/a/c/o')
|
||||
resp = self.object_controller.HEAD(req)
|
||||
req = Request.blank('/sda1/p/a/c/o', environ={'REQUEST_METHOD': 'HEAD'})
|
||||
resp = req.get_response(self.object_controller)
|
||||
self.assertEquals(resp.status_int, 404)
|
||||
|
||||
quar_dir = os.path.join(self.testdir, 'sda1', 'quarantined', 'objects',
|
||||
@ -644,12 +644,12 @@ class TestObjectController(unittest.TestCase):
|
||||
|
||||
def test_GET(self):
|
||||
""" Test swift.object_server.ObjectController.GET """
|
||||
req = Request.blank('/sda1/p/a/c')
|
||||
resp = self.object_controller.GET(req)
|
||||
req = Request.blank('/sda1/p/a/c', environ={'REQUEST_METHOD': 'GET'})
|
||||
resp = req.get_response(self.object_controller)
|
||||
self.assertEquals(resp.status_int, 400)
|
||||
|
||||
req = Request.blank('/sda1/p/a/c/o')
|
||||
resp = self.object_controller.GET(req)
|
||||
req = Request.blank('/sda1/p/a/c/o', environ={'REQUEST_METHOD': 'GET'})
|
||||
resp = req.get_response(self.object_controller)
|
||||
self.assertEquals(resp.status_int, 404)
|
||||
|
||||
timestamp = normalize_timestamp(time())
|
||||
@ -659,11 +659,11 @@ class TestObjectController(unittest.TestCase):
|
||||
'X-Object-Meta-1': 'One',
|
||||
'X-Object-Meta-Two': 'Two'})
|
||||
req.body = 'VERIFY'
|
||||
resp = self.object_controller.PUT(req)
|
||||
resp = req.get_response(self.object_controller)
|
||||
self.assertEquals(resp.status_int, 201)
|
||||
|
||||
req = Request.blank('/sda1/p/a/c/o')
|
||||
resp = self.object_controller.GET(req)
|
||||
req = Request.blank('/sda1/p/a/c/o', environ={'REQUEST_METHOD': 'GET'})
|
||||
resp = req.get_response(self.object_controller)
|
||||
self.assertEquals(resp.status_int, 200)
|
||||
self.assertEquals(resp.body, 'VERIFY')
|
||||
self.assertEquals(resp.content_length, 6)
|
||||
@ -677,23 +677,23 @@ class TestObjectController(unittest.TestCase):
|
||||
self.assertEquals(resp.headers['x-object-meta-1'], 'One')
|
||||
self.assertEquals(resp.headers['x-object-meta-two'], 'Two')
|
||||
|
||||
req = Request.blank('/sda1/p/a/c/o')
|
||||
req = Request.blank('/sda1/p/a/c/o', environ={'REQUEST_METHOD': 'GET'})
|
||||
req.range = 'bytes=1-3'
|
||||
resp = self.object_controller.GET(req)
|
||||
resp = req.get_response(self.object_controller)
|
||||
self.assertEquals(resp.status_int, 206)
|
||||
self.assertEquals(resp.body, 'ERI')
|
||||
self.assertEquals(resp.headers['content-length'], '3')
|
||||
|
||||
req = Request.blank('/sda1/p/a/c/o')
|
||||
req = Request.blank('/sda1/p/a/c/o', environ={'REQUEST_METHOD': 'GET'})
|
||||
req.range = 'bytes=1-'
|
||||
resp = self.object_controller.GET(req)
|
||||
resp = req.get_response(self.object_controller)
|
||||
self.assertEquals(resp.status_int, 206)
|
||||
self.assertEquals(resp.body, 'ERIFY')
|
||||
self.assertEquals(resp.headers['content-length'], '5')
|
||||
|
||||
req = Request.blank('/sda1/p/a/c/o')
|
||||
req = Request.blank('/sda1/p/a/c/o', environ={'REQUEST_METHOD': 'GET'})
|
||||
req.range = 'bytes=-2'
|
||||
resp = self.object_controller.GET(req)
|
||||
resp = req.get_response(self.object_controller)
|
||||
self.assertEquals(resp.status_int, 206)
|
||||
self.assertEquals(resp.body, 'FY')
|
||||
self.assertEquals(resp.headers['content-length'], '2')
|
||||
@ -703,8 +703,8 @@ class TestObjectController(unittest.TestCase):
|
||||
hash_path('a', 'c', 'o')),
|
||||
timestamp + '.data')
|
||||
os.unlink(objfile)
|
||||
req = Request.blank('/sda1/p/a/c/o')
|
||||
resp = self.object_controller.GET(req)
|
||||
req = Request.blank('/sda1/p/a/c/o', environ={'REQUEST_METHOD': 'GET'})
|
||||
resp = req.get_response(self.object_controller)
|
||||
self.assertEquals(resp.status_int, 404)
|
||||
|
||||
sleep(.00001)
|
||||
@ -715,7 +715,7 @@ class TestObjectController(unittest.TestCase):
|
||||
'Content-Type': 'application:octet-stream',
|
||||
'Content-Length': '6'})
|
||||
req.body = 'VERIFY'
|
||||
resp = self.object_controller.PUT(req)
|
||||
resp = req.get_response(self.object_controller)
|
||||
self.assertEquals(resp.status_int, 201)
|
||||
|
||||
sleep(.00001)
|
||||
@ -723,11 +723,11 @@ class TestObjectController(unittest.TestCase):
|
||||
req = Request.blank('/sda1/p/a/c/o',
|
||||
environ={'REQUEST_METHOD': 'DELETE'},
|
||||
headers={'X-Timestamp': timestamp})
|
||||
resp = self.object_controller.DELETE(req)
|
||||
resp = req.get_response(self.object_controller)
|
||||
self.assertEquals(resp.status_int, 204)
|
||||
|
||||
req = Request.blank('/sda1/p/a/c/o')
|
||||
resp = self.object_controller.GET(req)
|
||||
req = Request.blank('/sda1/p/a/c/o', environ={'REQUEST_METHOD': 'GET'})
|
||||
resp = req.get_response(self.object_controller)
|
||||
self.assertEquals(resp.status_int, 404)
|
||||
|
||||
def test_GET_if_match(self):
|
||||
|
Loading…
Reference in New Issue
Block a user