Move HeaderKeyDict to avoid an inline import

There was a function in swift.common.utils that was importing
swob.HeaderKeyDict at call time. It couldn't import it at compilation
time since utils can't import from swob or else it blows up with a
circular import error.

This commit just moves HeaderKeyDict into swift.common.header_key_dict
so that we can remove the inline import.

Change-Id: I656fde8cc2e125327c26c589cf1045cb81ffc7e5
This commit is contained in:
Samuel Merritt 2016-03-02 10:28:51 +00:00
parent 6cfb8557a8
commit 9430f4c9f5
30 changed files with 246 additions and 194 deletions

View File

@ -33,7 +33,7 @@ from swift.common.exceptions import ClientException
from swift.common.utils import Timestamp, FileLikeIter from swift.common.utils import Timestamp, FileLikeIter
from swift.common.http import HTTP_NO_CONTENT, HTTP_INSUFFICIENT_STORAGE, \ from swift.common.http import HTTP_NO_CONTENT, HTTP_INSUFFICIENT_STORAGE, \
is_success, is_server_error is_success, is_server_error
from swift.common.swob import HeaderKeyDict from swift.common.header_key_dict import HeaderKeyDict
from swift.common.utils import quote from swift.common.utils import quote

View File

@ -0,0 +1,63 @@
# Copyright (c) 2010-2012 OpenStack Foundation
#
# 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.
import six
class HeaderKeyDict(dict):
"""
A dict that title-cases all keys on the way in, so as to be
case-insensitive.
"""
def __init__(self, base_headers=None, **kwargs):
if base_headers:
self.update(base_headers)
self.update(kwargs)
def update(self, other):
if hasattr(other, 'keys'):
for key in other.keys():
self[key.title()] = other[key]
else:
for key, value in other:
self[key.title()] = value
def __getitem__(self, key):
return dict.get(self, key.title())
def __setitem__(self, key, value):
if value is None:
self.pop(key.title(), None)
elif isinstance(value, six.text_type):
return dict.__setitem__(self, key.title(), value.encode('utf-8'))
else:
return dict.__setitem__(self, key.title(), str(value))
def __contains__(self, key):
return dict.__contains__(self, key.title())
def __delitem__(self, key):
return dict.__delitem__(self, key.title())
def get(self, key, default=None):
return dict.get(self, key.title(), default)
def setdefault(self, key, value=None):
if key not in self:
self[key] = value
return self[key]
def pop(self, key, default=None):
return dict.pop(self, key.title(), default)

View File

@ -169,8 +169,9 @@ from six.moves.urllib.parse import parse_qs
from six.moves.urllib.parse import urlencode from six.moves.urllib.parse import urlencode
from swift.proxy.controllers.base import get_account_info, get_container_info from swift.proxy.controllers.base import get_account_info, get_container_info
from swift.common.swob import HeaderKeyDict, header_to_environ_key, \ from swift.common.header_key_dict import HeaderKeyDict
HTTPUnauthorized, HTTPBadRequest from swift.common.swob import header_to_environ_key, HTTPUnauthorized, \
HTTPBadRequest
from swift.common.utils import split_path, get_valid_utf8_str, \ from swift.common.utils import split_path, get_valid_utf8_str, \
register_swift_info, get_hmac, streq_const_time, quote register_swift_info, get_hmac, streq_const_time, quote

View File

@ -50,6 +50,7 @@ from six import BytesIO
from six import StringIO from six import StringIO
from six.moves import urllib from six.moves import urllib
from swift.common.header_key_dict import HeaderKeyDict
from swift.common.utils import reiterate, split_path, Timestamp, pairs, \ from swift.common.utils import reiterate, split_path, Timestamp, pairs, \
close_if_possible close_if_possible
from swift.common.exceptions import InvalidTimestamp from swift.common.exceptions import InvalidTimestamp
@ -271,53 +272,6 @@ class HeaderEnvironProxy(MutableMapping):
return keys return keys
class HeaderKeyDict(dict):
"""
A dict that title-cases all keys on the way in, so as to be
case-insensitive.
"""
def __init__(self, base_headers=None, **kwargs):
if base_headers:
self.update(base_headers)
self.update(kwargs)
def update(self, other):
if hasattr(other, 'keys'):
for key in other.keys():
self[key.title()] = other[key]
else:
for key, value in other:
self[key.title()] = value
def __getitem__(self, key):
return dict.get(self, key.title())
def __setitem__(self, key, value):
if value is None:
self.pop(key.title(), None)
elif isinstance(value, six.text_type):
return dict.__setitem__(self, key.title(), value.encode('utf-8'))
else:
return dict.__setitem__(self, key.title(), str(value))
def __contains__(self, key):
return dict.__contains__(self, key.title())
def __delitem__(self, key):
return dict.__delitem__(self, key.title())
def get(self, key, default=None):
return dict.get(self, key.title(), default)
def setdefault(self, key, value=None):
if key not in self:
self[key] = value
return self[key]
def pop(self, key, default=None):
return dict.pop(self, key.title(), default)
def _resp_status_property(): def _resp_status_property():
""" """
Set and retrieve the value of Response.status Set and retrieve the value of Response.status

View File

@ -68,6 +68,7 @@ from swift import gettext_ as _
import swift.common.exceptions import swift.common.exceptions
from swift.common.http import is_success, is_redirection, HTTP_NOT_FOUND, \ from swift.common.http import is_success, is_redirection, HTTP_NOT_FOUND, \
HTTP_PRECONDITION_FAILED, HTTP_REQUESTED_RANGE_NOT_SATISFIABLE HTTP_PRECONDITION_FAILED, HTTP_REQUESTED_RANGE_NOT_SATISFIABLE
from swift.common.header_key_dict import HeaderKeyDict
if six.PY3: if six.PY3:
stdlib_queue = eventlet.patcher.original('queue') stdlib_queue = eventlet.patcher.original('queue')
@ -3648,7 +3649,6 @@ def parse_mime_headers(doc_file):
:param doc_file: binary file-like object containing a MIME document :param doc_file: binary file-like object containing a MIME document
:returns: a swift.common.swob.HeaderKeyDict containing the headers :returns: a swift.common.swob.HeaderKeyDict containing the headers
""" """
from swift.common.swob import HeaderKeyDict # avoid circular import
headers = [] headers = []
while True: while True:
line = doc_file.readline() line = doc_file.readline()

View File

@ -41,10 +41,11 @@ from swift.common.exceptions import ConnectionTimeout
from swift.common.http import HTTP_NOT_FOUND, is_success from swift.common.http import HTTP_NOT_FOUND, is_success
from swift.common.storage_policy import POLICIES from swift.common.storage_policy import POLICIES
from swift.common.base_storage_server import BaseStorageServer from swift.common.base_storage_server import BaseStorageServer
from swift.common.header_key_dict import HeaderKeyDict
from swift.common.swob import HTTPAccepted, HTTPBadRequest, HTTPConflict, \ from swift.common.swob import HTTPAccepted, HTTPBadRequest, HTTPConflict, \
HTTPCreated, HTTPInternalServerError, HTTPNoContent, HTTPNotFound, \ HTTPCreated, HTTPInternalServerError, HTTPNoContent, HTTPNotFound, \
HTTPPreconditionFailed, HTTPMethodNotAllowed, Request, Response, \ HTTPPreconditionFailed, HTTPMethodNotAllowed, Request, Response, \
HTTPInsufficientStorage, HTTPException, HeaderKeyDict HTTPInsufficientStorage, HTTPException
def gen_resp_headers(info, is_deleted=False): def gen_resp_headers(info, is_deleted=False):

View File

@ -32,7 +32,7 @@ from swift.common.utils import (
whataremyips, unlink_older_than, compute_eta, get_logger, whataremyips, unlink_older_than, compute_eta, get_logger,
dump_recon_cache, mkdirs, config_true_value, list_from_csv, get_hub, dump_recon_cache, mkdirs, config_true_value, list_from_csv, get_hub,
tpool_reraise, GreenAsyncPile, Timestamp, remove_file) tpool_reraise, GreenAsyncPile, Timestamp, remove_file)
from swift.common.swob import HeaderKeyDict from swift.common.header_key_dict import HeaderKeyDict
from swift.common.bufferedhttp import http_connect from swift.common.bufferedhttp import http_connect
from swift.common.daemon import Daemon from swift.common.daemon import Daemon
from swift.common.ring.utils import is_local_device from swift.common.ring.utils import is_local_device

View File

