add name_check to /info

Also removed a bunch of unnecessary unquotes. Just use path_info
instead (it's already unquoted).

Partial-Bug: #1670915

Change-Id: If1af43485b4708cab6c4b5d7f6f0a334d8752518
This commit is contained in:
John Dickinson 2017-03-07 15:06:13 -08:00 committed by Alistair Coles
parent 8b2f01a619
commit cd39778824
3 changed files with 40 additions and 7 deletions

View File

@ -165,6 +165,11 @@ is a normal object and not a copy of the manifest. Instead it is a
concatenation of all the segment objects. This means that you concatenation of all the segment objects. This means that you
cannot copy objects larger than 5 GB. cannot copy objects larger than 5 GB.
Note that the provider may have limited the characters which are allowed
in an object name. Any name limits are exposed under the ``name_check`` key
in the ``/info`` discoverability response. Regardless of ``name_check``
limitations, names must be URL quoted UTF-8.
To create custom metadata, use the To create custom metadata, use the
``X-Object-Meta-name`` header, where ``name`` is the name of the metadata ``X-Object-Meta-name`` header, where ``name`` is the name of the metadata
item. item.

View File

@ -40,10 +40,8 @@ The filter returns HTTPBadRequest if path is invalid.
@author: eamonn-otoole @author: eamonn-otoole
''' '''
from six.moves.urllib.parse import unquote
import re import re
from swift.common.utils import get_logger from swift.common.utils import get_logger, register_swift_info
from swift.common.swob import Request, HTTPBadRequest from swift.common.swob import Request, HTTPBadRequest
@ -69,6 +67,15 @@ class NameCheckMiddleware(object):
self.forbidden_regexp_compiled = None self.forbidden_regexp_compiled = None
self.logger = get_logger(self.conf, log_route='name_check') self.logger = get_logger(self.conf, log_route='name_check')
self.register_info()
def register_info(self):
register_swift_info('name_check',
forbidden_chars=self.forbidden_chars,
maximum_length=self.maximum_length,
forbidden_regexp=self.forbidden_regexp
)
def check_character(self, req): def check_character(self, req):
''' '''
Checks req.path for any forbidden characters Checks req.path for any forbidden characters
@ -79,7 +86,7 @@ class NameCheckMiddleware(object):
self.logger.debug("name_check: self.forbidden_chars %s" % self.logger.debug("name_check: self.forbidden_chars %s" %
self.forbidden_chars) self.forbidden_chars)
return any((c in unquote(req.path)) for c in self.forbidden_chars) return any((c in req.path_info) for c in self.forbidden_chars)
def check_length(self, req): def check_length(self, req):
''' '''
@ -87,7 +94,7 @@ class NameCheckMiddleware(object):
Returns True if the length exceeds the maximum Returns True if the length exceeds the maximum
Returns False if the length is <= the maximum Returns False if the length is <= the maximum
''' '''
length = len(unquote(req.path)) length = len(req.path_info)
return length > self.maximum_length return length > self.maximum_length
def check_regexp(self, req): def check_regexp(self, req):
@ -103,8 +110,7 @@ class NameCheckMiddleware(object):
self.logger.debug("name_check: self.forbidden_regexp %s" % self.logger.debug("name_check: self.forbidden_regexp %s" %
self.forbidden_regexp) self.forbidden_regexp)
unquoted_path = unquote(req.path) match = self.forbidden_regexp_compiled.search(req.path_info)
match = self.forbidden_regexp_compiled.search(unquoted_path)
return (match is not None) return (match is not None)
def __call__(self, env, start_response): def __call__(self, env, start_response):

View File

@ -21,10 +21,12 @@ Created on February 29, 2012
@author: eamonn-otoole @author: eamonn-otoole
''' '''
import numbers
import unittest import unittest
from swift.common.swob import Request, Response from swift.common.swob import Request, Response
from swift.common.middleware import name_check from swift.common.middleware import name_check
from swift.common import utils
MAX_LENGTH = 255 MAX_LENGTH = 255
FORBIDDEN_CHARS = '\'\"<>`' FORBIDDEN_CHARS = '\'\"<>`'
@ -116,5 +118,25 @@ class TestNameCheckMiddleware(unittest.TestCase):
self.assertEqual(resp.body, 'OK') self.assertEqual(resp.body, 'OK')
class TestSwiftInfo(unittest.TestCase):
def setUp(self):
utils._swift_info = {}
utils._swift_admin_info = {}
def test_registered_defaults(self):
name_check.filter_factory({})(FakeApp())
swift_info = utils.get_swift_info()
self.assertTrue('name_check' in swift_info)
self.assertTrue(isinstance(
swift_info['name_check'].get('maximum_length'),
numbers.Integral))
self.assertTrue(isinstance(
swift_info['name_check'].get('forbidden_chars'),
str))
self.assertTrue(isinstance(
swift_info['name_check'].get('forbidden_regexp'),
str))
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()