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
Example #2
0
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
Example #3
0
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)
Example #5
0
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
Example #6
0
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
Example #7
0
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"}
Example #8
0
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