@ -44,14 +44,15 @@ from swift.common.exceptions import ConnectionTimeout, DiskFileQuarantined, \
from swift.obj import ssync_receiver from swift.obj import ssync_receiver
from swift.common.http import is_success from swift.common.http import is_success
from swift.common.base_storage_server import BaseStorageServer from swift.common.base_storage_server import BaseStorageServer
from swift.common.header_key_dict import HeaderKeyDict
from swift.common.request_helpers import get_name_and_placement, \ from swift.common.request_helpers import get_name_and_placement, \
is_user_meta, is_sys_or_user_meta is_user_meta, is_sys_or_user_meta
from swift.common.swob import HTTPAccepted, HTTPBadRequest, HTTPCreated, \ from swift.common.swob import HTTPAccepted, HTTPBadRequest, HTTPCreated, \
HTTPInternalServerError, HTTPNoContent, HTTPNotFound, \ HTTPInternalServerError, HTTPNoContent, HTTPNotFound, \
HTTPPreconditionFailed, HTTPRequestTimeout, HTTPUnprocessableEntity, \ HTTPPreconditionFailed, HTTPRequestTimeout, HTTPUnprocessableEntity, \
HTTPClientDisconnect, HTTPMethodNotAllowed, Request, Response, \ HTTPClientDisconnect, HTTPMethodNotAllowed, Request, Response, \
HTTPInsufficientStorage, HTTPForbidden, HTTPException, HeaderKeyDict, \ HTTPInsufficientStorage, HTTPForbidden, HTTPException, HTTPConflict, \
HTTPConflict, HTTPServerError HTTPServerError
from swift.obj.diskfile import DATAFILE_SYSTEM_META, DiskFileRouter from swift.obj.diskfile import DATAFILE_SYSTEM_META, DiskFileRouter

View File

@ -47,11 +47,12 @@ from swift.common.utils import Timestamp, config_true_value, \
from swift.common.bufferedhttp import http_connect from swift.common.bufferedhttp import http_connect
from swift.common.exceptions import ChunkReadTimeout, ChunkWriteTimeout, \ from swift.common.exceptions import ChunkReadTimeout, ChunkWriteTimeout, \
ConnectionTimeout, RangeAlreadyComplete ConnectionTimeout, RangeAlreadyComplete
from swift.common.header_key_dict import HeaderKeyDict
from swift.common.http import is_informational, is_success, is_redirection, \ from swift.common.http import is_informational, is_success, is_redirection, \
is_server_error, HTTP_OK, HTTP_PARTIAL_CONTENT, HTTP_MULTIPLE_CHOICES, \ is_server_error, HTTP_OK, HTTP_PARTIAL_CONTENT, HTTP_MULTIPLE_CHOICES, \
HTTP_BAD_REQUEST, HTTP_NOT_FOUND, HTTP_SERVICE_UNAVAILABLE, \ HTTP_BAD_REQUEST, HTTP_NOT_FOUND, HTTP_SERVICE_UNAVAILABLE, \
HTTP_INSUFFICIENT_STORAGE, HTTP_UNAUTHORIZED, HTTP_CONTINUE HTTP_INSUFFICIENT_STORAGE, HTTP_UNAUTHORIZED, HTTP_CONTINUE
from swift.common.swob import Request, Response, HeaderKeyDict, Range, \ from swift.common.swob import Request, Response, Range, \
HTTPException, HTTPRequestedRangeNotSatisfiable, HTTPServiceUnavailable, \ HTTPException, HTTPRequestedRangeNotSatisfiable, HTTPServiceUnavailable, \
status_map status_map
from swift.common.request_helpers import strip_sys_meta_prefix, \ from swift.common.request_helpers import strip_sys_meta_prefix, \

View File

