def _get_origin_if_valid(origin: str, allow_origin: HeaderSet) -> Optional[HeaderSet]: if origin == '': return None elif '*' in allow_origin: return HeaderSet(['*']) elif origin in allow_origin: return HeaderSet([origin]) else: return None
def _get_origin_if_valid(origin: str, allow_origin: HeaderSet) -> Optional[HeaderSet]: if origin == "": return None elif "*" in allow_origin: return HeaderSet(["*"]) elif origin in allow_origin: return HeaderSet([origin]) else: return None
def test_response_access_control() -> None: updated = False def on_update(_: HeaderSet) -> None: nonlocal updated updated = True access_control = ResponseAccessControl.from_headers( 'true', 'Cookie, X-Special', 'GET, POST', '*', 'Set-Cookie', '5', on_update, ) assert access_control.allow_credentials assert access_control.allow_headers == {'Cookie', 'X-Special'} assert access_control.allow_methods == {'GET', 'POST'} assert access_control.allow_origin == {'*'} assert access_control.expose_headers == {'Set-Cookie'} assert access_control.max_age == 5 access_control.allow_methods.add('DELETE') access_control.allow_origin = HeaderSet(['https://quart.com']) assert updated assert access_control.allow_methods == {'GET', 'POST', 'DELETE'} assert access_control.allow_origin == {'https://quart.com'}
def _sanitise_header_set(value: Optional[Iterable[str]], config_key: str) -> HeaderSet: if value is None: value = _get_config_or_default(config_key) elif isinstance(value, str): value = [value] return HeaderSet(value)
def test_header_set() -> None: updated = False def on_update(_: HeaderSet) -> None: nonlocal updated updated = True header_set = HeaderSet.from_header('GET, HEAD', on_update=on_update) assert header_set.to_header() in {'GET, HEAD', 'HEAD, GET'} assert updated is False header_set.add('PUT') assert updated
def test_header_set() -> None: updated = False def on_update(_: HeaderSet) -> None: nonlocal updated updated = True header_set = HeaderSet.from_header("GET, HEAD", on_update=on_update) assert header_set.to_header() in {"GET, HEAD", "HEAD, GET"} assert updated is False header_set.add("PUT") assert updated
def test_response_access_control() -> None: updated = False def on_update(_: HeaderSet) -> None: nonlocal updated updated = True access_control = ResponseAccessControl.from_headers( "true", "Cookie, X-Special", "GET, POST", "*", "Set-Cookie", "5", on_update) assert access_control.allow_credentials assert access_control.allow_headers == {"Cookie", "X-Special"} assert access_control.allow_methods == {"GET", "POST"} assert access_control.allow_origin == {"*"} assert access_control.expose_headers == {"Set-Cookie"} assert access_control.max_age == 5.0 access_control.allow_methods.add("DELETE") access_control.allow_origin = HeaderSet(["https://quart.com"]) assert updated assert access_control.allow_methods == {"GET", "POST", "DELETE"} assert access_control.allow_origin == {"https://quart.com"}
def _apply_cors( access_control: RequestAccessControl, method: str, response: Response, *, allow_credentials: bool, allow_headers: HeaderSet, allow_methods: HeaderSet, allow_origin: HeaderSet, expose_headers: HeaderSet, max_age: Optional[float], ) -> Response: # Logic follows https://www.w3.org/TR/cors/ if "*" in allow_origin and allow_credentials: raise ValueError( "Cannot allow credentials with wildcard allowed origins") if getattr(response, "_QUART_CORS_APPLIED", False): return response origin = _get_origin_if_valid(access_control.origin, allow_origin) if origin is not None: response.access_control.allow_origin = origin response.access_control.allow_credentials = allow_credentials response.access_control.expose_headers = expose_headers if method == "OPTIONS" and (access_control.request_method in allow_methods or "*" in allow_methods): if "*" in allow_headers: response.access_control.allow_headers = access_control.request_headers else: response.access_control.allow_headers = allow_headers.intersection( access_control.request_headers) response.access_control.allow_methods = allow_methods response.access_control.max_age = max_age if "*" not in origin: response.vary.add("Origin") setattr(response, "_QUART_CORS_APPLIED", True) return response