from types import MappingProxyType from urllib.parse import urlparse from aiohttp import web from aiohttp_session import get_session, session_middleware from aiohttp_session.redis_storage import RedisStorage from aioredis import create_pool def create_app(**options): """Create aiohttp app with custom middleware.""" app = web.Application(middlewares=[ session_middleware_factory, ]) app.router.add_route('GET', '/', view) app.settings = MappingProxyType(dict( REDIS_URL='redis://127.0.0.1:6379/0', **options )) return app async def session_middleware_factory(app, handler): """Wrapper to Session Middleware factory. Create Redis pool and setup session storage inside of coroutine. """ # Parse Redis URL parsed = urlparse(app.settings['REDIS_URL']) # Create Redis connection pool pool = await create_pool( (parsed.hostname, parsed.port), db=int(parsed.path.lstrip('/')), ) # Do the trick, by passing app & handler back to original session # middleware factory. Do not forget to await on results here as original # session middleware factory is also awaitable. return await session_middleware(RedisStorage(pool))(app, handler) async def view(request): """View function to work with session.""" session = await get_session(request) session['counter'] = (session.get('counter') or 0) + 1 return web.json_response({ 'counter': session['counter'], }) #: Global application to serve with Gunicorn app = create_app()