def test_filter_cookie_with_unicode_domain(loop) -> None: jar = CookieJar(loop=loop) jar.update_cookies(SimpleCookie( "idna-domain-first=first; Domain=xn--9caa.com; Path=/; " )) assert len(jar.filter_cookies(URL("http://éé.com"))) == 1 assert len(jar.filter_cookies(URL("http://xn--9caa.com"))) == 1
def test_domain_filter_ip_cookie_send(loop): jar = CookieJar(loop=loop) cookies = SimpleCookie( "shared-cookie=first; " "domain-cookie=second; Domain=example.com; " "subdomain1-cookie=third; Domain=test1.example.com; " "subdomain2-cookie=fourth; Domain=test2.example.com; " "dotted-domain-cookie=fifth; Domain=.example.com; " "different-domain-cookie=sixth; Domain=different.org; " "secure-cookie=seventh; Domain=secure.com; Secure; " "no-path-cookie=eighth; Domain=pathtest.com; " "path1-cookie=nineth; Domain=pathtest.com; Path=/; " "path2-cookie=tenth; Domain=pathtest.com; Path=/one; " "path3-cookie=eleventh; Domain=pathtest.com; Path=/one/two; " "path4-cookie=twelfth; Domain=pathtest.com; Path=/one/two/; " "expires-cookie=thirteenth; Domain=expirestest.com; Path=/;" " Expires=Tue, 1 Jan 1980 12:00:00 GMT; " "max-age-cookie=fourteenth; Domain=maxagetest.com; Path=/;" " Max-Age=60; " "invalid-max-age-cookie=fifteenth; Domain=invalid-values.com; " " Max-Age=string; " "invalid-expires-cookie=sixteenth; Domain=invalid-values.com; " " Expires=string;") jar.update_cookies(cookies) cookies_sent = jar.filter_cookies( URL("http://1.2.3.4/")).output(header='Cookie:') assert cookies_sent == 'Cookie: shared-cookie=first'
async def test_quotes_correctly_based_on_input( loop: Any, cookies: Any, expected: Any, quote_bool: Any ) -> None: jar = CookieJar(unsafe=True, quote_cookie=quote_bool) jar.update_cookies(SimpleCookie(cookies)) cookies_sent = jar.filter_cookies(URL("http://127.0.0.1/")).output(header="Cookie:") assert cookies_sent == expected
def _build_cookie_header(session, cookies, cookie_header, url): url, _ = strip_auth_from_url(url) all_cookies = session._cookie_jar.filter_cookies(url) if cookies is not None: tmp_cookie_jar = CookieJar() tmp_cookie_jar.update_cookies(cookies) req_cookies = tmp_cookie_jar.filter_cookies(url) if req_cookies: all_cookies.load(req_cookies) if not all_cookies and not cookie_header: return None c = SimpleCookie() if cookie_header: c.load(cookie_header) for name, value in all_cookies.items(): if isinstance(value, Morsel): mrsl_val = value.get(value.key, Morsel()) mrsl_val.set(value.key, value.value, value.coded_value) c[name] = mrsl_val else: c[name] = value return c.output(header="", sep=";").strip()
def test_domain_filter_ip_cookie_send(loop) -> None: jar = CookieJar(loop=loop) cookies = SimpleCookie( "shared-cookie=first; " "domain-cookie=second; Domain=example.com; " "subdomain1-cookie=third; Domain=test1.example.com; " "subdomain2-cookie=fourth; Domain=test2.example.com; " "dotted-domain-cookie=fifth; Domain=.example.com; " "different-domain-cookie=sixth; Domain=different.org; " "secure-cookie=seventh; Domain=secure.com; Secure; " "no-path-cookie=eighth; Domain=pathtest.com; " "path1-cookie=nineth; Domain=pathtest.com; Path=/; " "path2-cookie=tenth; Domain=pathtest.com; Path=/one; " "path3-cookie=eleventh; Domain=pathtest.com; Path=/one/two; " "path4-cookie=twelfth; Domain=pathtest.com; Path=/one/two/; " "expires-cookie=thirteenth; Domain=expirestest.com; Path=/;" " Expires=Tue, 1 Jan 1980 12:00:00 GMT; " "max-age-cookie=fourteenth; Domain=maxagetest.com; Path=/;" " Max-Age=60; " "invalid-max-age-cookie=fifteenth; Domain=invalid-values.com; " " Max-Age=string; " "invalid-expires-cookie=sixteenth; Domain=invalid-values.com; " " Expires=string;" ) jar.update_cookies(cookies) cookies_sent = jar.filter_cookies(URL("http://1.2.3.4/")).output( header='Cookie:') assert cookies_sent == 'Cookie: shared-cookie=first'
async def test_secure_cookie_not_filtered_from_unsafe_cookiejar_when_given_unsecured_endpoint( ) -> None: """Secure SimpleCookie should not be filtered from unsafe CookieJar when given an unsecured endpoint. There are times when sending a secure cookie to an unsecured endpoint is desireable. Such an occasion is during testing. RFC 6265 section-4.1.2.5 states that this behaviour is a decision based on the trust of a network by the user agent. """ endpoint = 'http://127.0.0.1/' secure_cookie = SimpleCookie( "cookie-key=cookie-value; HttpOnly; Path=/; Secure", ) jar = CookieJar(unsafe=True) # Confirm the jar is empty assert len(jar) == 0 jar.update_cookies( secure_cookie, URL(endpoint), ) # Confirm the jar contains the cookie assert len(jar) == 1 filtered_cookies = jar.filter_cookies(request_url=endpoint) # Confirm the filtered results contain the cookie assert len(filtered_cookies) == 1
async def session(): """Client session that can be used in tests.""" jar = CookieJar() jar.load(os.path.join(resource_path, "dummy_cookies.pickle")) sess = ClientSession(headers={"Connection": "keep-alive"}, cookie_jar=jar) yield sess await sess.close()
def test_preserving_quoted_cookies(loop): jar = CookieJar(loop=loop, unsafe=True) jar.update_cookies(SimpleCookie( "ip-cookie=\"second\"; Domain=127.0.0.1;" )) cookies_sent = jar.filter_cookies(URL("http://127.0.0.1/")).output( header='Cookie:') assert cookies_sent == 'Cookie: ip-cookie=\"second\"'
def test_preserving_quoted_cookies(loop) -> None: jar = CookieJar(loop=loop, unsafe=True) jar.update_cookies(SimpleCookie( "ip-cookie=\"second\"; Domain=127.0.0.1;" )) cookies_sent = jar.filter_cookies(URL("http://127.0.0.1/")).output( header='Cookie:') assert cookies_sent == 'Cookie: ip-cookie=\"second\"'
def test_ignore_domain_ending_with_dot(loop) -> None: jar = CookieJar(loop=loop, unsafe=True) jar.update_cookies(SimpleCookie("cookie=val; Domain=example.com.;"), URL("http://www.example.com")) cookies_sent = jar.filter_cookies(URL("http://www.example.com/")) assert cookies_sent.output(header='Cookie:') == "Cookie: cookie=val" cookies_sent = jar.filter_cookies(URL("http://example.com/")) assert cookies_sent.output(header='Cookie:') == ""
def function761(arg2357): var1898 = CookieJar(loop=arg2357) var1347 = SimpleCookie( 'shared-cookie=first; domain-cookie=second; Domain=example.com; subdomain1-cookie=third; Domain=test1.example.com; subdomain2-cookie=fourth; Domain=test2.example.com; dotted-domain-cookie=fifth; Domain=.example.com; different-domain-cookie=sixth; Domain=different.org; secure-cookie=seventh; Domain=secure.com; Secure; no-path-cookie=eighth; Domain=pathtest.com; path1-cookie=nineth; Domain=pathtest.com; Path=/; path2-cookie=tenth; Domain=pathtest.com; Path=/one; path3-cookie=eleventh; Domain=pathtest.com; Path=/one/two; path4-cookie=twelfth; Domain=pathtest.com; Path=/one/two/; expires-cookie=thirteenth; Domain=expirestest.com; Path=/; Expires=Tue, 1 Jan 1980 12:00:00 GMT; max-age-cookie=fourteenth; Domain=maxagetest.com; Path=/; Max-Age=60; invalid-max-age-cookie=fifteenth; Domain=invalid-values.com; Max-Age=string; invalid-expires-cookie=sixteenth; Domain=invalid-values.com; Expires=string;' ) var1898.update_cookies(var1347) var25 = var1898.filter_cookies( URL('http://1.2.3.4/')).output(header='Cookie:') assert (var25 == 'Cookie: shared-cookie=first')
def function829(self): super().function829() self.function674 = SimpleCookie( 'shared-cookie=first; domain-cookie=second; Domain=example.com; subdomain1-cookie=third; Domain=test1.example.com; subdomain2-cookie=fourth; Domain=test2.example.com; dotted-domain-cookie=fifth; Domain=.example.com; different-domain-cookie=sixth; Domain=different.org; secure-cookie=seventh; Domain=secure.com; Secure; no-path-cookie=eighth; Domain=pathtest.com; path1-cookie=nineth; Domain=pathtest.com; Path=/; path2-cookie=tenth; Domain=pathtest.com; Path=/one; path3-cookie=eleventh; Domain=pathtest.com; Path=/one/two; path4-cookie=twelfth; Domain=pathtest.com; Path=/one/two/; expires-cookie=thirteenth; Domain=expirestest.com; Path=/; Expires=Tue, 1 Jan 1980 12:00:00 GMT; max-age-cookie=fourteenth; Domain=maxagetest.com; Path=/; Max-Age=60; invalid-max-age-cookie=fifteenth; Domain=invalid-values.com; Max-Age=string; invalid-expires-cookie=sixteenth; Domain=invalid-values.com; Expires=string;' ) self.function1086 = SimpleCookie( 'unconstrained-cookie=first; Path=/; domain-cookie=second; Domain=example.com; Path=/; subdomain1-cookie=third; Domain=test1.example.com; Path=/; subdomain2-cookie=fourth; Domain=test2.example.com; Path=/; dotted-domain-cookie=fifth; Domain=.example.com; Path=/; different-domain-cookie=sixth; Domain=different.org; Path=/; no-path-cookie=seventh; Domain=pathtest.com; path-cookie=eighth; Domain=pathtest.com; Path=/somepath; wrong-path-cookie=nineth; Domain=pathtest.com; Path=somepath;' ) self.attribute684 = CookieJar(loop=self.attribute702)
def function364(arg532, function674, function1086): var1201 = CookieJar(loop=arg532) var1201.update_cookies(function674) var3419 = SimpleCookie() for var3474 in var1201: dict.__setitem__(var3419, var3474.key, var3474) var3194 = function674 assert (var3419 == var3194) assert (var1201._loop is arg532)
async def test_preserving_ip_domain_cookies(loop) -> None: jar = CookieJar(unsafe=True) jar.update_cookies( SimpleCookie("shared-cookie=first; " "ip-cookie=second; Domain=127.0.0.1;")) cookies_sent = jar.filter_cookies( URL("http://127.0.0.1/")).output(header='Cookie:') assert cookies_sent == ('Cookie: ip-cookie=second\r\n' 'Cookie: shared-cookie=first')
def test_constructor(loop, cookies_to_send, cookies_to_receive): jar = CookieJar(loop=loop) jar.update_cookies(cookies_to_send) jar_cookies = SimpleCookie() for cookie in jar: dict.__setitem__(jar_cookies, cookie.key, cookie) expected_cookies = cookies_to_send assert jar_cookies == expected_cookies assert jar._loop is loop
def function895(arg1205): var807 = CookieJar(loop=arg1205, unsafe=True) var807.update_cookies( SimpleCookie( 'shared-cookie=first; ip-cookie=second; Domain=127.0.0.1;')) var1203 = var807.filter_cookies( URL('http://127.0.0.1/')).output(header='Cookie:') assert ( var1203 == 'Cookie: ip-cookie=second\r\nCookie: shared-cookie=first')
def test_constructor(loop, cookies_to_send, cookies_to_receive) -> None: jar = CookieJar(loop=loop) jar.update_cookies(cookies_to_send) jar_cookies = SimpleCookie() for cookie in jar: dict.__setitem__(jar_cookies, cookie.key, cookie) expected_cookies = cookies_to_send assert jar_cookies == expected_cookies assert jar._loop is loop
def test_preserving_ip_domain_cookies(loop) -> None: jar = CookieJar(loop=loop, unsafe=True) jar.update_cookies(SimpleCookie( "shared-cookie=first; " "ip-cookie=second; Domain=127.0.0.1;" )) cookies_sent = jar.filter_cookies(URL("http://127.0.0.1/")).output( header='Cookie:') assert cookies_sent == ('Cookie: ip-cookie=second\r\n' 'Cookie: shared-cookie=first')
async def test_constructor_with_expired(loop, cookies_to_send_with_expired, cookies_to_receive) -> None: jar = CookieJar() jar.update_cookies(cookies_to_send_with_expired) jar_cookies = SimpleCookie() for cookie in jar: dict.__setitem__(jar_cookies, cookie.key, cookie) expected_cookies = cookies_to_send_with_expired assert jar_cookies != expected_cookies assert jar._loop is loop
class TestCookieJarBase(unittest.TestCase): def setUp(self): self.loop = asyncio.new_event_loop() asyncio.set_event_loop(None) # N.B. those need to be overriden in child test cases self.jar = CookieJar(loop=self.loop) def tearDown(self): self.loop.close() def request_reply_with_same_url(self, url): self.jar.update_cookies(self.cookies_to_send) cookies_sent = self.jar.filter_cookies(url) self.jar.clear() self.jar.update_cookies(self.cookies_to_receive, url) cookies_received = SimpleCookie() for cookie in self.jar: dict.__setitem__(cookies_received, cookie.key, cookie) self.jar.clear() return cookies_sent, cookies_received
class TestCookieJarBase(unittest.TestCase): def setUp(self): self.loop = asyncio.new_event_loop() asyncio.set_event_loop(None) # N.B. those need to be overridden in child test cases self.jar = CookieJar(loop=self.loop) def tearDown(self): self.loop.close() def request_reply_with_same_url(self, url): self.jar.update_cookies(self.cookies_to_send) cookies_sent = self.jar.filter_cookies(URL(url)) self.jar.clear() self.jar.update_cookies(self.cookies_to_receive, URL(url)) cookies_received = SimpleCookie() for cookie in self.jar: dict.__setitem__(cookies_received, cookie.key, cookie) self.jar.clear() return cookies_sent, cookies_received
def function244(arg1826, function674, function1086): var2077 = (tempfile.mkdtemp() + '/aiohttp.test.cookie') var769 = CookieJar(loop=arg1826) var769.update_cookies(function1086) var769.save(file_path=var2077) var856 = CookieJar(loop=arg1826) var856.load(file_path=var2077) var2054 = SimpleCookie() for var3909 in var856: var2054[var3909.key] = var3909 os.unlink(var2077) assert (var2054 == function1086)
async def test_loose_cookies_types() -> None: jar = CookieJar() accepted_types = [ [('str', BaseCookie())], [('str', Morsel())], [('str', 'str'), ], {'str': BaseCookie()}, {'str': Morsel()}, {'str': 'str'}, SimpleCookie(), ] for loose_cookies_type in accepted_types: jar.update_cookies(cookies=loose_cookies_type)
def test_update_cookie_with_unicode_domain(loop) -> None: cookies = ( "idna-domain-first=first; Domain=xn--9caa.com; Path=/;", "idna-domain-second=second; Domain=xn--9caa.com; Path=/;", ) jar = CookieJar(loop=loop) jar.update_cookies(SimpleCookie(cookies[0]), URL("http://éé.com/")) jar.update_cookies(SimpleCookie(cookies[1]), URL("http://xn--9caa.com/")) jar_test = SimpleCookie() for cookie in jar: jar_test[cookie.key] = cookie assert jar_test == SimpleCookie(" ".join(cookies))
async def test_treat_as_secure_origin() -> None: endpoint = URL("http://127.0.0.1/") jar = CookieJar(unsafe=True, treat_as_secure_origin=[endpoint]) secure_cookie = SimpleCookie( "cookie-key=cookie-value; HttpOnly; Path=/; Secure", ) jar.update_cookies( secure_cookie, endpoint, ) assert len(jar) == 1 filtered_cookies = jar.filter_cookies(request_url=endpoint) assert len(filtered_cookies) == 1
def __init__(self, limoo_url, bot_username, bot_password, secure=True): # Catch a relatively common mistake and report an informative error assert not limoo_url.startswith(('http://', 'https://')), ( 'The URL of the Limoo server should not start with' f' "http://" or "https://". The received URL was "{limoo_url}"') self._credentials = { 'j_username': bot_username, 'j_password': bot_password, } if limoo_url.endswith('/'): limoo_url = limoo_url[:-1] http_url = f'http{"s" if secure else ""}://{limoo_url}' ws_url = f'ws{"s" if secure else ""}://{limoo_url}' self._login_url = f'{http_url}/Limonad/j_spring_security_check' self._api_url_prefix = f'{http_url}/Limonad/api/v1' self._fileop_url = f'{http_url}/fileserver/api/v1/files' self._websocket_url = f'{ws_url}/Limonad/websocket' self._client_session = ClientSession(cookie_jar=CookieJar(unsafe=True)) self._successful_login_count = 0 self._authlock = asyncio.Lock() self._listen_task = None self._event_handler = lambda event: None self.conversations = Conversations(self) self.files = Files(self) self.messages = Messages(self) self.users = Users(self) self.workspaces = Workspaces(self)
async def connect(self): """Connect to the EAP device.""" if self.is_connected: return # By default, forbids cookie from URLs with IP address instead of DNS name jar = CookieJar(unsafe=True) # Need referer to be accepted self.session = ClientSession(cookie_jar=jar, headers={"Referer": self.url}) hashed_password = hashlib.md5(self.password.encode("utf-8")) try: await self.session.get(self.url) await self.session.post( self.url, data={ "username": self.username, "password": hashed_password.hexdigest().upper(), }, ) # Retrieve device info on login await self._async_retrieve_device_info() except ClientError as err: await self.disconnect() raise convert_exception("Could not login on EAP device", err) from err self.is_connected = True
async def init_session(self, session: Optional[ClientSession] = None): """ 初始化 ClientSession, 使用 get/post/head 方法之前需要调用一次, ClientSession 内部维护了连接池, 因此不建议每一个请求创建一个 session, 这里默认为每一个类创建一个 persistent session, 或者手动设置一个, 以实现复用, 在 __init__.py 中初始化 session 会出现 warning, 官方在 aiohttp 4.0 之后将只允许在协程中创建 session, See: https://github.com/aio-libs/aiohttp/issues/3658 https://github.com/aio-libs/aiohttp/issues/4932 :param session: 用于复用的 ClientSession 对象 """ if not self.session: if session: self.session = session return if self._dns_server: logger.debug(f"Use custom DNS Server: {self._dns_server}") resolver = AsyncResolver(nameservers=self._dns_server) con = TCPConnector(ssl=False, ttl_dns_cache=300, resolver=resolver) else: con = TCPConnector(ssl=False, ttl_dns_cache=300) jar = CookieJar(unsafe=True) self.session = ClientSession(connector=con, cookie_jar=jar)
async def get_controller(hass, host, username, password, port, site, verify_ssl): """Create a controller object and verify authentication.""" import aiounifi if verify_ssl: session = aiohttp_client.async_get_clientsession(hass) else: session = aiohttp_client.async_create_clientsession( hass, verify_ssl=verify_ssl, cookie_jar=CookieJar(unsafe=True)) controller = aiounifi.Controller(host, username=username, password=password, port=port, site=site, websession=session) try: with async_timeout.timeout(5): await controller.login() return controller except aiounifi.Unauthorized: LOGGER.warning("Connected to UniFi at %s but not registered.", host) raise AuthenticationRequired except (asyncio.TimeoutError, aiounifi.RequestError): LOGGER.error("Error connecting to the UniFi controller at %s", host) raise CannotConnect except aiounifi.AiounifiException: LOGGER.exception('Unknown UniFi communication error occurred') raise AuthenticationRequired
async def async_step_user( self, user_input: dict[str, Any] | None = None ) -> FlowResult: """Handle the initial step.""" errors: dict[str, str] = {} if user_input is not None: host = user_input[CONF_HOST] if host_valid(host): session = async_create_clientsession( self.hass, cookie_jar=CookieJar(unsafe=True, quote_cookie=False), ) self.client = BraviaTV(host=host, session=session) self.device_config[CONF_HOST] = host return await self.async_step_authorize() errors[CONF_HOST] = "invalid_host" return self.async_show_form( step_id="user", data_schema=vol.Schema({vol.Required(CONF_HOST, default=""): str}), errors=errors, )
async def test_save_load(tmp_path, loop, cookies_to_send, cookies_to_receive) -> None: file_path = pathlib.Path(str(tmp_path)) / "aiohttp.test.cookie" # export cookie jar jar_save = CookieJar() jar_save.update_cookies(cookies_to_receive) jar_save.save(file_path=file_path) jar_load = CookieJar() jar_load.load(file_path=file_path) jar_test = SimpleCookie() for cookie in jar_load: jar_test[cookie.key] = cookie assert jar_test == cookies_to_receive
async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry) -> None: """Set up Aqualink from a config entry.""" username = entry.data[CONF_USERNAME] password = entry.data[CONF_PASSWORD] # These will contain the initialized devices climates = hass.data[DOMAIN][CLIMATE_DOMAIN] = [] lights = hass.data[DOMAIN][LIGHT_DOMAIN] = [] sensors = hass.data[DOMAIN][SENSOR_DOMAIN] = [] switches = hass.data[DOMAIN][SWITCH_DOMAIN] = [] session = async_create_clientsession(hass, cookie_jar=CookieJar(unsafe=True)) aqualink = AqualinkClient(username, password, session) try: await aqualink.login() except AqualinkLoginException as login_exception: _LOGGER.error("Exception raised while attempting to login: %s", login_exception) return False systems = await aqualink.get_systems() systems = list(systems.values()) if not systems: _LOGGER.error("No systems detected or supported") return False # Only supporting the first system for now. devices = await systems[0].get_devices() for dev in devices.values(): if isinstance(dev, AqualinkThermostat): climates += [dev] elif isinstance(dev, AqualinkLight): lights += [dev] elif isinstance(dev, AqualinkSensor): sensors += [dev] elif isinstance(dev, AqualinkToggle): switches += [dev] forward_setup = hass.config_entries.async_forward_entry_setup if climates: _LOGGER.debug("Got %s climates: %s", len(climates), climates) hass.async_create_task(forward_setup(entry, CLIMATE_DOMAIN)) if lights: _LOGGER.debug("Got %s lights: %s", len(lights), lights) hass.async_create_task(forward_setup(entry, LIGHT_DOMAIN)) if sensors: _LOGGER.debug("Got %s sensors: %s", len(sensors), sensors) hass.async_create_task(forward_setup(entry, SENSOR_DOMAIN)) if switches: _LOGGER.debug("Got %s switches: %s", len(switches), switches) hass.async_create_task(forward_setup(entry, SWITCH_DOMAIN)) async def _async_systems_update(now): """Refresh internal state for all systems.""" await systems[0].update() async_dispatcher_send(hass, DOMAIN) async_track_time_interval(hass, _async_systems_update, UPDATE_INTERVAL) return True
def __init__(self, app, loop=None, host='127.0.0.1', protocol=None, ssl=None, scheme=None, **kwargs): if not isinstance(app, Sanic): raise TypeError("app should be a Sanic application.") self._app = app self._loop = loop # we should use '127.0.0.1' in most cases. self._host = host self._ssl = ssl self._scheme = scheme self._protocol = HttpProtocol if protocol is None else protocol self._closed = False self._server = TestServer(self._app, loop=self._loop, protocol=self._protocol, ssl=self._ssl, scheme=self._scheme) cookie_jar = CookieJar(unsafe=True, loop=loop) self._session = ClientSession(loop=loop, cookie_jar=cookie_jar, **kwargs) # Let's collect responses objects and websocket objects, # and clean up when test is done. self._responses = [] self._websockets = []
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Set up the Unifi Protect config entries.""" _async_import_options_from_data_if_missing(hass, entry) session = async_create_clientsession(hass, cookie_jar=CookieJar(unsafe=True)) protectserver = UpvServer( session, entry.data[CONF_HOST], entry.data[CONF_PORT], entry.data[CONF_USERNAME], entry.data[CONF_PASSWORD], ) _LOGGER.debug("Connect to Unfi Protect") protect_data = UnifiProtectData(hass, protectserver, SCAN_INTERVAL) try: nvr_info = await protectserver.server_information() except NotAuthorized: _LOGGER.error( "Could not Authorize against Unifi Protect. Please reinstall the Integration" ) return False except (asyncio.TimeoutError, NvrError, ServerDisconnectedError) as notreadyerror: raise ConfigEntryNotReady from notreadyerror if nvr_info["server_version"] < MIN_REQUIRED_PROTECT_V: _LOGGER.error( "You are running V%s of UniFi Protect. Minimum required version is V%s. Please upgrade UniFi Protect and then retry", nvr_info["server_version"], MIN_REQUIRED_PROTECT_V, ) return False if entry.unique_id is None: hass.config_entries.async_update_entry(entry, unique_id=nvr_info[SERVER_ID]) await protect_data.async_setup() if not protect_data.last_update_success: raise ConfigEntryNotReady hass.data.setdefault(DOMAIN, {})[entry.entry_id] = UnifiProtectEntryData( protect_data=protect_data, upv=protectserver, server_info=nvr_info, disable_stream=entry.options.get(CONF_DISABLE_RTSP, False), doorbell_text=entry.options.get(CONF_DOORBELL_TEXT, None), ) await _async_get_or_create_nvr_device_in_registry(hass, entry, nvr_info) hass.config_entries.async_setup_platforms(entry, PLATFORMS) entry.async_on_unload(entry.add_update_listener(_async_options_updated)) entry.async_on_unload( hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, protect_data.async_stop) ) return True
async def get_controller(hass, host, username, password, port, site, verify_ssl, async_callback=None): """Create a controller object and verify authentication.""" sslcontext = None if verify_ssl: session = aiohttp_client.async_get_clientsession(hass) if isinstance(verify_ssl, str): sslcontext = ssl.create_default_context(cafile=verify_ssl) else: session = aiohttp_client.async_create_clientsession( hass, verify_ssl=verify_ssl, cookie_jar=CookieJar(unsafe=True)) controller = aiounifi.Controller( host, username=username, password=password, port=port, site=site, websession=session, sslcontext=sslcontext, callback=async_callback, ) try: with async_timeout.timeout(10): await controller.check_unifi_os() await controller.login() return controller except aiounifi.Unauthorized as err: LOGGER.warning("Connected to UniFi at %s but not registered: %s", host, err) raise AuthenticationRequired from err except ( asyncio.TimeoutError, aiounifi.BadGateway, aiounifi.ServiceUnavailable, aiounifi.RequestError, ) as err: LOGGER.error("Error connecting to the UniFi controller at %s: %s", host, err) raise CannotConnect from err except aiounifi.LoginRequired as err: LOGGER.warning("Connected to UniFi at %s but login required: %s", host, err) raise AuthenticationRequired from err except aiounifi.AiounifiException as err: LOGGER.exception("Unknown UniFi communication error occurred: %s", err) raise AuthenticationRequired from err
def test_cookie_not_expired_when_added_after_removal(self) -> None: """Test case for https://github.com/aio-libs/aiohttp/issues/2084""" timestamps = [533588.993, 533588.993, 533588.993, 533588.993, 533589.093, 533589.093] loop = mock.Mock() loop.time.side_effect = itertools.chain( timestamps, itertools.cycle([timestamps[-1]])) jar = CookieJar(unsafe=True, loop=loop) # Remove `foo` cookie. jar.update_cookies(SimpleCookie('foo=""; Max-Age=0')) # Set `foo` cookie to `bar`. jar.update_cookies(SimpleCookie('foo="bar"')) # Assert that there is a cookie. assert len(jar) == 1
async def _request(self, method, uri, *args, **kwargs): url = self._server.make_url(uri) cookie_jar = CookieJar(unsafe=True, loop=self._loop) async with ClientSession(loop=asyncio.get_event_loop(), cookie_jar=cookie_jar) as session: response = await session.request(method, url, *args, **kwargs) self._responses.append(response) return response
async def test_loose_cookies_types() -> None: jar = CookieJar() accepted_types = [ [("str", BaseCookie())], [("str", Morsel())], [ ("str", "str"), ], {"str": BaseCookie()}, {"str": Morsel()}, {"str": "str"}, SimpleCookie(), ] for loose_cookies_type in accepted_types: jar.update_cookies(cookies=loose_cookies_type)
def test_save_load(loop, cookies_to_send, cookies_to_receive): file_path = tempfile.mkdtemp() + '/aiohttp.test.cookie' # export cookie jar jar_save = CookieJar(loop=loop) jar_save.update_cookies(cookies_to_receive) jar_save.save(file_path=file_path) jar_load = CookieJar(loop=loop) jar_load.load(file_path=file_path) jar_test = SimpleCookie() for cookie in jar_load: jar_test[cookie.key] = cookie os.unlink(file_path) assert jar_test == cookies_to_receive
def test_save_load(loop, cookies_to_send, cookies_to_receive) -> None: file_path = tempfile.mkdtemp() + '/aiohttp.test.cookie' # export cookie jar jar_save = CookieJar(loop=loop) jar_save.update_cookies(cookies_to_receive) jar_save.save(file_path=file_path) jar_load = CookieJar(loop=loop) jar_load.load(file_path=file_path) jar_test = SimpleCookie() for cookie in jar_load: jar_test[cookie.key] = cookie os.unlink(file_path) assert jar_test == cookies_to_receive
def setUp(self): super().setUp() self.cookies_to_send = SimpleCookie( "shared-cookie=first; " "domain-cookie=second; Domain=example.com; " "subdomain1-cookie=third; Domain=test1.example.com; " "subdomain2-cookie=fourth; Domain=test2.example.com; " "dotted-domain-cookie=fifth; Domain=.example.com; " "different-domain-cookie=sixth; Domain=different.org; " "secure-cookie=seventh; Domain=secure.com; Secure; " "no-path-cookie=eighth; Domain=pathtest.com; " "path1-cookie=nineth; Domain=pathtest.com; Path=/; " "path2-cookie=tenth; Domain=pathtest.com; Path=/one; " "path3-cookie=eleventh; Domain=pathtest.com; Path=/one/two; " "path4-cookie=twelfth; Domain=pathtest.com; Path=/one/two/; " "expires-cookie=thirteenth; Domain=expirestest.com; Path=/;" " Expires=Tue, 1 Jan 1980 12:00:00 GMT; " "max-age-cookie=fourteenth; Domain=maxagetest.com; Path=/;" " Max-Age=60; " "invalid-max-age-cookie=fifteenth; Domain=invalid-values.com; " " Max-Age=string; " "invalid-expires-cookie=sixteenth; Domain=invalid-values.com; " " Expires=string;" ) self.cookies_to_receive = SimpleCookie( "unconstrained-cookie=first; Path=/; " "domain-cookie=second; Domain=example.com; Path=/; " "subdomain1-cookie=third; Domain=test1.example.com; Path=/; " "subdomain2-cookie=fourth; Domain=test2.example.com; Path=/; " "dotted-domain-cookie=fifth; Domain=.example.com; Path=/; " "different-domain-cookie=sixth; Domain=different.org; Path=/; " "no-path-cookie=seventh; Domain=pathtest.com; " "path-cookie=eighth; Domain=pathtest.com; Path=/somepath; " "wrong-path-cookie=nineth; Domain=pathtest.com; Path=somepath;" ) self.jar = CookieJar(loop=self.loop)
def setUp(self): self.loop = asyncio.new_event_loop() asyncio.set_event_loop(None) # N.B. those need to be overridden in child test cases self.jar = CookieJar(loop=self.loop)
class TestCookieJarSafe(TestCookieJarBase): def setUp(self): super().setUp() self.cookies_to_send = SimpleCookie( "shared-cookie=first; " "domain-cookie=second; Domain=example.com; " "subdomain1-cookie=third; Domain=test1.example.com; " "subdomain2-cookie=fourth; Domain=test2.example.com; " "dotted-domain-cookie=fifth; Domain=.example.com; " "different-domain-cookie=sixth; Domain=different.org; " "secure-cookie=seventh; Domain=secure.com; Secure; " "no-path-cookie=eighth; Domain=pathtest.com; " "path1-cookie=nineth; Domain=pathtest.com; Path=/; " "path2-cookie=tenth; Domain=pathtest.com; Path=/one; " "path3-cookie=eleventh; Domain=pathtest.com; Path=/one/two; " "path4-cookie=twelfth; Domain=pathtest.com; Path=/one/two/; " "expires-cookie=thirteenth; Domain=expirestest.com; Path=/;" " Expires=Tue, 1 Jan 1980 12:00:00 GMT; " "max-age-cookie=fourteenth; Domain=maxagetest.com; Path=/;" " Max-Age=60; " "invalid-max-age-cookie=fifteenth; Domain=invalid-values.com; " " Max-Age=string; " "invalid-expires-cookie=sixteenth; Domain=invalid-values.com; " " Expires=string;" ) self.cookies_to_receive = SimpleCookie( "unconstrained-cookie=first; Path=/; " "domain-cookie=second; Domain=example.com; Path=/; " "subdomain1-cookie=third; Domain=test1.example.com; Path=/; " "subdomain2-cookie=fourth; Domain=test2.example.com; Path=/; " "dotted-domain-cookie=fifth; Domain=.example.com; Path=/; " "different-domain-cookie=sixth; Domain=different.org; Path=/; " "no-path-cookie=seventh; Domain=pathtest.com; " "path-cookie=eighth; Domain=pathtest.com; Path=/somepath; " "wrong-path-cookie=nineth; Domain=pathtest.com; Path=somepath;" ) self.jar = CookieJar(loop=self.loop) def timed_request(self, url, update_time, send_time): with mock.patch.object(self.loop, 'time', return_value=update_time): self.jar.update_cookies(self.cookies_to_send) with mock.patch.object(self.loop, 'time', return_value=send_time): cookies_sent = self.jar.filter_cookies(URL(url)) self.jar.clear() return cookies_sent def test_domain_filter_same_host(self) -> None: cookies_sent, cookies_received = ( self.request_reply_with_same_url("http://example.com/")) self.assertEqual(set(cookies_sent.keys()), { "shared-cookie", "domain-cookie", "dotted-domain-cookie" }) self.assertEqual(set(cookies_received.keys()), { "unconstrained-cookie", "domain-cookie", "dotted-domain-cookie" }) def test_domain_filter_same_host_and_subdomain(self) -> None: cookies_sent, cookies_received = ( self.request_reply_with_same_url("http://test1.example.com/")) self.assertEqual(set(cookies_sent.keys()), { "shared-cookie", "domain-cookie", "subdomain1-cookie", "dotted-domain-cookie" }) self.assertEqual(set(cookies_received.keys()), { "unconstrained-cookie", "domain-cookie", "subdomain1-cookie", "dotted-domain-cookie" }) def test_domain_filter_same_host_diff_subdomain(self) -> None: cookies_sent, cookies_received = ( self.request_reply_with_same_url("http://different.example.com/")) self.assertEqual(set(cookies_sent.keys()), { "shared-cookie", "domain-cookie", "dotted-domain-cookie" }) self.assertEqual(set(cookies_received.keys()), { "unconstrained-cookie", "domain-cookie", "dotted-domain-cookie" }) def test_domain_filter_diff_host(self) -> None: cookies_sent, cookies_received = ( self.request_reply_with_same_url("http://different.org/")) self.assertEqual(set(cookies_sent.keys()), { "shared-cookie", "different-domain-cookie" }) self.assertEqual(set(cookies_received.keys()), { "unconstrained-cookie", "different-domain-cookie" }) def test_domain_filter_host_only(self) -> None: self.jar.update_cookies(self.cookies_to_receive, URL("http://example.com/")) cookies_sent = self.jar.filter_cookies(URL("http://example.com/")) self.assertIn("unconstrained-cookie", set(cookies_sent.keys())) cookies_sent = self.jar.filter_cookies(URL("http://different.org/")) self.assertNotIn("unconstrained-cookie", set(cookies_sent.keys())) def test_secure_filter(self) -> None: cookies_sent, _ = ( self.request_reply_with_same_url("http://secure.com/")) self.assertEqual(set(cookies_sent.keys()), { "shared-cookie" }) cookies_sent, _ = ( self.request_reply_with_same_url("https://secure.com/")) self.assertEqual(set(cookies_sent.keys()), { "shared-cookie", "secure-cookie" }) def test_path_filter_root(self) -> None: cookies_sent, _ = ( self.request_reply_with_same_url("http://pathtest.com/")) self.assertEqual(set(cookies_sent.keys()), { "shared-cookie", "no-path-cookie", "path1-cookie" }) def test_path_filter_folder(self) -> None: cookies_sent, _ = ( self.request_reply_with_same_url("http://pathtest.com/one/")) self.assertEqual(set(cookies_sent.keys()), { "shared-cookie", "no-path-cookie", "path1-cookie", "path2-cookie" }) def test_path_filter_file(self) -> None: cookies_sent, _ = self.request_reply_with_same_url( "http://pathtest.com/one/two") self.assertEqual(set(cookies_sent.keys()), { "shared-cookie", "no-path-cookie", "path1-cookie", "path2-cookie", "path3-cookie" }) def test_path_filter_subfolder(self) -> None: cookies_sent, _ = self.request_reply_with_same_url( "http://pathtest.com/one/two/") self.assertEqual(set(cookies_sent.keys()), { "shared-cookie", "no-path-cookie", "path1-cookie", "path2-cookie", "path3-cookie", "path4-cookie" }) def test_path_filter_subsubfolder(self) -> None: cookies_sent, _ = self.request_reply_with_same_url( "http://pathtest.com/one/two/three/") self.assertEqual(set(cookies_sent.keys()), { "shared-cookie", "no-path-cookie", "path1-cookie", "path2-cookie", "path3-cookie", "path4-cookie" }) def test_path_filter_different_folder(self) -> None: cookies_sent, _ = ( self.request_reply_with_same_url("http://pathtest.com/hundred/")) self.assertEqual(set(cookies_sent.keys()), { "shared-cookie", "no-path-cookie", "path1-cookie" }) def test_path_value(self) -> None: _, cookies_received = ( self.request_reply_with_same_url("http://pathtest.com/")) self.assertEqual(set(cookies_received.keys()), { "unconstrained-cookie", "no-path-cookie", "path-cookie", "wrong-path-cookie" }) self.assertEqual(cookies_received["no-path-cookie"]["path"], "/") self.assertEqual(cookies_received["path-cookie"]["path"], "/somepath") self.assertEqual(cookies_received["wrong-path-cookie"]["path"], "/") def test_expires(self) -> None: ts_before = datetime.datetime( 1975, 1, 1, tzinfo=datetime.timezone.utc).timestamp() ts_after = datetime.datetime( 2115, 1, 1, tzinfo=datetime.timezone.utc).timestamp() cookies_sent = self.timed_request( "http://expirestest.com/", ts_before, ts_before) self.assertEqual(set(cookies_sent.keys()), { "shared-cookie", "expires-cookie" }) cookies_sent = self.timed_request( "http://expirestest.com/", ts_before, ts_after) self.assertEqual(set(cookies_sent.keys()), { "shared-cookie" }) def test_max_age(self) -> None: cookies_sent = self.timed_request( "http://maxagetest.com/", 1000, 1000) self.assertEqual(set(cookies_sent.keys()), { "shared-cookie", "max-age-cookie" }) cookies_sent = self.timed_request( "http://maxagetest.com/", 1000, 2000) self.assertEqual(set(cookies_sent.keys()), { "shared-cookie" }) def test_invalid_values(self) -> None: cookies_sent, cookies_received = ( self.request_reply_with_same_url("http://invalid-values.com/")) self.assertEqual(set(cookies_sent.keys()), { "shared-cookie", "invalid-max-age-cookie", "invalid-expires-cookie" }) cookie = cookies_sent["invalid-max-age-cookie"] self.assertEqual(cookie["max-age"], "") cookie = cookies_sent["invalid-expires-cookie"] self.assertEqual(cookie["expires"], "") def test_cookie_not_expired_when_added_after_removal(self) -> None: """Test case for https://github.com/aio-libs/aiohttp/issues/2084""" timestamps = [533588.993, 533588.993, 533588.993, 533588.993, 533589.093, 533589.093] loop = mock.Mock() loop.time.side_effect = itertools.chain( timestamps, itertools.cycle([timestamps[-1]])) jar = CookieJar(unsafe=True, loop=loop) # Remove `foo` cookie. jar.update_cookies(SimpleCookie('foo=""; Max-Age=0')) # Set `foo` cookie to `bar`. jar.update_cookies(SimpleCookie('foo="bar"')) # Assert that there is a cookie. assert len(jar) == 1
def test_domain_filter_ip_cookie_receive(loop, cookies_to_receive) -> None: jar = CookieJar(loop=loop) jar.update_cookies(cookies_to_receive, URL("http://1.2.3.4/")) assert len(jar) == 0
async def test_filter_cookies_str_deprecated(loop) -> None: jar = CookieJar() with pytest.warns(DeprecationWarning): jar.filter_cookies("http://éé.com")
class TestCookieJarSafe(TestCookieJarBase): def setUp(self): super().setUp() self.cookies_to_send = SimpleCookie( "shared-cookie=first; " "domain-cookie=second; Domain=example.com; " "subdomain1-cookie=third; Domain=test1.example.com; " "subdomain2-cookie=fourth; Domain=test2.example.com; " "dotted-domain-cookie=fifth; Domain=.example.com; " "different-domain-cookie=sixth; Domain=different.org; " "secure-cookie=seventh; Domain=secure.com; Secure; " "no-path-cookie=eighth; Domain=pathtest.com; " "path1-cookie=nineth; Domain=pathtest.com; Path=/; " "path2-cookie=tenth; Domain=pathtest.com; Path=/one; " "path3-cookie=eleventh; Domain=pathtest.com; Path=/one/two; " "path4-cookie=twelfth; Domain=pathtest.com; Path=/one/two/; " "expires-cookie=thirteenth; Domain=expirestest.com; Path=/;" " Expires=Tue, 1 Jan 1980 12:00:00 GMT; " "max-age-cookie=fourteenth; Domain=maxagetest.com; Path=/;" " Max-Age=60; " "invalid-max-age-cookie=fifteenth; Domain=invalid-values.com; " " Max-Age=string; " "invalid-expires-cookie=sixteenth; Domain=invalid-values.com; " " Expires=string;" ) self.cookies_to_receive = SimpleCookie( "unconstrained-cookie=first; Path=/; " "domain-cookie=second; Domain=example.com; Path=/; " "subdomain1-cookie=third; Domain=test1.example.com; Path=/; " "subdomain2-cookie=fourth; Domain=test2.example.com; Path=/; " "dotted-domain-cookie=fifth; Domain=.example.com; Path=/; " "different-domain-cookie=sixth; Domain=different.org; Path=/; " "no-path-cookie=seventh; Domain=pathtest.com; " "path-cookie=eighth; Domain=pathtest.com; Path=/somepath; " "wrong-path-cookie=nineth; Domain=pathtest.com; Path=somepath;" ) self.jar = CookieJar(loop=self.loop) def timed_request(self, url, update_time, send_time): with mock.patch.object(self.loop, 'time', return_value=update_time): self.jar.update_cookies(self.cookies_to_send) with mock.patch.object(self.loop, 'time', return_value=send_time): cookies_sent = self.jar.filter_cookies(URL(url)) self.jar.clear() return cookies_sent def test_domain_filter_same_host(self): cookies_sent, cookies_received = ( self.request_reply_with_same_url("http://example.com/")) self.assertEqual(set(cookies_sent.keys()), { "shared-cookie", "domain-cookie", "dotted-domain-cookie" }) self.assertEqual(set(cookies_received.keys()), { "unconstrained-cookie", "domain-cookie", "dotted-domain-cookie" }) def test_domain_filter_same_host_and_subdomain(self): cookies_sent, cookies_received = ( self.request_reply_with_same_url("http://test1.example.com/")) self.assertEqual(set(cookies_sent.keys()), { "shared-cookie", "domain-cookie", "subdomain1-cookie", "dotted-domain-cookie" }) self.assertEqual(set(cookies_received.keys()), { "unconstrained-cookie", "domain-cookie", "subdomain1-cookie", "dotted-domain-cookie" }) def test_domain_filter_same_host_diff_subdomain(self): cookies_sent, cookies_received = ( self.request_reply_with_same_url("http://different.example.com/")) self.assertEqual(set(cookies_sent.keys()), { "shared-cookie", "domain-cookie", "dotted-domain-cookie" }) self.assertEqual(set(cookies_received.keys()), { "unconstrained-cookie", "domain-cookie", "dotted-domain-cookie" }) def test_domain_filter_diff_host(self): cookies_sent, cookies_received = ( self.request_reply_with_same_url("http://different.org/")) self.assertEqual(set(cookies_sent.keys()), { "shared-cookie", "different-domain-cookie" }) self.assertEqual(set(cookies_received.keys()), { "unconstrained-cookie", "different-domain-cookie" }) def test_domain_filter_host_only(self): self.jar.update_cookies(self.cookies_to_receive, URL("http://example.com/")) cookies_sent = self.jar.filter_cookies(URL("http://example.com/")) self.assertIn("unconstrained-cookie", set(cookies_sent.keys())) cookies_sent = self.jar.filter_cookies(URL("http://different.org/")) self.assertNotIn("unconstrained-cookie", set(cookies_sent.keys())) def test_secure_filter(self): cookies_sent, _ = ( self.request_reply_with_same_url("http://secure.com/")) self.assertEqual(set(cookies_sent.keys()), { "shared-cookie" }) cookies_sent, _ = ( self.request_reply_with_same_url("https://secure.com/")) self.assertEqual(set(cookies_sent.keys()), { "shared-cookie", "secure-cookie" }) def test_path_filter_root(self): cookies_sent, _ = ( self.request_reply_with_same_url("http://pathtest.com/")) self.assertEqual(set(cookies_sent.keys()), { "shared-cookie", "no-path-cookie", "path1-cookie" }) def test_path_filter_folder(self): cookies_sent, _ = ( self.request_reply_with_same_url("http://pathtest.com/one/")) self.assertEqual(set(cookies_sent.keys()), { "shared-cookie", "no-path-cookie", "path1-cookie", "path2-cookie" }) def test_path_filter_file(self): cookies_sent, _ = self.request_reply_with_same_url( "http://pathtest.com/one/two") self.assertEqual(set(cookies_sent.keys()), { "shared-cookie", "no-path-cookie", "path1-cookie", "path2-cookie", "path3-cookie" }) def test_path_filter_subfolder(self): cookies_sent, _ = self.request_reply_with_same_url( "http://pathtest.com/one/two/") self.assertEqual(set(cookies_sent.keys()), { "shared-cookie", "no-path-cookie", "path1-cookie", "path2-cookie", "path3-cookie", "path4-cookie" }) def test_path_filter_subsubfolder(self): cookies_sent, _ = self.request_reply_with_same_url( "http://pathtest.com/one/two/three/") self.assertEqual(set(cookies_sent.keys()), { "shared-cookie", "no-path-cookie", "path1-cookie", "path2-cookie", "path3-cookie", "path4-cookie" }) def test_path_filter_different_folder(self): cookies_sent, _ = ( self.request_reply_with_same_url("http://pathtest.com/hundred/")) self.assertEqual(set(cookies_sent.keys()), { "shared-cookie", "no-path-cookie", "path1-cookie" }) def test_path_value(self): _, cookies_received = ( self.request_reply_with_same_url("http://pathtest.com/")) self.assertEqual(set(cookies_received.keys()), { "unconstrained-cookie", "no-path-cookie", "path-cookie", "wrong-path-cookie" }) self.assertEqual(cookies_received["no-path-cookie"]["path"], "/") self.assertEqual(cookies_received["path-cookie"]["path"], "/somepath") self.assertEqual(cookies_received["wrong-path-cookie"]["path"], "/") def test_expires(self): ts_before = datetime.datetime( 1975, 1, 1, tzinfo=datetime.timezone.utc).timestamp() ts_after = datetime.datetime( 2115, 1, 1, tzinfo=datetime.timezone.utc).timestamp() cookies_sent = self.timed_request( "http://expirestest.com/", ts_before, ts_before) self.assertEqual(set(cookies_sent.keys()), { "shared-cookie", "expires-cookie" }) cookies_sent = self.timed_request( "http://expirestest.com/", ts_before, ts_after) self.assertEqual(set(cookies_sent.keys()), { "shared-cookie" }) def test_max_age(self): cookies_sent = self.timed_request( "http://maxagetest.com/", 1000, 1000) self.assertEqual(set(cookies_sent.keys()), { "shared-cookie", "max-age-cookie" }) cookies_sent = self.timed_request( "http://maxagetest.com/", 1000, 2000) self.assertEqual(set(cookies_sent.keys()), { "shared-cookie" }) def test_invalid_values(self): cookies_sent, cookies_received = ( self.request_reply_with_same_url("http://invalid-values.com/")) self.assertEqual(set(cookies_sent.keys()), { "shared-cookie", "invalid-max-age-cookie", "invalid-expires-cookie" }) cookie = cookies_sent["invalid-max-age-cookie"] self.assertEqual(cookie["max-age"], "") cookie = cookies_sent["invalid-expires-cookie"] self.assertEqual(cookie["expires"], "")