Disable case-changing behavior in Eventlet
RFC 2616 says that HTTP header fields are case-insensitive. However, there are some S3 clients who don't accept normalized header by Swift and Eventlet. For example, AWS Java SDK expects that an etag header is 'ETag', not 'Etag'. This patch disables Eventlet's header capitalization so that the swift3 middleware can normalize the response headers as those clients expect. Note that this change requires a fix for Eventlet, which will be included in the next Eventlet release (v0.15). Change-Id: I6d3428b0dafef776bdb3ebac7639b3126fa5e60d
This commit is contained in:
parent
92fb1c15da
commit
f2774a4d11
|
@ -253,10 +253,10 @@ class ProxyLoggingMiddleware(object):
|
|||
break
|
||||
else:
|
||||
if not chunk:
|
||||
start_response_args[0][1].append(('content-length', '0'))
|
||||
start_response_args[0][1].append(('Content-Length', '0'))
|
||||
elif isinstance(iterable, list):
|
||||
start_response_args[0][1].append(
|
||||
('content-length', str(sum(len(i) for i in iterable))))
|
||||
('Content-Length', str(sum(len(i) for i in iterable))))
|
||||
start_response(*start_response_args[0])
|
||||
req = Request(env)
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
"""WSGI tools for use with swift."""
|
||||
|
||||
import errno
|
||||
import inspect
|
||||
import os
|
||||
import signal
|
||||
import time
|
||||
|
@ -386,7 +387,14 @@ def run_server(conf, logger, sock, global_conf=None):
|
|||
max_clients = int(conf.get('max_clients', '1024'))
|
||||
pool = RestrictedGreenPool(size=max_clients)
|
||||
try:
|
||||
wsgi.server(sock, app, NullLogger(), custom_pool=pool)
|
||||
# Disable capitalizing headers in Eventlet if possible. This is
|
||||
# necessary for the AWS SDK to work with swift3 middleware.
|
||||
argspec = inspect.getargspec(wsgi.server)
|
||||
if 'capitalize_response_headers' in argspec.args:
|
||||
wsgi.server(sock, app, NullLogger(), custom_pool=pool,
|
||||
capitalize_response_headers=False)
|
||||
else:
|
||||
wsgi.server(sock, app, NullLogger(), custom_pool=pool)
|
||||
except socket.error as err:
|
||||
if err[0] != errno.EINVAL:
|
||||
raise
|
||||
|
|
|
@ -335,10 +335,11 @@ class TestWSGI(unittest.TestCase):
|
|||
'modify_wsgi_pipeline'):
|
||||
with mock.patch('swift.common.wsgi.wsgi') as _wsgi:
|
||||
with mock.patch('swift.common.wsgi.eventlet') as _eventlet:
|
||||
conf = wsgi.appconfig(conf_file)
|
||||
logger = logging.getLogger('test')
|
||||
sock = listen(('localhost', 0))
|
||||
wsgi.run_server(conf, logger, sock)
|
||||
with mock.patch('swift.common.wsgi.inspect'):
|
||||
conf = wsgi.appconfig(conf_file)
|
||||
logger = logging.getLogger('test')
|
||||
sock = listen(('localhost', 0))
|
||||
wsgi.run_server(conf, logger, sock)
|
||||
self.assertEquals('HTTP/1.0',
|
||||
_wsgi.HttpProtocol.default_request_version)
|
||||
self.assertEquals(30, _wsgi.WRITE_TIMEOUT)
|
||||
|
@ -356,6 +357,43 @@ class TestWSGI(unittest.TestCase):
|
|||
self.assert_('custom_pool' in kwargs)
|
||||
self.assertEquals(1000, kwargs['custom_pool'].size)
|
||||
|
||||
def test_run_server_with_latest_eventlet(self):
|
||||
config = """
|
||||
[DEFAULT]
|
||||
swift_dir = TEMPDIR
|
||||
|
||||
[pipeline:main]
|
||||
pipeline = proxy-server
|
||||
|
||||
[app:proxy-server]
|
||||
use = egg:swift#proxy
|
||||
"""
|
||||
|
||||
def argspec_stub(server):
|
||||
return mock.MagicMock(args=['capitalize_response_headers'])
|
||||
|
||||
contents = dedent(config)
|
||||
with temptree(['proxy-server.conf']) as t:
|
||||
conf_file = os.path.join(t, 'proxy-server.conf')
|
||||
with open(conf_file, 'w') as f:
|
||||
f.write(contents.replace('TEMPDIR', t))
|
||||
_fake_rings(t)
|
||||
with nested(
|
||||
mock.patch('swift.proxy.server.Application.'
|
||||
'modify_wsgi_pipeline'),
|
||||
mock.patch('swift.common.wsgi.wsgi'),
|
||||
mock.patch('swift.common.wsgi.eventlet'),
|
||||
mock.patch('swift.common.wsgi.inspect',
|
||||
getargspec=argspec_stub)) as (_, _wsgi, _, _):
|
||||
conf = wsgi.appconfig(conf_file)
|
||||
logger = logging.getLogger('test')
|
||||
sock = listen(('localhost', 0))
|
||||
wsgi.run_server(conf, logger, sock)
|
||||
|
||||
_wsgi.server.assert_called()
|
||||
args, kwargs = _wsgi.server.call_args
|
||||
self.assertEquals(kwargs.get('capitalize_response_headers'), False)
|
||||
|
||||
def test_run_server_conf_dir(self):
|
||||
config_dir = {
|
||||
'proxy-server.conf.d/pipeline.conf': """
|
||||
|
@ -384,11 +422,12 @@ class TestWSGI(unittest.TestCase):
|
|||
with mock.patch('swift.common.wsgi.wsgi') as _wsgi:
|
||||
with mock.patch('swift.common.wsgi.eventlet') as _eventlet:
|
||||
with mock.patch.dict('os.environ', {'TZ': ''}):
|
||||
conf = wsgi.appconfig(conf_dir)
|
||||
logger = logging.getLogger('test')
|
||||
sock = listen(('localhost', 0))
|
||||
wsgi.run_server(conf, logger, sock)
|
||||
self.assert_(os.environ['TZ'] is not '')
|
||||
with mock.patch('swift.common.wsgi.inspect'):
|
||||
conf = wsgi.appconfig(conf_dir)
|
||||
logger = logging.getLogger('test')
|
||||
sock = listen(('localhost', 0))
|
||||
wsgi.run_server(conf, logger, sock)
|
||||
self.assert_(os.environ['TZ'] is not '')
|
||||
|
||||
self.assertEquals('HTTP/1.0',
|
||||
_wsgi.HttpProtocol.default_request_version)
|
||||
|
|
Loading…
Reference in New Issue