class DeviceView(web.View, CorsViewMixin): cors_config = { "*": ResourceOptions( allow_credentials=True, expose_headers="*", allow_headers="*", ) } async def get(self): device = await Devices.get_device( self.request.app["api"], self.request.app["gateway"], self.request.match_info["id"], ) # print(json.dumps(device)) # return web.json_response(device) return web.json_response(device.description) async def put(self): if self.request.body_exists: try: return web.json_response(await Server_Commands.serverCommand( self.request)) except TypeError: # Can't serialize, bypass for now return web.json_response(None) else: return web.json_response( Server_Commands.return_object(status="Error", result="No PUT-data given")) return web.json_response(Server_Commands.returnObject)
def test_static_route(self): """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')) yield from self.create_server(app) response = yield from self.session.request( "OPTIONS", URL(self.server_url) / "static/test_page.html", headers={ hdrs.ORIGIN: "http://example.org", hdrs.ACCESS_CONTROL_REQUEST_METHOD: "OPTIONS", hdrs.ACCESS_CONTROL_REQUEST_HEADERS: "content-type", }) data = yield from response.text() self.assertEqual(response.status, 200) self.assertEqual(data, '')
class CallsWSView(web.View, CorsViewMixin): cors_config = { "*": ResourceOptions( allow_credentials=True, expose_headers="*", allow_headers="*", ) } async def get(self): ws = web.WebSocketResponse() await ws.prepare(self.request) WSInterface.ws_clients.append(ws) logger.info( f'New WS connection. WS counts: {len(WSInterface.ws_clients)}') async for msg in ws: pass try: WSInterface.ws_clients.remove(ws) except Exception as err: logger.warning('Close error', err=err) return ws
async def test_preflight_default_disallowed_method(aiohttp_client, make_app): app = make_app(None, {"http://client1.example.org": ResourceOptions()}) client = await aiohttp_client(app) resp = await client.options("/resource", headers={ hdrs.ORIGIN: "http://client1.example.org", hdrs.ACCESS_CONTROL_REQUEST_METHOD: "POST", }) assert resp.status == 403 resp_text = await resp.text() assert ("request method 'POST' is not allowed for " "'http://client1.example.org' origin" in resp_text) for header_name in { hdrs.ACCESS_CONTROL_ALLOW_ORIGIN, hdrs.ACCESS_CONTROL_ALLOW_CREDENTIALS, hdrs.ACCESS_CONTROL_MAX_AGE, hdrs.ACCESS_CONTROL_EXPOSE_HEADERS, hdrs.ACCESS_CONTROL_ALLOW_METHODS, hdrs.ACCESS_CONTROL_ALLOW_HEADERS, }: assert header_name not in resp.headers
class AuthN(View, CorsViewMixin): cors_config = { "*": ResourceOptions( allow_credentials=True, allow_headers='*', ) } def set_cookie(self, request: Request, response: Response, userid: str): key = request.app['cookie_key'] value = urlsafe_b64encode(crypt(key, userid)).decode('utf-8') config = request.app['config'] cookie_name: str = config.get('authn.cookie.id_name') cookie_max_age: int = config.get('authn.cookie.max_age') if config.get('authn.cookie.secure'): cookie_secure: Optional[str] = 'yes' else: cookie_secure = None logger.debug('Set cookie %s=%s', cookie_name, value) response.set_cookie(cookie_name, value, max_age=cookie_max_age, secure=cookie_secure, httponly='yes') async def authenticate(self, params: MultiDict): raise NotImplementedError
async def test_preflight_default_origin_and_method(aiohttp_client, make_app): app = make_app(None, {"http://client1.example.org": ResourceOptions()}) client = await aiohttp_client(app) resp = await client.options("/resource", headers={ hdrs.ORIGIN: "http://client1.example.org", hdrs.ACCESS_CONTROL_REQUEST_METHOD: "GET", }) assert resp.status == 200 resp_text = await resp.text() assert '' == resp_text for hdr, val in { hdrs.ACCESS_CONTROL_ALLOW_ORIGIN: "http://client1.example.org", hdrs.ACCESS_CONTROL_ALLOW_METHODS: "GET"}.items(): assert resp.headers.get(hdr) == val for header_name in { hdrs.ACCESS_CONTROL_ALLOW_CREDENTIALS, hdrs.ACCESS_CONTROL_MAX_AGE, hdrs.ACCESS_CONTROL_EXPOSE_HEADERS, hdrs.ACCESS_CONTROL_ALLOW_HEADERS, }: assert header_name not in resp.headers
async def test_simple_expose_headers_allowed_origin(aiohttp_client, make_app): app = make_app( None, { "http://client1.example.org": ResourceOptions(expose_headers=(SERVER_CUSTOM_HEADER_NAME, )) }) client = await aiohttp_client(app) resp = await client.get( "/resource", headers={hdrs.ORIGIN: 'http://client1.example.org'}) assert resp.status == 200 resp_text = await resp.text() assert resp_text == TEST_BODY for hdr, val in { hdrs.ACCESS_CONTROL_ALLOW_ORIGIN: 'http://client1.example.org', hdrs.ACCESS_CONTROL_EXPOSE_HEADERS: SERVER_CUSTOM_HEADER_NAME }.items(): assert resp.headers.get(hdr) == val for header_name in { hdrs.ACCESS_CONTROL_ALLOW_CREDENTIALS, }: assert header_name not in resp.headers
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_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 == ''
class SourcesStatsView(web.View, CorsViewMixin): cors_config = { "*": ResourceOptions( allow_credentials=True, allow_headers="*", expose_headers="*", ) } schema: Type[BaseModel] = SourceSchemaWithStats async def get(self: web.View) -> Response: await check_permission(self.request, Permissions.READ) source_id = int(self.request.match_info["id"]) async with db.transaction(): source = await Source.get(source_id) source_model = self.schema.from_orm(source) source_config = json.loads(source_model.config_json) table_fullname = source_config["table_name"] if not table_fullname: raise web.HTTPConflict( text="table_name not defined in source config") source_executor: AbstractSource = LIVE_SOURCES[source_model.typename] availability_intervals = await source_executor.list_availability_intervals( interval=3600, table_fullname=table_fullname) source_model.available_intervals = [] for res in availability_intervals: source_model.available_intervals.append([res[0], res[1]]) return web.json_response(body=source_model.json())
async def create_app(loop): app = web.Application(loop=loop) job_setup(app) app.on_startup.append(startup) app.on_shutdown.append(shutdown) app.middlewares.extend(middlewares) for route in routes: app.router.add_route(**route) setup_templates(app, loader=jinja2.FileSystemLoader('templates/')) # CORS SETUP cors = setup_cors(app, defaults={ "*": ResourceOptions( allow_credentials=True, expose_headers="*", allow_headers="*", allow_methods='*', ) }) for resource in app.router.resources(): cors.add(resource) return app
class SourcesIntervalView(web.View, CorsViewMixin): cors_config = { "*": ResourceOptions( allow_credentials=True, allow_headers="*", expose_headers="*", ) } schema: Type[BaseModel] = SourceSchemaWithStats async def get(self: web.View) -> Response: await check_permission(self.request, Permissions.READ) source_id = int(self.request.match_info["id"]) async with db.transaction(): source = await Source.get(source_id) source_model = self.schema.from_orm(source) source_config = json.loads(source_model.config_json) table_fullname = source_config["table_name"] if not table_fullname: raise web.HTTPConflict( text="table_name not defined in source config") source_executor: AbstractSource = LIVE_SOURCES[source_model.typename] res = await source_executor.list_data_in_interval( table_fullname=table_fullname, start=self.request.query.get("start"), end=self.request.query.get("end"), ) source_model.data = res return web.json_response(body=source_model.json())
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 == ""
class BaseView(View, CorsViewMixin): """ The base view that all other views extend. Contains some useful helper functions that the extending classes can use. """ url: str name: Optional[str] route: AbstractRoute rental_manager: RentalManager bike_connection_manager: BikeConnectionManager reservation_manager: ReservationManager reservation_sourcer: ReservationSourcer statistics_reporter: StatisticsReporter payment_manager: PaymentManager cors_config = { "*": ResourceOptions( allow_credentials=True, expose_headers="*", allow_headers="*", allow_methods="*", ) } @classmethod def register_route(cls, app: Application, base: Optional[str] = None): """ Registers the view with the given router. :raises ViewConfigurationError: If the URL hasn't been set on the given view. """ try: url = base + cls.url if base is not None else cls.url except AttributeError: raise ViewConfigurationError("No URL provided!") kwargs = {} name = getattr(cls, "name", None) if name is not None: kwargs["name"] = name cls.route = app.router.add_view(url, cls, **kwargs) cls.rental_manager = app["rental_manager"] cls.bike_connection_manager = app["bike_location_manager"] cls.reservation_manager = app["reservation_manager"] cls.reservation_sourcer = app["reservation_sourcer"] cls.statistics_reporter = app["statistics_reporter"] cls.payment_manager = app["payment_manager"] @classmethod def enable_cors(cls, cors: CorsConfig): """Enables CORS on the view.""" try: cors.add(cls.route, webview=True) except AttributeError as error: raise ViewConfigurationError( "No route assigned. Please register the route first." ) from error
def test_preflight_request_multiple_routes_with_one_options_resource(self): """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="*", ) }) resource = cors.add(app.router.add_resource("/{name}")) cors.add(resource.add_route("GET", handler)) cors.add(resource.add_route("PUT", handler)) yield from self.create_server(app) response = yield from self.session.request( "OPTIONS", self.server_url + "user", headers={ hdrs.ORIGIN: "http://example.org", hdrs.ACCESS_CONTROL_REQUEST_METHOD: "PUT" }) self.assertEqual(response.status, 200) data = yield from response.text() self.assertEqual(data, "")
async def test_method_not_allowed(aiohttp_client, make_app): app = make_app(None, {"http://client1.example.org": ResourceOptions()}) client = await aiohttp_client(app) resp = await client.post("/resource") assert resp.status == 405
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 == ""
def test_simple_expose_headers(self): """Test CORS simple requests with a route that exposes header.""" client1 = "http://client1.example.org" client2 = "http://client2.example.org" tests_descriptions = [ { "name": "default", "defaults": None, "route_config": { client1: ResourceOptions( expose_headers=(SERVER_CUSTOM_HEADER_NAME, )), }, "tests": [ { "name": "no origin header", "not_in_response_headers": { hdrs.ACCESS_CONTROL_ALLOW_ORIGIN, hdrs.ACCESS_CONTROL_EXPOSE_HEADERS, hdrs.ACCESS_CONTROL_ALLOW_CREDENTIALS, } }, { "name": "allowed origin", "request_headers": { hdrs.ORIGIN: client1, }, "in_response_headers": { hdrs.ACCESS_CONTROL_ALLOW_ORIGIN: client1, hdrs.ACCESS_CONTROL_EXPOSE_HEADERS: SERVER_CUSTOM_HEADER_NAME, }, "not_in_response_headers": { hdrs.ACCESS_CONTROL_ALLOW_CREDENTIALS, } }, { "name": "not allowed origin", "request_headers": { hdrs.ORIGIN: client2, }, "not_in_response_headers": { hdrs.ACCESS_CONTROL_ALLOW_ORIGIN, hdrs.ACCESS_CONTROL_EXPOSE_HEADERS, hdrs.ACCESS_CONTROL_ALLOW_CREDENTIALS, } }, ], }, ] yield from self._run_simple_requests_tests(tests_descriptions, False) yield from self._run_simple_requests_tests(tests_descriptions, True) yield from self._run_simple_requests_tests(tests_descriptions, True)
class UserInfoHandler(OAuth2Handler, CorsViewMixin): __get_stream__ = get_user_info_stream __request_class__ = UserInfoRequest @custom_cors( {'*': ResourceOptions(allow_credentials=True, allow_headers='*')}) async def get(self): return await super().get()
def setUp(self): self.loop = asyncio.new_event_loop() self.app = web.Application(loop=self.loop) self.cors = CorsConfig(self.app, defaults={"*": ResourceOptions()}) self.get_route = self.app.router.add_route("GET", "/get_path", _handler) self.options_route = self.app.router.add_route("OPTIONS", "/options_path", _handler)
def init_cors(app): return setup_cors(app, defaults={ "*": ResourceOptions( allow_credentials=True, expose_headers="*", allow_headers="*", ) })
def setup_cors(app): cors = setup(app, defaults={ "*": ResourceOptions( allow_credentials=True, allow_methods=["GET", "Post", "PUT", "DELETE"], expose_headers="*", allow_headers="*", ) }) for route in list(app.router.routes()): cors.add(route)
def setUp(self): self.loop = asyncio.new_event_loop() self.app = web.Application(loop=self.loop) self.adapter = ResourcesUrlDispatcherRouterAdapter( self.app.router, defaults={"*": ResourceOptions()}) self.get_route = self.app.router.add_route("GET", "/get_path", _handler) self.options_route = self.app.router.add_route("OPTIONS", "/options_path", _handler)
def _enable_cors(self): app = self.api._api._app cors = cors_setup(app, defaults={ "*": ResourceOptions( allow_credentials=True, expose_headers="*", allow_headers="*", ) }) for route in self.api._api.router.routes(): cors.add(route)
async def _setup_cors(self, resource: Resource): """ Настройка CORS @param resource: сущность в таблице роута """ cors = setup(self._app, defaults={ '*': ResourceOptions(allow_credentials=True, expose_headers='*', allow_headers='*', allow_methods='*') }) cors.add(resource)
def __init__(self, port, logs=None): # Build Web App self.port = port self.logs = logs self.webapp = web.Application(middlewares=[ # Just in case someone wants to use it behind a reverse proxy # Not sure why someone will want to do that though XForwardedRelaxed().middleware, # Handle unexpected and HTTP exceptions self._middleware_exceptions, # Handle media type validation self._middleware_media_type, # Handle schema validation self._middleware_schema, ]) self.webapp.router.add_get('/api/logs', self.api_logs) self.webapp.router.add_post('/api/config', self.api_config) self.webapp.router.add_post('/api/push', self.api_push) self.webapp.router.add_post('/api/message', self.api_message) # Enable CORS in case someone wants to build a web agent self.cors = CorsConfig( self.webapp, defaults={ '*': ResourceOptions( allow_credentials=True, expose_headers='*', allow_headers='*', ) } ) for route in self.webapp.router.routes(): self.cors.add(route) # Create task for the push hearbeat event_loop = get_event_loop() self.timestamp = None self.heartbeat = event_loop.create_task(self._check_last_timestamp()) # Build Terminal UI App self.ui = UIManager() self.tuiapp = MainLoop( self.ui.topmost, pop_ups=True, palette=self.ui.palette, event_loop=AsyncioEventLoop(loop=event_loop), )
async def test_simple_no_origin(aiohttp_client, make_app): app = make_app(None, {"http://client1.example.org": ResourceOptions()}) client = await aiohttp_client(app) resp = await client.get("/resource") assert resp.status == 200 resp_text = await resp.text() assert resp_text == TEST_BODY for header_name in { hdrs.ACCESS_CONTROL_ALLOW_ORIGIN, hdrs.ACCESS_CONTROL_EXPOSE_HEADERS, hdrs.ACCESS_CONTROL_ALLOW_CREDENTIALS, }: assert header_name not in resp.headers
def map_routes(app): cors = setup(app, defaults={ '*': ResourceOptions( allow_credentials=True, expose_headers='*', allow_headers='*', ) }) user_controller = UserController() news_feed_controller = NewsFeedController() resource = app.router.add_resource('/login', name='login') resource.add_route('POST', user_controller.login) resource = app.router.add_resource('/logout', name='logout') resource.add_route('GET', user_controller.logout) resource = app.router.add_resource('/register', name='register') resource.add_route('POST', user_controller.register) resource = app.router.add_resource('/user_data', name='user_data') resource.add_route('GET', user_controller.get_user_data) resource = app.router.add_resource('/all_users', name='all_users') resource.add_route('GET', user_controller.get_all_users) resource = app.router.add_resource('/friend', name='friend') resource.add_route('GET', user_controller.get_friend) resource.add_route('POST', user_controller.make_friend) resource = app.router.add_resource('/feed', name='news_feed') resource.add_route('GET', news_feed_controller.get) resource.add_route('POST', news_feed_controller.create) resource.add_route('PATCH', news_feed_controller.update) resource.add_route('DELETE', news_feed_controller.delete) resource = app.router.add_resource('/interact', name='interact') resource.add_route('POST', news_feed_controller.interact) for route in app.router.routes(): cors.add(route)
class SourcesView(web.View, CorsViewMixin): cors_config = { "*": ResourceOptions( allow_credentials=True, allow_headers="*", expose_headers="*", ) } schema: Type[BaseModel] = SourceSchema async def get(self: web.View) -> Response: await check_permission(self.request, Permissions.READ) response = [] async with db.transaction(): async for s in Source.query.order_by(Source.id).gino.iterate(): validated = self.schema.from_orm(s) response.append(validated.dict()) return web.json_response(response) async def post(self: web.View) -> Response: await check_permission(self.request, Permissions.WRITE_OBJECTS) response = [] try: raw_data = await self.request.json() incoming = self.schema(**raw_data) async with db.transaction(): await Source.create(**incoming.private_dict()) async for s in Source.query.order_by(Source.id).gino.iterate(): response.append(self.schema.from_orm(s).dict()) except Exception: raise web.HTTPBadRequest return web.json_response(response) async def delete(self: web.View) -> Response: await check_permission(self.request, Permissions.WRITE_OBJECTS) raw_data = await self.request.json() incoming = self.schema(**raw_data) response = [] async with db.transaction(): await Source.delete.where(Source.id == incoming.id).gino.status() async for s in Source.query.order_by(Source.id).gino.iterate(): validated = self.schema.from_orm(s) response.append(validated.dict()) return web.json_response(response)
async def test_preflight_default_no_origin(aiohttp_client, make_app): app = make_app(None, {"http://client1.example.org": ResourceOptions()}) client = await aiohttp_client(app) resp = await client.options("/resource") assert resp.status == 403 resp_text = await resp.text() assert "origin header is not specified" in resp_text for header_name in { hdrs.ACCESS_CONTROL_ALLOW_ORIGIN, hdrs.ACCESS_CONTROL_ALLOW_CREDENTIALS, hdrs.ACCESS_CONTROL_MAX_AGE, hdrs.ACCESS_CONTROL_EXPOSE_HEADERS, hdrs.ACCESS_CONTROL_ALLOW_METHODS, hdrs.ACCESS_CONTROL_ALLOW_HEADERS, }: assert header_name not in resp.headers