diff --git a/aiohttp/worker.py b/aiohttp/worker.py index e2c707d207e..78505dfc34f 100644 --- a/aiohttp/worker.py +++ b/aiohttp/worker.py @@ -4,6 +4,7 @@ import logging import os import signal +import ssl import sys import gunicorn.workers.base as base @@ -80,9 +81,13 @@ def close(self): @asyncio.coroutine def _run(self): + + ctx = self._create_ssl_context(self.cfg) if self.cfg.is_ssl else None + for sock in self.sockets: handler = self.make_handler(self.wsgi) - srv = yield from self.loop.create_server(handler, sock=sock.sock) + srv = yield from self.loop.create_server(handler, sock=sock.sock, + ssl=ctx) self.servers[srv] = handler # If our parent changed then we shut down. @@ -142,6 +147,21 @@ def handle_abort(self, sig, frame): self.alive = False self.exit_code = 1 + @staticmethod + def _create_ssl_context(cfg): + """ Creates SSLContext instance for usage in asyncio.create_server. + + See ssl.SSLSocket.__init__ for more details. + """ + ctx = ssl.SSLContext(cfg.ssl_version) + ctx.load_cert_chain(cfg.certfile, cfg.keyfile) + ctx.verify_mode = cfg.cert_reqs + if cfg.ca_certs: + ctx.load_verify_locations(cfg.ca_certs) + if cfg.ciphers: + ctx.set_ciphers(cfg.ciphers) + return ctx + class GunicornUVLoopWebWorker(GunicornWebWorker): diff --git a/tests/test_worker.py b/tests/test_worker.py index 15abe1d9f9e..889c3cabbe4 100644 --- a/tests/test_worker.py +++ b/tests/test_worker.py @@ -116,15 +116,23 @@ def test__run_ok(worker, loop): ret.set_result(sock) worker.wsgi.make_handler.return_value.num_connections = 1 worker.cfg.max_requests = 100 + worker.cfg.is_ssl = True - with mock.patch('aiohttp.worker.asyncio') as m_asyncio: - m_asyncio.sleep = mock.Mock( - wraps=asyncio.coroutine(lambda *a, **kw: None)) - loop.run_until_complete(worker._run()) + ssl_context = mock.Mock() + with mock.patch('ssl.SSLContext', return_value=ssl_context): + with mock.patch('aiohttp.worker.asyncio') as m_asyncio: + m_asyncio.sleep = mock.Mock( + wraps=asyncio.coroutine(lambda *a, **kw: None)) + loop.run_until_complete(worker._run()) assert worker.notify.called assert worker.log.info.called + args, kwargs = loop.create_server.call_args + assert 'ssl' in kwargs + ctx = kwargs['ssl'] + assert ctx is ssl_context + def test__run_exc(worker, loop): with mock.patch('aiohttp.worker.os') as m_os: @@ -138,6 +146,7 @@ def test__run_exc(worker, loop): worker.log = mock.Mock() worker.loop = mock.Mock() worker.notify = mock.Mock() + worker.cfg.is_ssl = False with mock.patch('aiohttp.worker.asyncio.sleep') as m_sleep: slp = helpers.create_future(loop)