@ -57,6 +57,7 @@ from swift.common.exceptions import ChunkReadTimeout, \
ChunkWriteTimeout, ConnectionTimeout, ResponseTimeout, \ ChunkWriteTimeout, ConnectionTimeout, ResponseTimeout, \
InsufficientStorage, FooterNotSupported, MultiphasePUTNotSupported, \ InsufficientStorage, FooterNotSupported, MultiphasePUTNotSupported, \
PutterConnectError, ChunkReadError PutterConnectError, ChunkReadError
from swift.common.header_key_dict import HeaderKeyDict
from swift.common.http import ( from swift.common.http import (
is_informational, is_success, is_client_error, is_server_error, is_informational, is_success, is_client_error, is_server_error,
HTTP_CONTINUE, HTTP_CREATED, HTTP_MULTIPLE_CHOICES, HTTP_CONTINUE, HTTP_CREATED, HTTP_MULTIPLE_CHOICES,
@ -69,7 +70,7 @@ from swift.proxy.controllers.base import Controller, delay_denial, \
cors_validation, ResumingGetter cors_validation, ResumingGetter
from swift.common.swob import HTTPAccepted, HTTPBadRequest, HTTPNotFound, \ from swift.common.swob import HTTPAccepted, HTTPBadRequest, HTTPNotFound, \
HTTPPreconditionFailed, HTTPRequestEntityTooLarge, HTTPRequestTimeout, \ HTTPPreconditionFailed, HTTPRequestEntityTooLarge, HTTPRequestTimeout, \
HTTPServerError, HTTPServiceUnavailable, Request, HeaderKeyDict, \ HTTPServerError, HTTPServiceUnavailable, Request, \
HTTPClientDisconnect, HTTPUnprocessableEntity, Response, HTTPException, \ HTTPClientDisconnect, HTTPUnprocessableEntity, Response, HTTPException, \
HTTPRequestedRangeNotSatisfiable, Range, HTTPInternalServerError HTTPRequestedRangeNotSatisfiable, Range, HTTPInternalServerError
from swift.common.request_helpers import is_sys_or_user_meta, is_sys_meta, \ from swift.common.request_helpers import is_sys_or_user_meta, is_sys_meta, \

View File

@ -34,7 +34,8 @@ from tempfile import mkdtemp
from shutil import rmtree from shutil import rmtree
from swift.common.utils import Timestamp, NOTICE from swift.common.utils import Timestamp, NOTICE
from test import get_config from test import get_config
from swift.common import swob, utils from swift.common import utils
from swift.common.header_key_dict import HeaderKeyDict
from swift.common.ring import Ring, RingData from swift.common.ring import Ring, RingData
from hashlib import md5 from hashlib import md5
import logging.handlers import logging.handlers
@ -901,7 +902,7 @@ def fake_http_connect(*code_iter, **kwargs):
else: else:
etag = '"68b329da9893e34099c7d8ad5cb9c940"' etag = '"68b329da9893e34099c7d8ad5cb9c940"'
headers = swob.HeaderKeyDict({ headers = HeaderKeyDict({
'content-length': len(self.body), 'content-length': len(self.body),
'content-type': 'x-application/test', 'content-type': 'x-application/test',
'x-timestamp': self.timestamp, 'x-timestamp': self.timestamp,
@ -960,7 +961,7 @@ def fake_http_connect(*code_iter, **kwargs):
eventlet.sleep(value) eventlet.sleep(value)
def getheader(self, name, default=None): def getheader(self, name, default=None):
return swob.HeaderKeyDict(self.getheaders()).get(name, default) return HeaderKeyDict(self.getheaders()).get(name, default)
def close(self): def close(self):
pass pass

View File

@ -20,7 +20,7 @@ import mock
from swift.account import utils, backend from swift.account import utils, backend
from swift.common.storage_policy import POLICIES from swift.common.storage_policy import POLICIES
from swift.common.utils import Timestamp from swift.common.utils import Timestamp
from swift.common.swob import HeaderKeyDict from swift.common.header_key_dict import HeaderKeyDict
from test.unit import patch_policies from test.unit import patch_policies

View File

@ -19,6 +19,7 @@ from collections import defaultdict
from copy import deepcopy from copy import deepcopy
from hashlib import md5 from hashlib import md5
from swift.common import swob from swift.common import swob
from swift.common.header_key_dict import HeaderKeyDict
from swift.common.utils import split_path from swift.common.utils import split_path
from test.unit import FakeLogger, FakeRing from test.unit import FakeLogger, FakeRing
@ -85,18 +86,18 @@ class FakeSwift(object):
try: try:
resp_class, raw_headers, body = self._find_response(method, path) resp_class, raw_headers, body = self._find_response(method, path)
headers = swob.HeaderKeyDict(raw_headers) headers = HeaderKeyDict(raw_headers)
except KeyError: except KeyError:
if (env.get('QUERY_STRING') if (env.get('QUERY_STRING')
and (method, env['PATH_INFO']) in self._responses): and (method, env['PATH_INFO']) in self._responses):
resp_class, raw_headers, body = self._find_response( resp_class, raw_headers, body = self._find_response(
method, env['PATH_INFO']) method, env['PATH_INFO'])
headers = swob.HeaderKeyDict(raw_headers) headers = HeaderKeyDict(raw_headers)
elif method == 'HEAD' and ('GET', path) in self._responses: elif method == 'HEAD' and ('GET', path) in self._responses:
resp_class, raw_headers, body = self._find_response( resp_class, raw_headers, body = self._find_response(
'GET', path) 'GET', path)
body = None body = None
headers = swob.HeaderKeyDict(raw_headers) headers = HeaderKeyDict(raw_headers)
elif method == 'GET' and obj and path in self.uploaded: elif method == 'GET' and obj and path in self.uploaded:
resp_class = swob.HTTPOk resp_class = swob.HTTPOk
headers, body = self.uploaded[path] headers, body = self.uploaded[path]

View File

@ -29,9 +29,10 @@ from eventlet import sleep
from mock import patch, call from mock import patch, call
from test.unit.common.middleware.helpers import FakeSwift from test.unit.common.middleware.helpers import FakeSwift
from swift.common import utils, constraints from swift.common import utils, constraints
from swift.common.header_key_dict import HeaderKeyDict
from swift.common.middleware import bulk from swift.common.middleware import bulk
from swift.common.swob import Request, Response, HTTPException, \ from swift.common.swob import Request, Response, HTTPException, \
HTTPNoContent, HTTPCreated, HeaderKeyDict HTTPNoContent, HTTPCreated
from swift.common.http import HTTP_NOT_FOUND, HTTP_UNAUTHORIZED from swift.common.http import HTTP_NOT_FOUND, HTTP_UNAUTHORIZED

View File

@ -24,6 +24,7 @@ import time
import unittest import unittest
from swift.common import exceptions, swob from swift.common import exceptions, swob
from swift.common.header_key_dict import HeaderKeyDict
from swift.common.middleware import dlo from swift.common.middleware import dlo
from swift.common.utils import closing_if_possible from swift.common.utils import closing_if_possible
from test.unit.common.middleware.helpers import FakeSwift from test.unit.common.middleware.helpers import FakeSwift
@ -248,7 +249,7 @@ class TestDloHeadManifest(DloTestCase):
req = swob.Request.blank('/v1/AUTH_test/mancon/manifest', req = swob.Request.blank('/v1/AUTH_test/mancon/manifest',
environ={'REQUEST_METHOD': 'HEAD'}) environ={'REQUEST_METHOD': 'HEAD'})
status, headers, body = self.call_dlo(req) status, headers, body = self.call_dlo(req)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(headers["Etag"], expected_etag) self.assertEqual(headers["Etag"], expected_etag)
self.assertEqual(headers["Content-Length"], "25") self.assertEqual(headers["Content-Length"], "25")
@ -257,7 +258,7 @@ class TestDloHeadManifest(DloTestCase):
environ={'REQUEST_METHOD': 'HEAD'}) environ={'REQUEST_METHOD': 'HEAD'})
with mock.patch(LIMIT, 3): with mock.patch(LIMIT, 3):
status, headers, body = self.call_dlo(req) status, headers, body = self.call_dlo(req)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
# etag is manifest's etag # etag is manifest's etag
self.assertEqual(headers["Etag"], "etag-manyseg") self.assertEqual(headers["Etag"], "etag-manyseg")
@ -267,7 +268,7 @@ class TestDloHeadManifest(DloTestCase):
req = swob.Request.blank('/v1/AUTH_test/mancon/manifest-no-segments', req = swob.Request.blank('/v1/AUTH_test/mancon/manifest-no-segments',
environ={'REQUEST_METHOD': 'HEAD'}) environ={'REQUEST_METHOD': 'HEAD'})
status, headers, body = self.call_dlo(req) status, headers, body = self.call_dlo(req)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(headers["Etag"], '"%s"' % md5hex("")) self.assertEqual(headers["Etag"], '"%s"' % md5hex(""))
self.assertEqual(headers["Content-Length"], "0") self.assertEqual(headers["Content-Length"], "0")
@ -291,7 +292,7 @@ class TestDloGetManifest(DloTestCase):
req = swob.Request.blank('/v1/AUTH_test/mancon/manifest', req = swob.Request.blank('/v1/AUTH_test/mancon/manifest',
environ={'REQUEST_METHOD': 'GET'}) environ={'REQUEST_METHOD': 'GET'})
status, headers, body = self.call_dlo(req) status, headers, body = self.call_dlo(req)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(headers["Etag"], expected_etag) self.assertEqual(headers["Etag"], expected_etag)
self.assertEqual(headers["Content-Length"], "25") self.assertEqual(headers["Content-Length"], "25")
self.assertEqual(body, 'aaaaabbbbbcccccdddddeeeee') self.assertEqual(body, 'aaaaabbbbbcccccdddddeeeee')
@ -336,7 +337,7 @@ class TestDloGetManifest(DloTestCase):
environ={'REQUEST_METHOD': 'GET', environ={'REQUEST_METHOD': 'GET',
'QUERY_STRING': 'multipart-manifest=get'}) 'QUERY_STRING': 'multipart-manifest=get'})
status, headers, body = self.call_dlo(req) status, headers, body = self.call_dlo(req)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(headers["Etag"], "manifest-etag") self.assertEqual(headers["Etag"], "manifest-etag")
self.assertEqual(body, "manifest-contents") self.assertEqual(body, "manifest-contents")
@ -354,7 +355,7 @@ class TestDloGetManifest(DloTestCase):
environ={'REQUEST_METHOD': 'GET'}, environ={'REQUEST_METHOD': 'GET'},
headers={'Range': 'bytes=8-17'}) headers={'Range': 'bytes=8-17'})
status, headers, body = self.call_dlo(req) status, headers, body = self.call_dlo(req)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(status, "206 Partial Content") self.assertEqual(status, "206 Partial Content")
self.assertEqual(headers["Content-Length"], "10") self.assertEqual(headers["Content-Length"], "10")
self.assertEqual(body, "bbcccccddd") self.assertEqual(body, "bbcccccddd")
@ -368,7 +369,7 @@ class TestDloGetManifest(DloTestCase):
environ={'REQUEST_METHOD': 'GET'}, environ={'REQUEST_METHOD': 'GET'},
headers={'Range': 'bytes=10-19'}) headers={'Range': 'bytes=10-19'})
status, headers, body = self.call_dlo(req) status, headers, body = self.call_dlo(req)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(status, "206 Partial Content") self.assertEqual(status, "206 Partial Content")
self.assertEqual(headers["Content-Length"], "10") self.assertEqual(headers["Content-Length"], "10")
self.assertEqual(body, "cccccddddd") self.assertEqual(body, "cccccddddd")
@ -378,7 +379,7 @@ class TestDloGetManifest(DloTestCase):
environ={'REQUEST_METHOD': 'GET'}, environ={'REQUEST_METHOD': 'GET'},
headers={'Range': 'bytes=0-0'}) headers={'Range': 'bytes=0-0'})
status, headers, body = self.call_dlo(req) status, headers, body = self.call_dlo(req)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(status, "206 Partial Content") self.assertEqual(status, "206 Partial Content")
self.assertEqual(headers["Content-Length"], "1") self.assertEqual(headers["Content-Length"], "1")
self.assertEqual(body, "a") self.assertEqual(body, "a")
@ -388,7 +389,7 @@ class TestDloGetManifest(DloTestCase):
environ={'REQUEST_METHOD': 'GET'}, environ={'REQUEST_METHOD': 'GET'},
headers={'Range': 'bytes=24-24'}) headers={'Range': 'bytes=24-24'})
status, headers, body = self.call_dlo(req) status, headers, body = self.call_dlo(req)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(status, "206 Partial Content") self.assertEqual(status, "206 Partial Content")
self.assertEqual(headers["Content-Length"], "1") self.assertEqual(headers["Content-Length"], "1")
self.assertEqual(body, "e") self.assertEqual(body, "e")
@ -398,7 +399,7 @@ class TestDloGetManifest(DloTestCase):
environ={'REQUEST_METHOD': 'GET'}, environ={'REQUEST_METHOD': 'GET'},
headers={'Range': 'bytes=18-30'}) headers={'Range': 'bytes=18-30'})
status, headers, body = self.call_dlo(req) status, headers, body = self.call_dlo(req)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(status, "206 Partial Content") self.assertEqual(status, "206 Partial Content")
self.assertEqual(headers["Content-Length"], "7") self.assertEqual(headers["Content-Length"], "7")
self.assertEqual(headers["Content-Range"], "bytes 18-24/25") self.assertEqual(headers["Content-Range"], "bytes 18-24/25")
@ -417,7 +418,7 @@ class TestDloGetManifest(DloTestCase):
headers={'Range': 'bytes=3-12'}) headers={'Range': 'bytes=3-12'})
with mock.patch(LIMIT, 3): with mock.patch(LIMIT, 3):
status, headers, body = self.call_dlo(req) status, headers, body = self.call_dlo(req)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(status, "206 Partial Content") self.assertEqual(status, "206 Partial Content")
self.assertEqual(headers["Content-Length"], "10") self.assertEqual(headers["Content-Length"], "10")
# The /15 here indicates that this is a 15-byte object. DLO can't tell # The /15 here indicates that this is a 15-byte object. DLO can't tell
@ -448,7 +449,7 @@ class TestDloGetManifest(DloTestCase):
headers={'Range': 'bytes=10-22'}) headers={'Range': 'bytes=10-22'})
with mock.patch(LIMIT, 3): with mock.patch(LIMIT, 3):
status, headers, body = self.call_dlo(req) status, headers, body = self.call_dlo(req)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(status, "200 OK") self.assertEqual(status, "200 OK")
# this requires multiple pages of container listing, so we can't send # this requires multiple pages of container listing, so we can't send
# a Content-Length header # a Content-Length header
@ -460,7 +461,7 @@ class TestDloGetManifest(DloTestCase):
environ={'REQUEST_METHOD': 'GET'}, environ={'REQUEST_METHOD': 'GET'},
headers={'Range': 'bytes=-40'}) headers={'Range': 'bytes=-40'})
status, headers, body = self.call_dlo(req) status, headers, body = self.call_dlo(req)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(status, "206 Partial Content") self.assertEqual(status, "206 Partial Content")
self.assertEqual(headers["Content-Length"], "25") self.assertEqual(headers["Content-Length"], "25")
self.assertEqual(body, "aaaaabbbbbcccccdddddeeeee") self.assertEqual(body, "aaaaabbbbbcccccdddddeeeee")
@ -471,7 +472,7 @@ class TestDloGetManifest(DloTestCase):
headers={'Range': 'bytes=-5'}) headers={'Range': 'bytes=-5'})
with mock.patch(LIMIT, 3): with mock.patch(LIMIT, 3):
status, headers, body = self.call_dlo(req) status, headers, body = self.call_dlo(req)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(status, "200 OK") self.assertEqual(status, "200 OK")
self.assertEqual(headers.get("Content-Length"), None) self.assertEqual(headers.get("Content-Length"), None)
self.assertEqual(headers.get("Content-Range"), None) self.assertEqual(headers.get("Content-Range"), None)
@ -485,7 +486,7 @@ class TestDloGetManifest(DloTestCase):
headers={'Range': 'bytes=5-9,15-19'}) headers={'Range': 'bytes=5-9,15-19'})
with mock.patch(LIMIT, 3): with mock.patch(LIMIT, 3):
status, headers, body = self.call_dlo(req) status, headers, body = self.call_dlo(req)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(status, "200 OK") self.assertEqual(status, "200 OK")
self.assertEqual(headers.get("Content-Length"), None) self.assertEqual(headers.get("Content-Length"), None)
self.assertEqual(headers.get("Content-Range"), None) self.assertEqual(headers.get("Content-Range"), None)
@ -500,7 +501,7 @@ class TestDloGetManifest(DloTestCase):
headers={'If-Match': manifest_etag}) headers={'If-Match': manifest_etag})
status, headers, body = self.call_dlo(req) status, headers, body = self.call_dlo(req)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(status, '200 OK') self.assertEqual(status, '200 OK')
self.assertEqual(headers['Content-Length'], '25') self.assertEqual(headers['Content-Length'], '25')
@ -512,7 +513,7 @@ class TestDloGetManifest(DloTestCase):
headers={'If-Match': 'not it'}) headers={'If-Match': 'not it'})
status, headers, body = self.call_dlo(req) status, headers, body = self.call_dlo(req)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(status, '412 Precondition Failed') self.assertEqual(status, '412 Precondition Failed')
self.assertEqual(headers['Content-Length'], '0') self.assertEqual(headers['Content-Length'], '0')
@ -527,7 +528,7 @@ class TestDloGetManifest(DloTestCase):
headers={'If-None-Match': manifest_etag}) headers={'If-None-Match': manifest_etag})
status, headers, body = self.call_dlo(req) status, headers, body = self.call_dlo(req)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(status, '304 Not Modified') self.assertEqual(status, '304 Not Modified')
self.assertEqual(headers['Content-Length'], '0') self.assertEqual(headers['Content-Length'], '0')
@ -539,7 +540,7 @@ class TestDloGetManifest(DloTestCase):
headers={'If-None-Match': 'not it'}) headers={'If-None-Match': 'not it'})
status, headers, body = self.call_dlo(req) status, headers, body = self.call_dlo(req)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(status, '200 OK') self.assertEqual(status, '200 OK')
self.assertEqual(headers['Content-Length'], '25') self.assertEqual(headers['Content-Length'], '25')
@ -582,7 +583,7 @@ class TestDloGetManifest(DloTestCase):
req = swob.Request.blank('/v1/AUTH_test/mancon/manifest', req = swob.Request.blank('/v1/AUTH_test/mancon/manifest',
environ={'REQUEST_METHOD': 'GET'}) environ={'REQUEST_METHOD': 'GET'})
status, headers, body, exc = self.call_dlo(req, expect_exception=True) status, headers, body, exc = self.call_dlo(req, expect_exception=True)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertTrue(isinstance(exc, exceptions.SegmentError)) self.assertTrue(isinstance(exc, exceptions.SegmentError))
self.assertEqual(status, "200 OK") self.assertEqual(status, "200 OK")
@ -628,7 +629,7 @@ class TestDloGetManifest(DloTestCase):
req = swob.Request.blank('/v1/AUTH_test/mancon/manifest', req = swob.Request.blank('/v1/AUTH_test/mancon/manifest',
environ={'REQUEST_METHOD': 'GET'}) environ={'REQUEST_METHOD': 'GET'})
status, headers, body, exc = self.call_dlo(req, expect_exception=True) status, headers, body, exc = self.call_dlo(req, expect_exception=True)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertTrue(isinstance(exc, exceptions.SegmentError)) self.assertTrue(isinstance(exc, exceptions.SegmentError))
self.assertEqual(status, "200 OK") self.assertEqual(status, "200 OK")
@ -653,7 +654,7 @@ class TestDloGetManifest(DloTestCase):
req = swob.Request.blank('/v1/AUTH_test/mani/festo', req = swob.Request.blank('/v1/AUTH_test/mani/festo',
environ={'REQUEST_METHOD': 'HEAD'}) environ={'REQUEST_METHOD': 'HEAD'})
status, headers, body = self.call_dlo(req) status, headers, body = self.call_dlo(req)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(headers["Etag"], self.assertEqual(headers["Etag"],
'"' + hashlib.md5("abcdef").hexdigest() + '"') '"' + hashlib.md5("abcdef").hexdigest() + '"')
@ -729,7 +730,7 @@ class TestDloGetManifest(DloTestCase):
'/v1/AUTH_test/mancon/manifest', '/v1/AUTH_test/mancon/manifest',
environ={'REQUEST_METHOD': 'GET'}) environ={'REQUEST_METHOD': 'GET'})
status, headers, body, exc = self.call_dlo(req, expect_exception=True) status, headers, body, exc = self.call_dlo(req, expect_exception=True)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(status, '200 OK') # sanity check self.assertEqual(status, '200 OK') # sanity check
self.assertEqual(headers.get('Content-Length'), '25') # sanity check self.assertEqual(headers.get('Content-Length'), '25') # sanity check
@ -762,7 +763,7 @@ class TestDloGetManifest(DloTestCase):
'/v1/AUTH_test/mancon/manifest', '/v1/AUTH_test/mancon/manifest',
environ={'REQUEST_METHOD': 'GET'}) environ={'REQUEST_METHOD': 'GET'})
status, headers, body, exc = self.call_dlo(req, expect_exception=True) status, headers, body, exc = self.call_dlo(req, expect_exception=True)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(status, '200 OK') # sanity check self.assertEqual(status, '200 OK') # sanity check
self.assertEqual(headers.get('Content-Length'), '25') # sanity check self.assertEqual(headers.get('Content-Length'), '25') # sanity check
@ -781,7 +782,7 @@ class TestDloGetManifest(DloTestCase):
environ={'REQUEST_METHOD': 'GET'}, environ={'REQUEST_METHOD': 'GET'},
headers={'Range': 'bytes=0-14'}) headers={'Range': 'bytes=0-14'})
status, headers, body, exc = self.call_dlo(req, expect_exception=True) status, headers, body, exc = self.call_dlo(req, expect_exception=True)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(status, '206 Partial Content') # sanity check self.assertEqual(status, '206 Partial Content') # sanity check
self.assertEqual(headers.get('Content-Length'), '15') # sanity check self.assertEqual(headers.get('Content-Length'), '15') # sanity check

