async def test_dummy_setup_roundtrip_resource(aiohttp_client): """Test a dummy configuration with a message round-trip.""" app = web.Application() _setup(app) app.router.add_resource("/").add_route("GET", handler) client = await aiohttp_client(app) resp = await client.get('/') assert resp.status == 200 data = await resp.text() assert data == TEST_BODY
async def test_static_route(aiohttp_client): """Test a static route with CORS.""" app = web.Application() cors = _setup(app, defaults={ "*": ResourceOptions( allow_credentials=True, expose_headers="*", allow_methods="*", allow_headers=("Content-Type", "X-Header"), ) }) test_static_path = pathlib.Path(__file__).parent cors.add(app.router.add_static("/static", test_static_path, name='static')) client = await aiohttp_client(app) resp = await client.options( "/static/test_page.html", headers={ hdrs.ORIGIN: "http://example.org", hdrs.ACCESS_CONTROL_REQUEST_METHOD: "OPTIONS", hdrs.ACCESS_CONTROL_REQUEST_HEADERS: "content-type", } ) data = await resp.text() assert resp.status == 200 assert data == ''
async def test_preflight_request_headers(aiohttp_client): """Test CORS preflight request handlers handling.""" app = web.Application() cors = _setup(app, defaults={ "*": ResourceOptions( allow_credentials=True, expose_headers="*", allow_headers=("Content-Type", "X-Header"), ) }) resource = cors.add(app.router.add_resource("/")) cors.add(resource.add_route("PUT", handler)) client = await aiohttp_client(app) resp = await client.options( '/', headers={ hdrs.ORIGIN: "http://example.org", hdrs.ACCESS_CONTROL_REQUEST_METHOD: "PUT", hdrs.ACCESS_CONTROL_REQUEST_HEADERS: "content-type", } ) assert (await resp.text()) == "" assert resp.status == 200 # Access-Control-Allow-Headers must be compared in case-insensitive # way. assert ( resp.headers[hdrs.ACCESS_CONTROL_ALLOW_HEADERS].upper() == "content-type".upper()) resp = await client.options( '/', headers={ hdrs.ORIGIN: "http://example.org", hdrs.ACCESS_CONTROL_REQUEST_METHOD: "PUT", hdrs.ACCESS_CONTROL_REQUEST_HEADERS: "X-Header,content-type", } ) assert resp.status == 200 # Access-Control-Allow-Headers must be compared in case-insensitive # way. assert ( frozenset(resp.headers[hdrs.ACCESS_CONTROL_ALLOW_HEADERS] .upper().split(",")) == {"X-Header".upper(), "content-type".upper()}) assert (await resp.text()) == "" resp = await client.options( '/', headers={ hdrs.ORIGIN: "http://example.org", hdrs.ACCESS_CONTROL_REQUEST_METHOD: "PUT", hdrs.ACCESS_CONTROL_REQUEST_HEADERS: "content-type,Test", } ) assert resp.status == 403 assert hdrs.ACCESS_CONTROL_ALLOW_HEADERS not in resp.headers assert "headers are not allowed: TEST" in (await resp.text())
async def test_preflight_request_max_age_resource(aiohttp_client): """Test CORS preflight handling on resource that is available through several routes. """ app = web.Application() cors = _setup(app, defaults={ "*": ResourceOptions( allow_credentials=True, expose_headers="*", allow_headers="*", max_age=1200 ) }) resource = cors.add(app.router.add_resource("/{name}")) cors.add(resource.add_route("GET", handler)) client = await aiohttp_client(app) resp = await client.options( "/user", headers={ hdrs.ORIGIN: "http://example.org", hdrs.ACCESS_CONTROL_REQUEST_METHOD: "GET" } ) assert resp.status == 200 assert resp.headers[hdrs.ACCESS_CONTROL_MAX_AGE].upper() == "1200" data = await resp.text() assert data == ""
async def test_preflight_req_multiple_routes_with_one_options(aiohttp_client): """Test CORS preflight handling on resource that is available through several routes. """ app = web.Application() cors = _setup(app, defaults={ "*": ResourceOptions( allow_credentials=True, expose_headers="*", allow_headers="*", ) }) cors.add(app.router.add_route("GET", "/{name}", handler)) cors.add(app.router.add_route("PUT", "/{name}", handler)) client = await aiohttp_client(app) resp = await client.options( "/user", headers={ hdrs.ORIGIN: "http://example.org", hdrs.ACCESS_CONTROL_REQUEST_METHOD: "PUT" } ) assert resp.status == 200 data = await resp.text() assert data == ""
def inner(defaults, route_config): app = web.Application() cors = _setup(app, defaults=defaults) if request.param == 'resource': resource = cors.add(app.router.add_resource("/resource")) cors.add(resource.add_route("GET", handler), route_config) elif request.param == 'view': WebViewHandler.cors_config = route_config cors.add(app.router.add_route("*", "/resource", WebViewHandler)) elif request.param == 'route': cors.add(app.router.add_route("GET", "/resource", handler), route_config) else: raise RuntimeError('unknown parameter {}'.format(request.param)) return app
async def test_preflight_request_mult_routes_with_one_options_webview( aiohttp_client): """Test CORS preflight handling on resource that is available through several routes. """ app = web.Application() cors = _setup(app, defaults={ "*": ResourceOptions( allow_credentials=True, expose_headers="*", allow_headers="*", ) }) class TestView(web.View, CorsViewMixin): async def get(self): resp = web.Response(text=TEST_BODY) resp.headers[SERVER_CUSTOM_HEADER_NAME] = \ SERVER_CUSTOM_HEADER_VALUE return resp put = get cors.add(app.router.add_route("*", "/{name}", TestView)) client = await aiohttp_client(app) resp = await client.options( "/user", headers={ hdrs.ORIGIN: "http://example.org", hdrs.ACCESS_CONTROL_REQUEST_METHOD: "PUT" } ) assert resp.status == 200 data = await resp.text() assert data == ""
async def test_dummy_setup(aiohttp_server): """Test a dummy configuration.""" app = web.Application() _setup(app) await aiohttp_server(app)
async def start_servers(self): test_page_path = pathlib.Path(__file__).with_name("test_page.html") async def handle_test_page(request: web.Request) -> web.StreamResponse: with test_page_path.open("r", encoding="utf-8") as f: return web.Response(text=f.read(), headers={hdrs.CONTENT_TYPE: "text/html"}) async def handle_no_cors(request: web.Request) -> web.StreamResponse: return web.Response( text="""{"type": "no_cors.json"}""", headers={hdrs.CONTENT_TYPE: "application/json"}) async def handle_resource(request: web.Request) -> web.StreamResponse: return web.Response( text="""{"type": "resource"}""", headers={hdrs.CONTENT_TYPE: "application/json"}) async def handle_servers_addresses( request: web.Request) -> web.StreamResponse: servers_addresses = \ {name: descr.url for name, descr in self.servers.items()} return web.Response(text=json.dumps(servers_addresses)) class ResourceView(web.View, CorsViewMixin): async def get(self) -> web.StreamResponse: return await handle_resource(self.request) # For most resources: # "origin" server has no CORS configuration. # "allowing" server explicitly allows CORS requests to "origin" server. # "denying" server explicitly disallows CORS requests to "origin" # server. # "free_for_all" server allows CORS requests for all origins server. # "no_cors" server has no CORS configuration. cors_server_names = ["allowing", "denying", "free_for_all"] server_names = cors_server_names + ["origin", "no_cors"] for server_name in server_names: assert server_name not in self.servers self.servers[server_name] = _ServerDescr() server_sockets = {} # Create applications and sockets. for server_name, server_descr in self.servers.items(): server_descr.app = web.Application() sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.bind(("127.0.0.1", 0)) sock.listen(10) server_sockets[server_name] = sock hostaddr, port = sock.getsockname() server_descr.url = "http://{host}:{port}".format(host=hostaddr, port=port) # Server test page from origin server. self.servers["origin"].app.router.add_route("GET", "/", handle_test_page) self.servers["origin"].app.router.add_route("GET", "/servers_addresses", handle_servers_addresses) # Add routes to all servers. for server_name in server_names: app = self.servers[server_name].app app.router.add_route("GET", "/no_cors.json", handle_no_cors) if self.use_webview: app.router.add_route("*", "/cors_resource", ResourceView, name="cors_resource") else: app.router.add_route("GET", "/cors_resource", handle_resource, name="cors_resource") cors_default_configs = { "allowing": { self.servers["origin"].url: ResourceOptions(allow_credentials=True, expose_headers="*", allow_headers="*") }, "denying": { # Allow requests to other than "origin" server. self.servers["allowing"].url: ResourceOptions(allow_credentials=True, expose_headers="*", allow_headers="*") }, "free_for_all": { "*": ResourceOptions(allow_credentials=True, expose_headers="*", allow_headers="*") }, } # Configure CORS. for server_name, server_descr in self.servers.items(): default_config = cors_default_configs.get(server_name) if default_config is None: continue server_descr.cors = _setup(server_descr.app, defaults=default_config) # Add CORS routes. for server_name in cors_server_names: server_descr = self.servers[server_name] # TODO: Starting from aiohttp 0.21.0 name-based access returns # Resource, not Route. Manually get route while aiohttp_cors # doesn't support configuring for Resources. resource = server_descr.app.router["cors_resource"] route = next(iter(resource)) if self.use_resources: server_descr.cors.add(resource) server_descr.cors.add(route) elif self.use_webview: server_descr.cors.add(route) else: server_descr.cors.add(route) # Start servers. for server_name, server_descr in self.servers.items(): handler = server_descr.app.make_handler() server = await self.loop.create_server( handler, sock=server_sockets[server_name]) server_descr.handler = handler server_descr.server = server self._logger.info("Started server '%s' at '%s'", server_name, server_descr.url)