执行批量聚合请求时,aiohttp不通过cookie

时间:2019-01-11 15:00:12

标签: cookies session-cookies aiohttp

我正在使用aiohttp开发api网关服务,该服务跨多个内部服务执行聚合操作,并将它们打包为207批量响应。

在内部,我们使用Django会话cookie作为主要的身份验证手段(计划于今年第二季度移至JWT),这意味着对于受此网关攻击的服务,我需要从浏览器或Rest API请求。

似乎aiohttp根本没有这样做,也没有在Postman Cookies标头中提供任何cookie。但是,如果我使用相同的Cookie直接访问该服务,则会得到预期的响应。

现在的代码:

class AggregateView(BaseView):
    async def post(self):
        requests = await self.request.json()
        logger.debug(f'Making [{len(requests)}] service calls at [{datetime.now()}]')
        queries = []
        async with ClientSession(cookie_jar=CookieJar(unsafe=True)) as session:
            for req in requests:
                queries.append(self._retrieve(req, session))

            logger.debug(f'Async calls created [{datetime.now()}]')
            results = await asyncio.gather(*queries)
            logger.debug(f'Async calls completed and aggregated [{datetime.now()}]')

        return web.json_response(
                status=207,
                data=results
        )

class BaseView(web.View):
    @cache
    async def _retrieve(self, req, session):
        """
        Unpacks a request body and executes the appropriate service call
        :param request: request body as dictionary
        :param session: aiohttp ClientSession
        :return:
        """
        url, path, query_params = await self._unpack_request(req)

        logger.info(f'{url}/{path}\t{query_params}')
        logger.info(f'Starting request for url [{url}/{path}] at [{datetime.now()}]')
        logger.info(f'with query params {query_params}')

        func = session.get
        params = {
            'url': f'{url}/{path}',
            'params': query_params,
            'headers': {
                'Vary': 'Accept, Origin, Accept, Accept-Encoding, Authorization, Cookie'
            }
        }

        async with AsyncBreaker(circuit_breaker, params['url'], func, **params) as resp:
            logger.info(f'received request for url [{url}/{path}] at [{datetime.now()}]')
            logger.info(resp.headers)
            logger.info(resp.cookies)
            return {
                'url': f'{url}/{path}',
                'status': resp.status,
                'response': await resp.json()
            }


def cache(func):
    @functools.wraps(func)
    async def wrapper(*args, **kwargs):
        request = args[1]
        access_logger.info(args[2].cookie_jar._cookies.keys())

        requested_service = request.get('service').upper()
        service = SERVICES.get(requested_service)
        if service and service.get('cache'):
            access_logger.info('This response is cacheable.')
            pass

        return await func(*args, **kwargs)

    return wrapper

dict_keys([]) # output in #cache for cookie jar inspection
This response is cacheable.
Starting request for url [https://service.company.com/api/v1/home-editorial/]
 at [2019-01-11 15:01:03.983993]
with query params None
received request for url [https://service.company.com/api/v1/home-editorial/]
 at [2019-01-11 15:01:04.434696]
Header output: <CIMultiDictProxy('Server': 'nginx/1.11.3', 'Content-Type': 
'application/json', 'Www-Authenticate': 'Token', 'Allow': 'GET, HEAD, 
OPTIONS', 'X-Frame-Options': 'SAMEORIGIN', 'Strict-Transport-Security': 
'max-age=15724800; includeSubDomains; preload', 'Accept-Ranges': 'bytes',
 'Content-Length': '58', 'Accept-Ranges': 'bytes', 'Date': 
'Fri, 11 Jan 2019 15:01:04 GMT', 'Via': '1.1 varnish', 'Connection': 
'keep-alive', 'X-Client-IP': '192.150.73.149', 'X-Served-By': 
'cache-bos8232-BOS', 'X-Cache': 'MISS', 'X-Cache-Hits': '0', 
'X-Timer': 'S1547218864.246313,VS0,VE152', 'Vary': 'Accept, Origin')>

注意:

  • AsyncBreaker使用aiobreaker来使用断路器模式来保护服务免受过载
  • @cache装饰器当前只包装了检索方法,并用于检查AggregateViewClientSession的属性。解决此问题后,它将在aiocache中具有更全面的功能。

0 个答案:

没有答案