View File

@ -24,6 +24,7 @@ from mock import patch
from hashlib import md5 from hashlib import md5
from swift.common import swob, utils from swift.common import swob, utils
from swift.common.exceptions import ListingIterError, SegmentError from swift.common.exceptions import ListingIterError, SegmentError
from swift.common.header_key_dict import HeaderKeyDict
from swift.common.middleware import slo from swift.common.middleware import slo
from swift.common.swob import Request, Response, HTTPException from swift.common.swob import Request, Response, HTTPException
from swift.common.utils import quote, closing_if_possible, close_if_possible from swift.common.utils import quote, closing_if_possible, close_if_possible
@ -1054,7 +1055,7 @@ class TestSloHeadManifest(SloTestCase):
'/v1/AUTH_test/headtest/man', '/v1/AUTH_test/headtest/man',
environ={'REQUEST_METHOD': 'HEAD'}) environ={'REQUEST_METHOD': 'HEAD'})
status, headers, body = self.call_slo(req) status, headers, body = self.call_slo(req)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(status, '200 OK') self.assertEqual(status, '200 OK')
self.assertEqual(headers.get('Etag', '').strip("'\""), self.assertEqual(headers.get('Etag', '').strip("'\""),
@ -1331,7 +1332,7 @@ class TestSloGetManifest(SloTestCase):
'/v1/AUTH_test/gettest/manifest-bc', '/v1/AUTH_test/gettest/manifest-bc',
environ={'REQUEST_METHOD': 'GET'}) environ={'REQUEST_METHOD': 'GET'})
status, headers, body = self.call_slo(req) status, headers, body = self.call_slo(req)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
manifest_etag = md5hex(md5hex("b" * 10) + md5hex("c" * 15)) manifest_etag = md5hex(md5hex("b" * 10) + md5hex("c" * 15))
self.assertEqual(status, '200 OK') self.assertEqual(status, '200 OK')
@ -1382,7 +1383,7 @@ class TestSloGetManifest(SloTestCase):
'/v1/AUTH_test/gettest/manifest-aabbccdd', '/v1/AUTH_test/gettest/manifest-aabbccdd',
environ={'REQUEST_METHOD': 'GET'}) environ={'REQUEST_METHOD': 'GET'})
status, headers, body = self.call_slo(req) status, headers, body = self.call_slo(req)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(status, '200 OK') self.assertEqual(status, '200 OK')
self.assertEqual(body, ( self.assertEqual(body, (
@ -1469,7 +1470,7 @@ class TestSloGetManifest(SloTestCase):
environ={'REQUEST_METHOD': 'GET'}, environ={'REQUEST_METHOD': 'GET'},
headers={'If-None-Match': self.manifest_abcd_etag}) headers={'If-None-Match': self.manifest_abcd_etag})
status, headers, body = self.call_slo(req) status, headers, body = self.call_slo(req)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(status, '304 Not Modified') self.assertEqual(status, '304 Not Modified')
self.assertEqual(headers['Content-Length'], '0') self.assertEqual(headers['Content-Length'], '0')
@ -1481,7 +1482,7 @@ class TestSloGetManifest(SloTestCase):
environ={'REQUEST_METHOD': 'GET'}, environ={'REQUEST_METHOD': 'GET'},
headers={'If-None-Match': "not-%s" % self.manifest_abcd_etag}) headers={'If-None-Match': "not-%s" % self.manifest_abcd_etag})
status, headers, body = self.call_slo(req) status, headers, body = self.call_slo(req)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(status, '200 OK') self.assertEqual(status, '200 OK')
self.assertEqual( self.assertEqual(
@ -1493,7 +1494,7 @@ class TestSloGetManifest(SloTestCase):
environ={'REQUEST_METHOD': 'GET'}, environ={'REQUEST_METHOD': 'GET'},
headers={'If-Match': self.manifest_abcd_etag}) headers={'If-Match': self.manifest_abcd_etag})
status, headers, body = self.call_slo(req) status, headers, body = self.call_slo(req)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(status, '200 OK') self.assertEqual(status, '200 OK')
self.assertEqual( self.assertEqual(
@ -1505,7 +1506,7 @@ class TestSloGetManifest(SloTestCase):
environ={'REQUEST_METHOD': 'GET'}, environ={'REQUEST_METHOD': 'GET'},
headers={'If-Match': "not-%s" % self.manifest_abcd_etag}) headers={'If-Match': "not-%s" % self.manifest_abcd_etag})
status, headers, body = self.call_slo(req) status, headers, body = self.call_slo(req)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(status, '412 Precondition Failed') self.assertEqual(status, '412 Precondition Failed')
self.assertEqual(headers['Content-Length'], '0') self.assertEqual(headers['Content-Length'], '0')
@ -1518,7 +1519,7 @@ class TestSloGetManifest(SloTestCase):
headers={'If-Match': self.manifest_abcd_etag, headers={'If-Match': self.manifest_abcd_etag,
'Range': 'bytes=3-6'}) 'Range': 'bytes=3-6'})
status, headers, body = self.call_slo(req) status, headers, body = self.call_slo(req)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(status, '206 Partial Content') self.assertEqual(status, '206 Partial Content')
self.assertEqual(headers['Content-Length'], '4') self.assertEqual(headers['Content-Length'], '4')
@ -1529,7 +1530,7 @@ class TestSloGetManifest(SloTestCase):
'/v1/AUTH_test/gettest/manifest-abcd', '/v1/AUTH_test/gettest/manifest-abcd',
environ={'REQUEST_METHOD': 'GET'}) environ={'REQUEST_METHOD': 'GET'})
status, headers, body = self.call_slo(req) status, headers, body = self.call_slo(req)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(status, '200 OK') self.assertEqual(status, '200 OK')
self.assertEqual(headers['Content-Length'], '50') self.assertEqual(headers['Content-Length'], '50')
@ -1543,7 +1544,7 @@ class TestSloGetManifest(SloTestCase):
environ={'REQUEST_METHOD': 'GET'}, environ={'REQUEST_METHOD': 'GET'},
headers={'Range': 'bytes=3-17'}) headers={'Range': 'bytes=3-17'})
status, headers, body = self.call_slo(req) status, headers, body = self.call_slo(req)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(status, '206 Partial Content') self.assertEqual(status, '206 Partial Content')
self.assertEqual(headers['Content-Length'], '15') self.assertEqual(headers['Content-Length'], '15')
@ -1582,7 +1583,7 @@ class TestSloGetManifest(SloTestCase):
environ={'REQUEST_METHOD': 'GET'}, environ={'REQUEST_METHOD': 'GET'},
headers={'Range': 'bytes=0-999999999'}) headers={'Range': 'bytes=0-999999999'})
status, headers, body = self.call_slo(req) status, headers, body = self.call_slo(req)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(status, '206 Partial Content') self.assertEqual(status, '206 Partial Content')
self.assertEqual( self.assertEqual(
@ -1619,7 +1620,7 @@ class TestSloGetManifest(SloTestCase):
environ={'REQUEST_METHOD': 'GET'}, environ={'REQUEST_METHOD': 'GET'},
headers={'Range': 'bytes=100000-199999'}) headers={'Range': 'bytes=100000-199999'})
status, headers, body = self.call_slo(req) status, headers, body = self.call_slo(req)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(status, '206 Partial Content') self.assertEqual(status, '206 Partial Content')
count_e = sum(1 if x == 'e' else 0 for x in body) count_e = sum(1 if x == 'e' else 0 for x in body)
@ -1656,7 +1657,7 @@ class TestSloGetManifest(SloTestCase):
environ={'REQUEST_METHOD': 'GET'}, environ={'REQUEST_METHOD': 'GET'},
headers={'Range': 'bytes=0-999999999'}) headers={'Range': 'bytes=0-999999999'})
status, headers, body = self.call_slo(req) status, headers, body = self.call_slo(req)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(status, '206 Partial Content') self.assertEqual(status, '206 Partial Content')
self.assertEqual( self.assertEqual(
@ -1678,7 +1679,7 @@ class TestSloGetManifest(SloTestCase):
environ={'REQUEST_METHOD': 'GET'}, environ={'REQUEST_METHOD': 'GET'},
headers={'Range': 'bytes=5-29'}) headers={'Range': 'bytes=5-29'})
status, headers, body = self.call_slo(req) status, headers, body = self.call_slo(req)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(status, '206 Partial Content') self.assertEqual(status, '206 Partial Content')
self.assertEqual(headers['Content-Length'], '25') self.assertEqual(headers['Content-Length'], '25')
@ -1706,7 +1707,7 @@ class TestSloGetManifest(SloTestCase):
environ={'REQUEST_METHOD': 'GET'}, environ={'REQUEST_METHOD': 'GET'},
headers={'Range': 'bytes=0-0'}) headers={'Range': 'bytes=0-0'})
status, headers, body = self.call_slo(req) status, headers, body = self.call_slo(req)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(status, '206 Partial Content') self.assertEqual(status, '206 Partial Content')
self.assertEqual(headers['Content-Length'], '1') self.assertEqual(headers['Content-Length'], '1')
@ -1726,7 +1727,7 @@ class TestSloGetManifest(SloTestCase):
environ={'REQUEST_METHOD': 'GET'}, environ={'REQUEST_METHOD': 'GET'},
headers={'Range': 'bytes=25-30'}) headers={'Range': 'bytes=25-30'})
status, headers, body = self.call_slo(req) status, headers, body = self.call_slo(req)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(status, '206 Partial Content') self.assertEqual(status, '206 Partial Content')
self.assertEqual(headers['Content-Length'], '6') self.assertEqual(headers['Content-Length'], '6')
self.assertEqual(body, 'cccccd') self.assertEqual(body, 'cccccd')
@ -1747,7 +1748,7 @@ class TestSloGetManifest(SloTestCase):
environ={'REQUEST_METHOD': 'GET'}, environ={'REQUEST_METHOD': 'GET'},
headers={'Range': 'bytes=45-55'}) headers={'Range': 'bytes=45-55'})
status, headers, body = self.call_slo(req) status, headers, body = self.call_slo(req)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(status, '206 Partial Content') self.assertEqual(status, '206 Partial Content')
self.assertEqual(headers['Content-Length'], '5') self.assertEqual(headers['Content-Length'], '5')
@ -1769,7 +1770,7 @@ class TestSloGetManifest(SloTestCase):
environ={'REQUEST_METHOD': 'GET'}, environ={'REQUEST_METHOD': 'GET'},
headers={'Range': 'bytes=0-0,2-2'}) headers={'Range': 'bytes=0-0,2-2'})
status, headers, body = self.call_slo(req) status, headers, body = self.call_slo(req)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(status, '200 OK') self.assertEqual(status, '200 OK')
self.assertEqual(headers['Content-Length'], '50') self.assertEqual(headers['Content-Length'], '50')
@ -1799,7 +1800,7 @@ class TestSloGetManifest(SloTestCase):
'/v1/AUTH_test/ünicode/manifest', '/v1/AUTH_test/ünicode/manifest',
environ={'REQUEST_METHOD': 'GET'}) environ={'REQUEST_METHOD': 'GET'})
status, headers, body = self.call_slo(req) status, headers, body = self.call_slo(req)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(status, '200 OK') self.assertEqual(status, '200 OK')
self.assertEqual(body, segment_body) self.assertEqual(body, segment_body)
@ -1808,7 +1809,7 @@ class TestSloGetManifest(SloTestCase):
'/v1/AUTH_test/gettest/manifest-abcd-ranges', '/v1/AUTH_test/gettest/manifest-abcd-ranges',
environ={'REQUEST_METHOD': 'GET'}) environ={'REQUEST_METHOD': 'GET'})
status, headers, body = self.call_slo(req) status, headers, body = self.call_slo(req)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(status, '200 OK') self.assertEqual(status, '200 OK')
self.assertEqual(headers['Content-Length'], '32') self.assertEqual(headers['Content-Length'], '32')
@ -1850,7 +1851,7 @@ class TestSloGetManifest(SloTestCase):
'/v1/AUTH_test/gettest/manifest-abcd-subranges', '/v1/AUTH_test/gettest/manifest-abcd-subranges',
environ={'REQUEST_METHOD': 'GET'}) environ={'REQUEST_METHOD': 'GET'})
status, headers, body = self.call_slo(req) status, headers, body = self.call_slo(req)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(status, '200 OK') self.assertEqual(status, '200 OK')
self.assertEqual(headers['Content-Length'], '17') self.assertEqual(headers['Content-Length'], '17')
@ -1899,7 +1900,7 @@ class TestSloGetManifest(SloTestCase):
environ={'REQUEST_METHOD': 'GET'}, environ={'REQUEST_METHOD': 'GET'},
headers={'Range': 'bytes=7-26'}) headers={'Range': 'bytes=7-26'})
status, headers, body = self.call_slo(req) status, headers, body = self.call_slo(req)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(status, '206 Partial Content') self.assertEqual(status, '206 Partial Content')
self.assertEqual(headers['Content-Length'], '20') self.assertEqual(headers['Content-Length'], '20')
@ -1937,7 +1938,7 @@ class TestSloGetManifest(SloTestCase):
environ={'REQUEST_METHOD': 'GET'}, environ={'REQUEST_METHOD': 'GET'},
headers={'Range': 'bytes=4-12'}) headers={'Range': 'bytes=4-12'})
status, headers, body = self.call_slo(req) status, headers, body = self.call_slo(req)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(status, '206 Partial Content') self.assertEqual(status, '206 Partial Content')
self.assertEqual(headers['Content-Length'], '9') self.assertEqual(headers['Content-Length'], '9')
@ -1988,7 +1989,7 @@ class TestSloGetManifest(SloTestCase):
environ={'REQUEST_METHOD': 'GET'}, environ={'REQUEST_METHOD': 'GET'},
headers={'Range': 'bytes=0-999999999'}) headers={'Range': 'bytes=0-999999999'})
status, headers, body = self.call_slo(req) status, headers, body = self.call_slo(req)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(status, '206 Partial Content') self.assertEqual(status, '206 Partial Content')
self.assertEqual(headers['Content-Length'], '32') self.assertEqual(headers['Content-Length'], '32')
@ -2025,7 +2026,7 @@ class TestSloGetManifest(SloTestCase):
environ={'REQUEST_METHOD': 'GET'}, environ={'REQUEST_METHOD': 'GET'},
headers={'Range': 'bytes=0-0,2-2'}) headers={'Range': 'bytes=0-0,2-2'})
status, headers, body = self.call_slo(req) status, headers, body = self.call_slo(req)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(status, '200 OK') self.assertEqual(status, '200 OK')
self.assertEqual(headers['Content-Type'], 'application/json') self.assertEqual(headers['Content-Type'], 'application/json')
@ -2039,7 +2040,7 @@ class TestSloGetManifest(SloTestCase):
'/v1/AUTH_test/gettest/manifest-badjson', '/v1/AUTH_test/gettest/manifest-badjson',
environ={'REQUEST_METHOD': 'GET'}) environ={'REQUEST_METHOD': 'GET'})
status, headers, body = self.call_slo(req) status, headers, body = self.call_slo(req)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(status, '200 OK') self.assertEqual(status, '200 OK')
self.assertEqual(headers['Content-Length'], '0') self.assertEqual(headers['Content-Length'], '0')
@ -2113,7 +2114,7 @@ class TestSloGetManifest(SloTestCase):
'/v1/AUTH_test/gettest/manifest-abcd', '/v1/AUTH_test/gettest/manifest-abcd',
environ={'REQUEST_METHOD': 'HEAD'}) environ={'REQUEST_METHOD': 'HEAD'})
status, headers, body = self.call_slo(req) status, headers, body = self.call_slo(req)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertEqual(status, '200 OK') self.assertEqual(status, '200 OK')
self.assertEqual(headers['Content-Length'], '50') self.assertEqual(headers['Content-Length'], '50')
@ -2171,7 +2172,7 @@ class TestSloGetManifest(SloTestCase):
'/v1/AUTH_test/gettest/man1', '/v1/AUTH_test/gettest/man1',
environ={'REQUEST_METHOD': 'GET'}) environ={'REQUEST_METHOD': 'GET'})
status, headers, body, exc = self.call_slo(req, expect_exception=True) status, headers, body, exc = self.call_slo(req, expect_exception=True)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertIsInstance(exc, ListingIterError) self.assertIsInstance(exc, ListingIterError)
# we don't know at header-sending time that things are going to go # we don't know at header-sending time that things are going to go
@ -2319,7 +2320,7 @@ class TestSloGetManifest(SloTestCase):
'/v1/AUTH_test/gettest/manifest-abcd', '/v1/AUTH_test/gettest/manifest-abcd',
environ={'REQUEST_METHOD': 'GET'}) environ={'REQUEST_METHOD': 'GET'})
status, headers, body, exc = self.call_slo(req, expect_exception=True) status, headers, body, exc = self.call_slo(req, expect_exception=True)
headers = swob.HeaderKeyDict(headers) headers = HeaderKeyDict(headers)
self.assertIsInstance(exc, SegmentError) self.assertIsInstance(exc, SegmentError)
self.assertEqual(status, '200 OK') self.assertEqual(status, '200 OK')

View File

@ -35,7 +35,8 @@ from hashlib import sha1
from time import time from time import time
from swift.common.middleware import tempauth, tempurl from swift.common.middleware import tempauth, tempurl
from swift.common.swob import Request, Response, HeaderKeyDict from swift.common.header_key_dict import HeaderKeyDict
from swift.common.swob import Request, Response
from swift.common import utils from swift.common import utils

View File

@ -26,8 +26,9 @@ from six.moves import urllib
from swift.common import direct_client from swift.common import direct_client
from swift.common.exceptions import ClientException from swift.common.exceptions import ClientException
from swift.common.header_key_dict import HeaderKeyDict
from swift.common.utils import Timestamp from swift.common.utils import Timestamp
from swift.common.swob import HeaderKeyDict, RESPONSE_REASONS from swift.common.swob import RESPONSE_REASONS
from swift.common.storage_policy import POLICIES from swift.common.storage_policy import POLICIES
from six.moves.http_client import HTTPException from six.moves.http_client import HTTPException

View File

@ -0,0 +1,75 @@
# Copyright (c) 2012 OpenStack Foundation
#
# 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.
import unittest
from swift.common.header_key_dict import HeaderKeyDict
class TestHeaderKeyDict(unittest.TestCase):
def test_case_insensitive(self):
headers = HeaderKeyDict()
headers['Content-Length'] = 0
headers['CONTENT-LENGTH'] = 10
headers['content-length'] = 20
self.assertEqual(headers['Content-Length'], '20')
self.assertEqual(headers['content-length'], '20')
self.assertEqual(headers['CONTENT-LENGTH'], '20')
def test_setdefault(self):
headers = HeaderKeyDict()
# it gets set
headers.setdefault('x-rubber-ducky', 'the one')
self.assertEqual(headers['X-Rubber-Ducky'], 'the one')
# it has the right return value
ret = headers.setdefault('x-boat', 'dinghy')
self.assertEqual(ret, 'dinghy')
ret = headers.setdefault('x-boat', 'yacht')
self.assertEqual(ret, 'dinghy')
# shouldn't crash
headers.setdefault('x-sir-not-appearing-in-this-request', None)
def test_del_contains(self):
headers = HeaderKeyDict()
headers['Content-Length'] = 0
self.assertTrue('Content-Length' in headers)
del headers['Content-Length']
self.assertTrue('Content-Length' not in headers)
def test_update(self):
headers = HeaderKeyDict()
headers.update({'Content-Length': '0'})
headers.update([('Content-Type', 'text/plain')])
self.assertEqual(headers['Content-Length'], '0')
self.assertEqual(headers['Content-Type'], 'text/plain')
def test_get(self):
headers = HeaderKeyDict()
headers['content-length'] = 20
self.assertEqual(headers.get('CONTENT-LENGTH'), '20')
self.assertEqual(headers.get('something-else'), None)
self.assertEqual(headers.get('something-else', True), True)
def test_keys(self):
headers = HeaderKeyDict()
headers['content-length'] = 20
headers['cOnTent-tYpe'] = 'text/plain'
headers['SomeThing-eLse'] = 'somevalue'
self.assertEqual(
set(headers.keys()),
set(('Content-Length', 'Content-Type', 'Something-Else')))

View File

@ -27,6 +27,7 @@ from six.moves.urllib.parse import quote
from test.unit import FakeLogger from test.unit import FakeLogger
from eventlet.green import urllib2 from eventlet.green import urllib2
from swift.common import exceptions, internal_client, swob from swift.common import exceptions, internal_client, swob
from swift.common.header_key_dict import HeaderKeyDict
from swift.common.storage_policy import StoragePolicy from swift.common.storage_policy import StoragePolicy
from test.unit import with_tempdir, write_fake_ring, patch_policies from test.unit import with_tempdir, write_fake_ring, patch_policies
@ -1027,7 +1028,7 @@ class TestInternalClient(unittest.TestCase):
'user-agent': 'test', # from InternalClient.make_request 'user-agent': 'test', # from InternalClient.make_request
}) })
self.assertEqual(app.calls_with_headers, [( self.assertEqual(app.calls_with_headers, [(
'GET', path_info, swob.HeaderKeyDict(req_headers))]) 'GET', path_info, HeaderKeyDict(req_headers))])
def test_iter_object_lines(self): def test_iter_object_lines(self):
class InternalClient(internal_client.InternalClient): class InternalClient(internal_client.InternalClient):

View File

@ -98,64 +98,6 @@ class TestHeaderEnvironProxy(unittest.TestCase):
set(('Content-Length', 'Content-Type', 'Something-Else'))) set(('Content-Length', 'Content-Type', 'Something-Else')))
class TestHeaderKeyDict(unittest.TestCase):
def test_case_insensitive(self):
headers = swift.common.swob.HeaderKeyDict()
headers['Content-Length'] = 0
headers['CONTENT-LENGTH'] = 10
headers['content-length'] = 20
self.assertEqual(headers['Content-Length'], '20')
self.assertEqual(headers['content-length'], '20')
self.assertEqual(headers['CONTENT-LENGTH'], '20')
def test_setdefault(self):
headers = swift.common.swob.HeaderKeyDict()
# it gets set
headers.setdefault('x-rubber-ducky', 'the one')
self.assertEqual(headers['X-Rubber-Ducky'], 'the one')
# it has the right return value
ret = headers.setdefault('x-boat', 'dinghy')
self.assertEqual(ret, 'dinghy')
ret = headers.setdefault('x-boat', 'yacht')
self.assertEqual(ret, 'dinghy')
# shouldn't crash
headers.setdefault('x-sir-not-appearing-in-this-request', None)
def test_del_contains(self):
headers = swift.common.swob.HeaderKeyDict()
headers['Content-Length'] = 0
self.assertTrue('Content-Length' in headers)
del headers['Content-Length']
self.assertTrue('Content-Length' not in headers)
def test_update(self):
headers = swift.common.swob.HeaderKeyDict()
headers.update({'Content-Length': '0'})
headers.update([('Content-Type', 'text/plain')])
self.assertEqual(headers['Content-Length'], '0')
self.assertEqual(headers['Content-Type'], 'text/plain')
def test_get(self):
headers = swift.common.swob.HeaderKeyDict()
headers['content-length'] = 20
self.assertEqual(headers.get('CONTENT-LENGTH'), '20')
self.assertEqual(headers.get('something-else'), None)
self.assertEqual(headers.get('something-else', True), True)
def test_keys(self):
headers = swift.common.swob.HeaderKeyDict()
headers['content-length'] = 20
headers['cOnTent-tYpe'] = 'text/plain'
headers['SomeThing-eLse'] = 'somevalue'
self.assertEqual(
set(headers.keys()),
set(('Content-Length', 'Content-Type', 'Something-Else')))
class TestRange(unittest.TestCase): class TestRange(unittest.TestCase):
def test_range(self): def test_range(self):
swob_range = swift.common.swob.Range('bytes=1-7') swob_range = swift.common.swob.Range('bytes=1-7')

View File

@ -60,7 +60,8 @@ from swift.common.exceptions import Timeout, MessageTimeout, \
MimeInvalid, ThreadPoolDead MimeInvalid, ThreadPoolDead
from swift.common import utils from swift.common import utils
from swift.common.container_sync_realms import ContainerSyncRealms from swift.common.container_sync_realms import ContainerSyncRealms
from swift.common.swob import Request, Response, HeaderKeyDict from swift.common.header_key_dict import HeaderKeyDict
from swift.common.swob import Request, Response
from test.unit import FakeLogger from test.unit import FakeLogger
threading = eventlet.patcher.original('threading') threading = eventlet.patcher.original('threading')

View File

@ -31,6 +31,7 @@ from swift.container import reconciler
from swift.container.server import gen_resp_headers from swift.container.server import gen_resp_headers
from swift.common.direct_client import ClientException from swift.common.direct_client import ClientException
from swift.common import swob from swift.common import swob
from swift.common.header_key_dict import HeaderKeyDict
from swift.common.utils import split_path, Timestamp, encode_timestamps from swift.common.utils import split_path, Timestamp, encode_timestamps
from test.unit import debug_logger, FakeRing, fake_http_connect from test.unit import debug_logger, FakeRing, fake_http_connect
@ -43,7 +44,7 @@ def timestamp_to_last_modified(timestamp):
def container_resp_headers(**kwargs): def container_resp_headers(**kwargs):
return swob.HeaderKeyDict(gen_resp_headers(kwargs)) return HeaderKeyDict(gen_resp_headers(kwargs))
class FakeStoragePolicySwift(object): class FakeStoragePolicySwift(object):

View File

@ -34,8 +34,8 @@ from six import BytesIO
from six import StringIO from six import StringIO
from swift import __version__ as swift_version from swift import __version__ as swift_version
from swift.common.swob import (Request, HeaderKeyDict, from swift.common.header_key_dict import HeaderKeyDict
WsgiBytesIO, HTTPNoContent) from swift.common.swob import (Request, WsgiBytesIO, HTTPNoContent)
import swift.container import swift.container
from swift.container import server as container_server from swift.container import server as container_server
from swift.common import constraints from swift.common import constraints

View File

@ -30,8 +30,8 @@ from contextlib import closing, contextmanager
from gzip import GzipFile from gzip import GzipFile
from shutil import rmtree from shutil import rmtree
from swift.common import utils from swift.common import utils
from swift.common.swob import HeaderKeyDict
from swift.common.exceptions import DiskFileError from swift.common.exceptions import DiskFileError
from swift.common.header_key_dict import HeaderKeyDict
from swift.obj import diskfile, reconstructor as object_reconstructor from swift.obj import diskfile, reconstructor as object_reconstructor
from swift.common import ring from swift.common import ring
from swift.common.storage_policy import (StoragePolicy, ECStoragePolicy, from swift.common.storage_policy import (StoragePolicy, ECStoragePolicy,

View File

@ -50,11 +50,12 @@ from test.unit import connect_tcp, readuntil2crlfs, patch_policies
from swift.obj import server as object_server from swift.obj import server as object_server
from swift.obj import diskfile from swift.obj import diskfile
from swift.common import utils, bufferedhttp from swift.common import utils, bufferedhttp
from swift.common.header_key_dict import HeaderKeyDict
from swift.common.utils import hash_path, mkdirs, normalize_timestamp, \ from swift.common.utils import hash_path, mkdirs, normalize_timestamp, \
NullLogger, storage_directory, public, replication, encode_timestamps, \ NullLogger, storage_directory, public, replication, encode_timestamps, \
Timestamp Timestamp
from swift.common import constraints from swift.common import constraints
from swift.common.swob import Request, HeaderKeyDict, WsgiBytesIO from swift.common.swob import Request, WsgiBytesIO
from swift.common.splice import splice from swift.common.splice import splice
from swift.common.storage_policy import (StoragePolicy, ECStoragePolicy, from swift.common.storage_policy import (StoragePolicy, ECStoragePolicy,
POLICIES, EC_POLICY) POLICIES, EC_POLICY)

View File

@ -35,9 +35,9 @@ from swift.obj.diskfile import (ASYNCDIR_BASE, get_async_dir, DiskFileManager,
get_tmp_dir) get_tmp_dir)
from swift.common.ring import RingData from swift.common.ring import RingData
from swift.common import utils from swift.common import utils
from swift.common.header_key_dict import HeaderKeyDict
from swift.common.utils import hash_path, normalize_timestamp, mkdirs, \ from swift.common.utils import hash_path, normalize_timestamp, mkdirs, \
write_pickle write_pickle
from swift.common import swob
from test.unit import debug_logger, patch_policies, mocked_http_conn from test.unit import debug_logger, patch_policies, mocked_http_conn
from swift.common.storage_policy import StoragePolicy, POLICIES from swift.common.storage_policy import StoragePolicy, POLICIES
@ -316,7 +316,7 @@ class TestObjectUpdater(unittest.TestCase):
out.flush() out.flush()
self.assertEqual(inc.readline(), self.assertEqual(inc.readline(),
'PUT /sda1/0/a/c/o HTTP/1.1\r\n') 'PUT /sda1/0/a/c/o HTTP/1.1\r\n')
headers = swob.HeaderKeyDict() headers = HeaderKeyDict()
line = inc.readline() line = inc.readline()
while line and line != '\r\n': while line and line != '\r\n':
headers[line.split(':')[0]] = \ headers[line.split(':')[0]] = \
@ -404,7 +404,7 @@ class TestObjectUpdater(unittest.TestCase):
daemon = object_updater.ObjectUpdater(conf, logger=self.logger) daemon = object_updater.ObjectUpdater(conf, logger=self.logger)
dfmanager = DiskFileManager(conf, daemon.logger) dfmanager = DiskFileManager(conf, daemon.logger)
# don't include storage-policy-index in headers_out pickle # don't include storage-policy-index in headers_out pickle
headers_out = swob.HeaderKeyDict({ headers_out = HeaderKeyDict({
'x-size': 0, 'x-size': 0,
'x-content-type': 'text/plain', 'x-content-type': 'text/plain',
'x-etag': 'd41d8cd98f00b204e9800998ecf8427e', 'x-etag': 'd41d8cd98f00b204e9800998ecf8427e',
@ -452,7 +452,7 @@ class TestObjectUpdater(unittest.TestCase):
dfmanager = DiskFileManager(conf, daemon.logger) dfmanager = DiskFileManager(conf, daemon.logger)
account, container, obj = 'a', 'c', 'o' account, container, obj = 'a', 'c', 'o'
op = 'PUT' op = 'PUT'
headers_out = swob.HeaderKeyDict({ headers_out = HeaderKeyDict({
'x-size': 0, 'x-size': 0,
'x-content-type': 'text/plain', 'x-content-type': 'text/plain',
'x-etag': 'd41d8cd98f00b204e9800998ecf8427e', 'x-etag': 'd41d8cd98f00b204e9800998ecf8427e',

View File

@ -23,10 +23,10 @@ from swift.proxy.controllers.base import headers_to_container_info, \
get_object_env_key, get_info, get_object_info, \ get_object_env_key, get_info, get_object_info, \
Controller, GetOrHeadHandler, _set_info_cache, _set_object_info_cache, \ Controller, GetOrHeadHandler, _set_info_cache, _set_object_info_cache, \
bytes_to_skip bytes_to_skip
from swift.common.swob import Request, HTTPException, HeaderKeyDict, \ from swift.common.swob import Request, HTTPException, RESPONSE_REASONS
RESPONSE_REASONS
from swift.common import exceptions from swift.common import exceptions
from swift.common.utils import split_path from swift.common.utils import split_path
from swift.common.header_key_dict import HeaderKeyDict
from swift.common.http import is_success from swift.common.http import is_success
from swift.common.storage_policy import StoragePolicy from swift.common.storage_policy import StoragePolicy
from test.unit import fake_http_connect, FakeRing, FakeMemcache from test.unit import fake_http_connect, FakeRing, FakeMemcache

View File

@ -31,6 +31,7 @@ from six.moves import range
import swift import swift
from swift.common import utils, swob, exceptions from swift.common import utils, swob, exceptions
from swift.common.header_key_dict import HeaderKeyDict
from swift.proxy import server as proxy_server from swift.proxy import server as proxy_server
from swift.proxy.controllers import obj from swift.proxy.controllers import obj
from swift.proxy.controllers.base import get_info as _real_get_info from swift.proxy.controllers.base import get_info as _real_get_info
@ -1074,7 +1075,7 @@ class StubResponse(object):
self.status = status self.status = status
self.body = body self.body = body
self.readable = BytesIO(body) self.readable = BytesIO(body)
self.headers = swob.HeaderKeyDict(headers) self.headers = HeaderKeyDict(headers)
fake_reason = ('Fake', 'This response is a lie.') fake_reason = ('Fake', 'This response is a lie.')
self.reason = swob.RESPONSE_REASONS.get(status, fake_reason)[0] self.reason = swob.RESPONSE_REASONS.get(status, fake_reason)[0]

View File

@ -74,8 +74,9 @@ from swift.proxy.controllers.base import get_container_memcache_key, \
get_account_memcache_key, cors_validation, _get_info_cache get_account_memcache_key, cors_validation, _get_info_cache
import swift.proxy.controllers import swift.proxy.controllers
import swift.proxy.controllers.obj import swift.proxy.controllers.obj
from swift.common.header_key_dict import HeaderKeyDict
from swift.common.swob import Request, Response, HTTPUnauthorized, \ from swift.common.swob import Request, Response, HTTPUnauthorized, \
HTTPException, HeaderKeyDict, HTTPBadRequest HTTPException, HTTPBadRequest
from swift.common import storage_policy from swift.common import storage_policy
from swift.common.storage_policy import StoragePolicy, ECStoragePolicy, \ from swift.common.storage_policy import StoragePolicy, ECStoragePolicy, \
StoragePolicyCollection, POLICIES StoragePolicyCollection, POLICIES