aio-libs / aiohttp-cors Goto Github PK
View Code? Open in Web Editor NEWCORS support for aiohttp
License: Apache License 2.0
CORS support for aiohttp
License: Apache License 2.0
aiohttp cors setup breaks with
File "/home/idwaker/Code/webapp/app/api/common/utils/loaders.py", line 43, in init_cors
cors = aiohttp_cors.setup(app, defaults=CORS_DEFAULTS)
File "/home/idwaker/.local/share/virtualenvs/webapp-69lhAx_Z/lib/python3.6/site-packages/aiohttp_cors/__init__.py", line 65, in setup
cors = CorsConfig(app, defaults=defaults)
File "/home/idwaker/.local/share/virtualenvs/webapp-69lhAx_Z/lib/python3.6/site-packages/aiohttp_cors/cors_config.py", line 247, in __init__
self._resources_router_adapter)
File "/home/idwaker/.local/share/virtualenvs/webapp-69lhAx_Z/lib/python3.6/site-packages/aiohttp_cors/cors_config.py", line 117, in __init__
self._app.on_response_prepare.append(self._on_response_prepare)
File "aiohttp/_frozenlist.pyx", line 97, in aiohttp._frozenlist.FrozenList.append
File "aiohttp/_frozenlist.pyx", line 19, in aiohttp._frozenlist.FrozenList._check_frozen
RuntimeError: Cannot modify frozen list.
on latest 3.0 release of aiohttp
my init_cors is something like this
async def init_cors(app: web.Application):
logger = get_logger(app['name'])
cors = aiohttp_cors.setup(app, defaults=CORS_DEFAULTS)
# add resources to cors
for resource in list(app.router.resources()):
if isinstance(resource, web.Resource):
cors.add(resource)
logger.info("Initialized CORS for {}".format(app['name']))
and i am loading init_cors on app.on_startup
The issue seems to occur when i defer cors setup to on_startup signal like
app.on_startup.append(init_cors)
But it works normally if i put the cors init code on app setup like
# register routes here
register_routes(app)
cors = aiohttp_cors.setup(app, defaults=CORS_DEFAULTS)
# add resources to cors
for resource in list(app.router.resources()):
if isinstance(resource, web.Resource):
cors.add(resource)
Hello,
I am trying to work on a project, and I am facing an issue.
The problem is that when I am requesting a resource from the server, google chrome is saying that the "Access-Control-Allow-Origin' header contains multiple values"
This is my code
@asyncio.coroutine
def handler(request):
return web.Response(
text="Hello!",
headers={
"X-Custom-Server-Header": "Custom data",
})
app = web.Application()
cors = aiohttp_cors.setup(app)
resource = cors.add(app.router.add_resource("/"))
route = cors.add(
resource.add_route("POST", handler), {
"*": aiohttp_cors.ResourceOptions(allow_methods="*",
allow_headers=("X-Requested-With", "Content-Type", "AUTHORIZATION"),
expose_headers="*",
allow_credentials=False
)
})
if __name__ == '__main__':
web.run_app(app, port=os.getenv("PORT"), host='0.0.0.0')
i am serving aiohttp over nginx
This code works fine with aiohttp 2.3.10:
def setup_routes(app):
app.router.add_routes(routes)
setup_swagger(app,
api_base_url='/',
swagger_url='/api/doc',
description='API testing interface',
title='API',
api_version='2.0.0')
cors = aiohttp_cors.setup(app, defaults={
"*": aiohttp_cors.ResourceOptions(
allow_credentials=True,
expose_headers="*",
allow_headers="*",
)
})
for route in list(app.router.routes()):
if not isinstance(route.resource, StaticResource): # <<< WORKAROUND
cors.add(route)
curl -H "Origin: http://example.com" -H "Access-Control-Request-Method: POST" -H "Access-Control-Request-Headers: X-Requested-With" -X OPTIONS --verbose localhost:8080/api/users
* Trying ::1...
* TCP_NODELAY set
* connect to ::1 port 8080 failed: Connection refused
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> OPTIONS /api/users HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.58.0
> Accept: */*
> Origin: http://example.com
> Access-Control-Request-Method: POST
> Access-Control-Request-Headers: X-Requested-With
>
< HTTP/1.1 200 OK
< Access-Control-Allow-Origin: http://example.com
< Access-Control-Allow-Credentials: true
< Access-Control-Allow-Methods: POST
< Access-Control-Allow-Headers: X-REQUESTED-WITH
< Content-Length: 0
< Content-Type: application/octet-stream
< Date: Wed, 14 Feb 2018 23:19:55 GMT
< Server: Python/3.6 aiohttp/2.3.10
<
But following (fixed OPTIONS error, adding routes differently) code fails for aiohttp 3.0.1:
# This code fails with:
# RuntimeError: Added route will never be executed, method OPTIONS is already registered
# for route in list(app.router.routes()):
# if not isinstance(route.resource, StaticResource): # <<< WORKAROUND
# cors.add(route)
for resource in app.router.resources():
cors.add(resource)
Same cURL request results in:
* Trying ::1...
* TCP_NODELAY set
* connect to ::1 port 8080 failed: Connection refused
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> OPTIONS /api/users HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.58.0
> Accept: */*
> Origin: http://example.com
> Access-Control-Request-Method: POST
> Access-Control-Request-Headers: X-Requested-With
>
< HTTP/1.1 403 Forbidden
< Content-Type: text/plain; charset=utf-8
< Content-Length: 99
< Date: Wed, 14 Feb 2018 23:21:01 GMT
< Server: Python/3.6 aiohttp/3.0.1
<
* Connection #0 to host localhost left intact
CORS preflight request failed: request method 'POST' is not allowed for 'http://example.com' origin
When aiohttp-cors writes an header like Access-Control-Allow-Origin
, with the Origin
request Header, I think it shoul also emit a Vary: Origin
(because the response vary according to the Origin). What do you think?
I believe it worth to be renamed into abc.py -- nice to have all ABC in the same place, router_adapter.py
is not good name for all possible abcs.
RouterAdapter
should be renamed into AbstractRouterAdapter
or something like this.
We can do renaming without making a harm: the library is very young and most likely users don't use RouterAdapter
and router_adapter.py
explicitly.
Let's make renaming right now, later it will be more painful.
I'll manage it before publishing aiohttp 1.1
Hello. I wish to run tests on Python 3.8, but I needed to fight some problems. This is how I was able to run them on current master:
diff --git a/pytest.ini b/pytest.ini
deleted file mode 100644
index e62899b..0000000
--- a/pytest.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[pytest]
-filterwarnings=
- error
diff --git a/tox.ini b/tox.ini
index 9668d37..bb10832 100644
--- a/tox.ini
+++ b/tox.ini
@@ -5,6 +5,7 @@ envlist = py34, py35, check
commands = {envpython} setup.py test
deps =
pytest
+ pytest-aiohttp
[testenv:check]
deps =
$ tox -e py38
And this is the error I get:
============================= test session starts ==============================
platform linux -- Python 3.8.0, pytest-5.2.2, py-1.8.0, pluggy-0.13.0
cachedir: .tox/py38/.pytest_cache
rootdir: /home/churchyard/Dokumenty/aiohttp-cors, inifile: tox.ini, testpaths: aiohttp_cors, tests
plugins: cov-2.8.1, pylint-0.14.1, aiohttp-0.3.0
collected 99 items
tests/doc/test_basic_usage.py .. [ 2%]
tests/integration/test_main.py ......................................... [ 43%]
............................. [ 72%]
tests/integration/test_real_browser.py ssssss [ 78%]
tests/unit/test___about__.py . [ 79%]
tests/unit/test_cors_config.py ....F... [ 87%]
tests/unit/test_mixin.py ..... [ 92%]
tests/unit/test_preflight_handler.py . [ 93%]
tests/unit/test_resource_options.py ... [ 96%]
tests/unit/test_urldispatcher_router_adapter.py ... [100%]
=================================== FAILURES ===================================
_____________________________ test_static_resource _____________________________
app = <Application 0x7f735d3d6100>
cors = <aiohttp_cors.cors_config.CorsConfig object at 0x7f735d35c400>
def test_static_resource(app, cors):
"""Test adding static resource."""
assert len(app.router.keys()) == 0
app.router.add_static(
"/file", "/", name="dynamic_named_route")
assert len(app.router.keys()) == 1
for resource in list(app.router.resources()):
> if issubclass(resource, web.StaticResource):
tests/unit/test_cors_config.py:106:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
cls = <class 'aiohttp.web_urldispatcher.StaticResource'>
subclass = <StaticResource 'dynamic_named_route' /file -> PosixPath('/')>
def __subclasscheck__(cls, subclass):
"""Override for issubclass(subclass, cls)."""
> return _abc_subclasscheck(cls, subclass)
E TypeError: issubclass() arg 1 must be a class
.tox/py38/lib64/python3.8/abc.py:102: TypeError
=============================== warnings summary ===============================
tests/unit/test_cors_config.py:33
/home/churchyard/Dokumenty/aiohttp-cors/tests/unit/test_cors_config.py:33: DeprecationWarning: "@coroutine" decorator is deprecated since Python 3.8, use "async def" instead
def get(self):
tests/integration/test_main.py::test_dummy_setup[pyloop]
/home/churchyard/Dokumenty/aiohttp-cors/.tox/py38/lib/python3.8/site-packages/aiohttp/web_server.py:53: DeprecationWarning: The loop argument is deprecated since Python 3.8, and scheduled for removal in Python 3.10.
await asyncio.gather(*coros, loop=self._loop)
-- Docs: https://docs.pytest.org/en/latest/warnings.html
============= 1 failed, 92 passed, 6 skipped, 2 warnings in 5.91s ==============
I want to use semantic versioning for versioning aiohttp_cors.
E.g. release not yet stable version as 0.1.0, 0.2.0, ..., and subsequent stable versions as 1.0.0, 2.0.0, ..., according to semantic versioning rules.
Any objections?
/cc @asvetlov
Currently most of information regarding usage of aiohttp_cors is inside README.rst.
It should be splitted/reused for documentation that should go to https://readthedocs.org/.
Hi, i am starting to work with this libs but i cant enable CORS in my test app, here my code: https://gist.github.com/ovnicraft/86a58ff61438ff518415a6208a2efac0
cors vars need something else ?
Header has not any Control-Allow-*
header
i have tried to use allow_headers argument. And it seem that it doesn't work.
'*': aiohttp_cors.ResourceOptions(
expose_headers="*",
allow_headers=("X-Requested-With", "Content-Type"),
)
my options request is:
http OPTIONS http://localhost:9001/api/v1/hello_world Origin:'http://localhost:9001' Access-Control-Request-Method:GET X-Requested-With12:httpie
and response is:
HTTP/1.1 200 OK
Access-Control-Allow-Methods: GET
Access-Control-Allow-Origin: http://localhost:9001
Content-Length: 0
Content-Type: application/octet-stream
Date: Wed, 25 Oct 2017 10:39:40 GMT
Server: Python/3.6 aiohttp/2.2.3
I believe that response should be 403 with not allowed header.
Am i right?
We just encountered a strange CORS bug that that we found a solution to. Our solution is this git commit:
diff --git a/prism_orchestrator_server/router.py b/prism_orchestrator_server/router.py
index 58dfd83..34262f7 100644
--- a/prism_orchestrator_server/router.py
+++ b/prism_orchestrator_server/router.py
@@ -106,6 +106,15 @@ def register_routes(container):
visual_classes = router.add_resource("/visual-classes/")
visual_classes.add_route("GET", resources["visual_classes"].index)
+ visual_class_merge = router.add_resource("/visual-classes/merge")
+ visual_class_merge.add_route("PUT", resources["visual_classes"].merge)
+
+ visual_class_move = router.add_resource("/visual-classes/move")
+ visual_class_move.add_route("PUT", resources["visual_classes"].move)
+
+ visual_class_extract = router.add_resource("/visual-classes/extract")
+ visual_class_extract.add_route("PUT", resources["visual_classes"].extract)
+
visual_class = router.add_resource("/visual-classes/{visual_class_id}")
visual_class.add_route("GET", resources["visual_classes"].get)
@@ -119,15 +128,6 @@ def register_routes(container):
)
visual_class_history.add_route("GET", resources["visual_classes"].get_history)
- visual_class_merge = router.add_resource("/visual-classes/merge")
- visual_class_merge.add_route("PUT", resources["visual_classes"].merge)
-
- visual_class_move = router.add_resource("/visual-classes/move")
- visual_class_move.add_route("PUT", resources["visual_classes"].move)
-
- visual_class_extract = router.add_resource("/visual-classes/extract")
- visual_class_extract.add_route("PUT", resources["visual_classes"].extract)
-
router.add_route("GET", "/instances", redirect_perm("/instances/"))
router.add_route("POST", "/instances", redirect_perm("/instances/"))
instances = router.add_resource("/instances/")
Basically the problem was that /visual-classes/merge
, /visual-classes/move
and /visual-classes/extract
routes were defined after /visual-classes/{visual_class_id}
, and while aiohttp was able to handle this routing order with no problems, it appears that aiohttp-cors cannot.
That is aiohttp-cors fixes the GET
for /visual-classes/{visual_class_id}
and later when I try to enable CORS for /visual-classes/merge
for PUT
, it doesn't work, because it thinks that GET
cors options have already been set for /visual-classes/{visual_class_id}
.
After some debugging. The only solution was to move the more specific routes on top of the generic route. And then CORS worked beautifully.
I think this is a bug in aiohttp-cors, and it's particularly nasty because it's very silent, and when you think aiohttp routing works fine, but cors doesn't, it can be difficult to realize this.
Hello,
if we use init CORS in main app not work in subapp
File aiohttp_cors/mixin.py", line 22, in get_request_config
cors = request.app[APP_CONFIG_KEY]
File aiohttp/web_app.py", line 104, in __getitem__
return self._state[key]
KeyError: 'aiohttp_cors'
fix problem use config_dict https://docs.aiohttp.org/en/stable/web_reference.html#aiohttp.web.Request.config_dict
cors = request.config_dict[APP_CONFIG_KEY]
thanks!
I disable all of them for initial release in tox.ini
Just wanted to know if there is a particular issue why it was restricted to aiohttp <2.0. Was it simply not passing the unittests or someone just needs to thoroughly check unittests and compatibility?
See #43 for reasoning.
@asvetlov thanks for making the change c34202e.
In order to complete renameing we need to:
@asvetlov which parts you want to complete by yourself right now and which part can you want to delegate to me (during this week)?
Currently aiohttp_cors tests fails with master version of aiohttp: https://travis-ci.org/rutsky/aiohttp_cors/jobs/105379563
Currently all public API can be expressed in the following example:
class RouterAdapter(AbstractRouterAdapter):
def route_methods(self, route):
"""Returns list of HTTP methods that route handles"""
def add_options_method_handler(self, route, handler):
"""Add OPTIONS method request handler that will be issued at the same
paths as provided `route`.
:return: Newly added route.
"""
router_adapter = RouterAdapter()
cors = aiohttp_cors.setup(app, router_adapter=router_adapter, ...)
cors.add(route, ...)
Is any of these methods may be required to be coroutines?
E.g. is it reasonable to assume that router.add_route()
will never be coroutine for custom routers?
One of our applications requires CORS headers for static files. I'm currently using the default setup to add all of our APIs as being CORS enabled. The static route is added as add_static
.
Am I missing something?
While using asyncio and aiohttp, I am getting this error on environment: Python 3, mac
Python 3.7.0 (v3.7.0:1bf9cc5093, Jun 26 2018, 23:26:24)
[Clang 6.0 (clang-600.0.57)] on darwin
Traceback (most recent call last):
File "/Applications/PyCharm.app/Contents/helpers/pydev/pydev_run_in_console.py", line 52, in run_file
pydev_imports.execfile(file, globals, locals) # execute the script
File "/Applications/PyCharm.app/Contents/helpers/pydev/_pydev_imps/_pydev_execfile.py", line 18, in execfile
exec(compile(contents+"\n", file, 'exec'), glob, loc)
File "/Users/divyanshushekhar/ScrapeFOLDER/Scraping/scrape-parallel.py", line 173, in <module>
with aiohttp.ClientSession(loop=loop) as session:
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/aiohttp/client.py", line 806, in __enter__
raise TypeError("Use async with instead")
TypeError: Use async with instead
Unclosed client session
client_session: <aiohttp.client.ClientSession object at 0x111337b38>
Searching google gives the result https://stackoverflow.com/questions/46066629/proxy-broker-error-use-async-with-instead which says to install aiohttp version 2.0.0 which I did but got another issue #183
I get a ValueError
when passing a name to router.add_route
cors.add(
app.router.add_route(method, full_url, handler, name=name),
{
'*': aiohttp_cors.ResourceOptions(
allow_credentials=True, expose_headers='*', allow_headers='*'
)
}
)
Traceback:
app = create_app(TestConfig)
api/app.py:27: in create_app
routes.setup(app)
api/routes.py:26: in setup
allow_credentials=True, expose_headers='*', allow_headers='*'
../../../miniconda/envs/rero/lib/python3.5/site-packages/aiohttp_cors/__init__.py:193: in add
route, self._preflight_handler)
../../../miniconda/envs/rero/lib/python3.5/site-packages/aiohttp_cors/urldispatcher_router_adapter.py:45: in add_options_method_handler
self._router.register_route(new_route)
../../../miniconda/envs/rero/lib/python3.5/site-packages/aiohttp/web_urldispatcher.py:459: in register_route
.format(name, self._routes[name]))
E ValueError: Duplicate 'should_i_release', already handled by <DynamicRoute 'should_i_release' [GET] /v1/should_i_release/{username}/{repo}/ -> <function should_i_release at 0x103c85378>
Removing name=name
from the call to app.router.add_route
removes the error.
I've registered my routes that way:
cors = aiohttp_cors.setup(app, defaults={
"*": aiohttp_cors.ResourceOptions(
allow_credentials=True,
expose_headers="*",
allow_headers="*",
allow_methods="*"
)
})
for route in app.router.routes():
cors.add(route)
However, the JS fetch
API raises a CORS exception if I access a unkown URL.
const resp = await fetch('https://myapi.example.com/unknown/url') // raises a TypeError exception
// This code is never reached, but it would if resp had the CORS headers
resp.status === 404
resp.ok === false
What would be the recommended way to add CORS headers to aiohttp
built-in 404 response ?
If method is not allowedCorsViewMixin
raise KeyError
, and client gets 502 Bad Gateway
instead expected 405: Method Not Allowed
.
Source code:
https://github.com/aio-libs/aiohttp-cors/blob/master/aiohttp_cors/mixin.py#L28
Hi,
i installed aiohttp_cors, but i cant import it. when i open the python interactive shell with python3 it works, but when i open it with pyrthon3.7 it does not. in my project i use python3.7, is there any way to make it work?
I'm wondering if there is a way for me to use a regex to allow any localhost ports to be allowed?
Something like:
"http://localhost:[0-9]*": aiohttp_cors.ResourceOptions(
expose_headers="*",
allow_headers="*",
)
Say, I doubt using types in annotations make sense.
They are neither checked in runtime as I see nor pep 484 compatible.
@asvetlov, can you explain why they are not PEP 484 compatible?
E.g. this looks like a proper type annotation:
from aiohttp import web
...
class CorsConfig:
...
def setup(app: web.Application, *, defaults: dict=None) -> CorsConfig:
There should be collections.abc.Mapping
instead of dict
but other parts looks correct to me.
Type annotations yet not used at runtime, but can be used right now for documentation purposes and as hints for IDEs like PyCharm (PyCharm right now has limited support of them).
Do like this:
REPO_NAME={{ YOUR_REPO_NAME }}
travis encrypt -r "aio-libs/${REPO_NAME}" --api-endpoint 'https://api.travis-ci.com/'
Ref: https://github.com/orgs/aio-libs/teams/admins/discussions/9
Can I create views in OOP style? How in tornado or in Django CBV.
Is this module python3.7 ready?
Dependabot couldn't authenticate with https://pypi.python.org/simple/.
You can provide authentication details in your Dependabot dashboard by clicking into the account menu (in the top right) and selecting 'Config variables'.
[E 2016-11-18_11:45:00 server:208]
Traceback (most recent call last):
File "/Users/yihong/virtualenvs/py35/lib/python3.5/site-packages/aiohttp/server.py", line 265, in start
yield from self.handle_request(message, payload)
File "/Users/yihong/virtualenvs/py35/lib/python3.5/site-packages/aiohttp/web.py", line 96, in handle_request
resp = yield from handler(request)
File "/Users/yihong/virtualenvs/py35/lib/python3.5/site-packages/aiohttp_cors/cors_config.py", line 253, in _preflight_handler
request, origin, request_method)
File "/Users/yihong/virtualenvs/py35/lib/python3.5/site-packages/aiohttp_cors/urldispatcher_router_adapter.py", line 400, in get_preflight_request_config
requested_method, path)
TypeError: resolve() takes 2 positional arguments but 3 were given
can somebody update it?
Please never use underscores in python-packages names.
Python packages should also have short, all-lowercase names, although the use of underscores is discouraged.
We have a really problem. When our build system convert all dependencies to RPM (using FPM) yum is broken. We are can't use this package in our projects.
I am using aiohttp and initializing new relic in my __main__
file this way:
import newrelic.agent
if config.NEW_RELIC_SETTED:
newrelic.agent.initialize()
# some initializations ...
web.run_app(app)
Api is the class that I am using aiohttp and initializing my session, web.Application, cors setup and so on
However, when I run my application the following error ocours:
Traceback (most recent call last):
File "/home/gabrielly.silva/sieve/api_portal/app/__main__.py", line 12, in <module>
Api().start()
File "/home/gabrielly.silva/sieve/api_portal/app/api.py", line 41, in __init__
self.register_routes()
File "/home/gabrielly.silva/sieve/api_portal/app/api.py", line 90, in register_routes
self.cors.add(route)
File "/home/gabrielly.silva/sieve/api_portal/.venv/lib/python3.7/site-packages/aiohttp_cors/cors_config.py", line 263, in add
return self._cors_impl.add(routing_entity, config)
File "/home/gabrielly.silva/sieve/api_portal/.venv/lib/python3.7/site-packages/aiohttp_cors/cors_config.py", line 135, in add
routing_entity, self._preflight_handler)
File "/home/gabrielly.silva/sieve/api_portal/.venv/lib/python3.7/site-packages/aiohttp_cors/urldispatcher_router_adapter.py", line 195, in add_preflight_handler
self.add_preflight_handler(route.resource, handler)
File "/home/gabrielly.silva/sieve/api_portal/.venv/lib/python3.7/site-packages/aiohttp_cors/urldispatcher_router_adapter.py", line 165, in add_preflight_handler
if _is_web_view(route_obj):
File "/home/gabrielly.silva/sieve/api_portal/.venv/lib/python3.7/site-packages/aiohttp_cors/urldispatcher_router_adapter.py", line 95, in _is_web_view
if isinstance(handler, type) and issubclass(handler, web.View):
File "/usr/lib/python3.7/abc.py", line 143, in __subclasscheck__
return _abc_subclasscheck(cls, subclass)
TypeError: issubclass() arg 1 must be a class
In the point that the function __is_web_view_
compares if handler is a subclasse of web.View
, the handler is wrapped by new relic
$ type(handler)
<class 'newrelic.common.object_wrapper.FunctionWrapper'>
Is there a way that I can work around and solve this?
Thanks
As we all know, today more than ever before, it is crucial to be able to trust our computing environments. One of the main difficulties that package maintainers of GNU/Linux distributions face, is the difficulty to verify the authenticity and the integrity of the source code. With GPG signatures it is possible for packagers to verify source code releases quickly and easily.
In order to securely package your software I am kindly requesting GPG signatures for the source tarballs. If you are not yet familiar with secure source code signing I recommend using GPGit which automates the process of secure source code signing and also has a quick start guide on GPG for learning how to use it manually.
Thanks in advance.
I have an authentication middleware. In the middleware if the request method is OPTIONS I am returning the handler intact with the aim that aiohttp-cors handle the preflight request and return the correct response headers. However, the response headers are not being sent correctly by the signals.
It is quite possible that I am doing something wrong in my middleware, and the OPTIONS call need to be handled differently. This is my middleware:
@middleware
async def auth_middleware(request, handler):
if isinstance(request.match_info.route, SystemRoute): # eg. 404
return await handler(request)
if request.method == hdrs.METH_OPTIONS:
return await handler(request)
try:
request['claims'] = await authenticate(request)
except ValueError as e:
raise HTTPUnauthorized(PayloadErrors(e.args[0]))
return await handler(request)
I am creating the app as following:
def create_app():
app = Application(middlewares=middlewares)
setup_cors(app)
return app
And this is how I am setting up cors:
def setup_cors(app: Application):
resources = [
'http://localhost:8100',
'http://www.example.com',
]
cors = aiohttp_cors.setup(app, defaults={
resource: aiohttp_cors.ResourceOptions(
allow_credentials=True,
expose_headers='*',
allow_methods='*',
allow_headers='*',
) for resource in resources
})
for route in app.router.routes():
cors.add(route)
However, whenever I make a call I get the following error:
Unhandled exception
Traceback (most recent call last):
File "/python3.7/site-packages/aiohttp/web_protocol.py", line 398, in start
await resp.prepare(request)
File "/python3.7/site-packages/aiohttp/web_response.py", line 299, in prepare
await request._prepare_hook(self)
File "/python3.7/site-packages/aiohttp/web_request.py", line 686, in _prepare_hook
await app.on_response_prepare.send(self, response)
File "/python3.7/site-packages/aiohttp/signals.py", line 35, in send
await receiver(*args, **kwargs)
File "/python3.7/site-packages/aiohttp_cors/cors_config.py", line 171, in _on_response_prepare
assert hdrs.ACCESS_CONTROL_ALLOW_ORIGIN not in response.headers
AssertionError
Unhandled exception
Traceback (most recent call last):
File "/python3.7/site-packages/aiohttp/web_protocol.py", line 398, in start
await resp.prepare(request)
File "/python3.7/site-packages/aiohttp/web_response.py", line 299, in prepare
await request._prepare_hook(self)
File "/python3.7/site-packages/aiohttp/web_request.py", line 686, in _prepare_hook
await app.on_response_prepare.send(self, response)
File "/python3.7/site-packages/aiohttp/signals.py", line 35, in send
await receiver(*args, **kwargs)
File "/python3.7/site-packages/aiohttp_cors/cors_config.py", line 171, in _on_response_prepare
assert hdrs.ACCESS_CONTROL_ALLOW_ORIGIN not in response.headers
AssertionError
While trying to use asyncio and aiohttp , I am getting this error.
Environment: Python 3, Mac
Traceback (most recent call last):
File "/Applications/PyCharm.app/Contents/helpers/pydev/pydev_run_in_console.py", line 52, in run_file
pydev_imports.execfile(file, globals, locals) # execute the script
File "/Applications/PyCharm.app/Contents/helpers/pydev/_pydev_imps/_pydev_execfile.py", line 18, in execfile
exec(compile(contents+"\n", file, 'exec'), glob, loc)
File "/Users/divyanshushekhar/ScrapeAMAZON/Scraping/scrape-consistency.py", line 10, in <module>
import aiohttp
File "/Applications/PyCharm.app/Contents/helpers/pydev/_pydev_bundle/pydev_import_hook.py", line 19, in do_import
module = self._system_import(name, *args, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/aiohttp/__init__.py", line 6, in <module>
from .client import * # noqa
File "/Applications/PyCharm.app/Contents/helpers/pydev/_pydev_bundle/pydev_import_hook.py", line 19, in do_import
module = self._system_import(name, *args, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/aiohttp/client.py", line 15, in <module>
from . import connector as connector_mod
File "/Applications/PyCharm.app/Contents/helpers/pydev/_pydev_bundle/pydev_import_hook.py", line 19, in do_import
module = self._system_import(name, *args, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/aiohttp/connector.py", line 11, in <module>
from . import hdrs, helpers
File "/Applications/PyCharm.app/Contents/helpers/pydev/_pydev_bundle/pydev_import_hook.py", line 19, in do_import
module = self._system_import(name, *args, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/aiohttp/helpers.py", line 29
ensure_future = asyncio.async
^
SyntaxError: invalid syntax
Like aiohttp and others. Current installation techniques don't require nested folders.
I'm developing figma plugin and figma uploads plugins html from local filesystem, in this case, all requests will have 'Origin: null' header and thus Access-Control-Allow-Origin
will have null
, which, in turn, leads to CORS error in browser. I've checked preflight_handler.py source and did not found any way to change usage of existing Origin
header value to externally defined one(*
). Am I missing something?
I'm trying to use aiohttp-cors with aiohttp-graphl, which registers a route with the '*' method. I get
ValueError: <PlainResource 'graphql' /graphql> already has a '*' handler for all methods
Here is a small reproducer showing that '*' is different:
import asyncio
import aiohttp
import aiohttp_cors
from aiohttp.web_runner import GracefulExit
async def handler(request):
return aiohttp.web.Response(text="Hello!")
app = aiohttp.web.Application()
cors = aiohttp_cors.setup(app)
routes = [{
'method': 'GET',
'path': '/test',
'handler': handler,
'name': 'test-good'
}, {
'method': '*', # ValueError: <PlainResource 'another-route' /another-route> already has a '*' handler for all methods
'path': '/another-route',
'handler': handler,
'name': 'another-route'
}, ]
for route in routes:
print('creating a route for method', route['method'])
cors.add(
app.router.add_route(
method=route['method'],
path=route['path'],
handler=route['handler'],
name=route['name']
)
)
web.run_app(app, host='localhost', port=8081)
which prints
creating a route for method GET
creating a route for method *
Traceback (most recent call last):
...
ValueError: <PlainResource 'another-route' /another-route> already has a '*' handler for all methods
Reading the aiohttp-cors code I can see that _is_web_view() is False and then causes this confusing message? But only for method '*' and not GET.
I hacked the aiohttp-cors code to create separate routes for all the methods other than OPTIONS, and my program now runs successfully. But obviously that's not a fix.
Hello!
Cors wont working on Apple devices - cors is not working. It works only if i manually disable CORS Tracking Protection in device settings.
What's wrong with apple?
Aiohttp merges resources, when they are added in the correct order:
When using aiohttp-cors, resources have to be fully merged, or you end up having 2 resources for the same path, one for the GET method one for the POST, but the latter will not be considered when aiohttp-cors answers the OPTIONS request. It seems that aiohttp-cors supports only a single resource per path.
It would be nice if a hint about this could be added to the docs, if the support of multiple resources for the same path is too complex.
Requirements:
aiohttp==3.0.6
aiohttp_cors==0.7.0
Replicate:
def handler():
pass
app.router.add_route('POST', '/a', handler)
app.router.add_route('GET', '/b', handler)
app.router.add_route('PUT', '/a', handler)
# Configure default CORS settings.
cors = aiohttp_cors.setup(app, defaults={
"*": aiohttp_cors.ResourceOptions(
allow_credentials=True,
expose_headers="*",
allow_headers="*")
})
# Configure CORS on all routes.
for route in list(app.router.routes()):
cors.add(route)
raise ValueError("web view should be derived from "
"aiohttp_cors.WebViewMixig for working "
"with the library")
I think that aiohttp_cors.WebViewMixig
should change to aiohttp_cors.CorsViewMixin
. If its ok, ill submit a PR
when router has a static resource in routes... then this code fails:
with:
AttributeError: 'StaticResource' object has no attribute 'add_route'
When using web.View as the handler if the route being added for '*' then cors doesn't work because the server seems not to be able to find the OPTIONS. Not sure why that is, I didn't take the time to investigate but my guess is that the * end up taking priority and the routing goes to the * handler instead of the CORS handler.
=============================== warnings summary ===============================
tests/unit/test_cors_config.py:33
.../tests/unit/test_cors_config.py:33: DeprecationWarning: "@coroutine" decorator is deprecated since Python 3.8, use "async def" instead
def get(self):
tests/integration/test_main.py::test_dummy_setup[pyloop]
/usr/lib64/python3.8/site-packages/aiohttp/web_server.py:53: DeprecationWarning: The loop argument is deprecated since Python 3.8, and scheduled for removal in Python 3.10.
await asyncio.gather(*coros, loop=self._loop)
-- Docs: https://docs.pytest.org/en/latest/warnings.html
==================== 93 passed, 2 warnings in 2.61 seconds =====================
With current default tests config:
============================= test session starts ==============================
platform linux -- Python 3.8.0, pytest-5.2.2, py-1.8.0, pluggy-0.13.0
cachedir: .tox/py38/.pytest_cache
rootdir: /...aiohttp-cors, inifile: pytest.ini
plugins: cov-2.8.1, pylint-0.14.1, aiohttp-0.3.0
collected 91 items / 1 errors / 90 selected
==================================== ERRORS ====================================
_______________ ERROR collecting tests/unit/test_cors_config.py ________________
tests/unit/test_cors_config.py:30: in <module>
class _View(web.View, CorsViewMixin):
tests/unit/test_cors_config.py:33: in _View
def get(self):
/usr/lib64/python3.8/asyncio/coroutines.py:111: in coroutine
warnings.warn('"@coroutine" decorator is deprecated since Python 3.8, use "async def" instead',
E DeprecationWarning: "@coroutine" decorator is deprecated since Python 3.8, use "async def" instead
!!!!!!!!!!!!!!!!!!! Interrupted: 1 errors during collection !!!!!!!!!!!!!!!!!!!!
=============================== 1 error in 0.27s ===============================
look at line 52 of .travis.yml
What is better way to specify this module in requirements? Can it be used with ~=
operator (does it follow Semantic versioning?)
aiohttp-cors~=0.7.0
E.g. using this documentation: http://docs.travis-ci.com/user/gui-and-headless-browsers/
I'm trying to package your module as an rpm package. So I'm using the typical build, install and test cycle used on building packages from non-root account.
May I ask for help because few units are failing:
+ PYTHONPATH=/home/tkloczko/rpmbuild/BUILDROOT/python-aiohttp-cors-0.7.0-15.fc35.x86_64/usr/lib64/python3.8/site-packages:/home/tkloczko/rpmbuild/BUILDROOT/python-aiohttp-cors-0.7.0-15.fc35.x86_64/usr/lib/python3.8/site-packages
+ /usr/bin/pytest -ra --import-mode=importlib
=========================================================================== test session starts ============================================================================
platform linux -- Python 3.8.12, pytest-6.2.5, py-1.10.0, pluggy-0.13.1
benchmark: 3.4.1 (defaults: timer=time.perf_counter disable_gc=False min_rounds=5 min_time=0.000005 max_time=1.0 calibration_precision=10 warmup=False warmup_iterations=100000)
Using --randomly-seed=1568170391
rootdir: /home/tkloczko/rpmbuild/BUILD/aiohttp-cors-0.7.0, configfile: pytest.ini
plugins: forked-1.3.0, shutil-1.7.0, virtualenv-1.7.0, expect-1.1.0, flake8-1.0.7, timeout-1.4.2, betamax-0.8.1, freezegun-0.4.2, aspectlib-1.5.2, toolbox-0.5, rerunfailures-9.1.1, requests-mock-1.9.3, cov-2.12.1, flaky-3.7.0, benchmark-3.4.1, xdist-2.3.0, pylama-7.7.1, datadir-1.3.1, regressions-2.2.0, cases-3.6.3, xprocess-0.18.1, black-0.3.12, anyio-3.3.0, asyncio-0.15.1, subtests-0.5.0, isort-2.0.0, hypothesis-6.14.6, mock-3.6.1, profiling-1.7.0, randomly-3.8.0, Faker-8.12.1, nose2pytest-1.0.8, pyfakefs-4.5.1, tornado-0.8.1, twisted-1.13.3, aiohttp-0.3.0
collected 85 items / 2 errors / 83 selected
================================================================================== ERRORS ==================================================================================
_________________________________________________________ ERROR collecting tests/integration/test_real_browser.py __________________________________________________________
tests/integration/test_real_browser.py:30: in <module>
from selenium import webdriver
/usr/lib/python3.8/site-packages/selenium/webdriver/__init__.py:18: in <module>
from .firefox.webdriver import WebDriver as Firefox # noqa
/usr/lib/python3.8/site-packages/selenium/webdriver/firefox/webdriver.py:28: in <module>
from selenium.webdriver.remote.webdriver import WebDriver as RemoteWebDriver
/usr/lib/python3.8/site-packages/selenium/webdriver/remote/webdriver.py:26: in <module>
from .webelement import WebElement
/usr/lib/python3.8/site-packages/selenium/webdriver/remote/webelement.py:43: in <module>
getAttribute_js = pkgutil.get_data(_pkg, 'getAttribute.js').decode('utf8')
/usr/lib64/python3.8/pkgutil.py:638: in get_data
return loader.get_data(resource_name)
<frozen importlib._bootstrap_external>:1032: in get_data
???
E FileNotFoundError: [Errno 2] No such file or directory: '/usr/lib/python3.8/site-packages/selenium/webdriver/remote/getAttribute.js'
_____________________________________________________________ ERROR collecting tests/unit/test_cors_config.py ______________________________________________________________
tests/unit/test_cors_config.py:30: in <module>
class _View(web.View, CorsViewMixin):
tests/unit/test_cors_config.py:33: in _View
def get(self):
/usr/lib64/python3.8/asyncio/coroutines.py:111: in coroutine
warnings.warn('"@coroutine" decorator is deprecated since Python 3.8, use "async def" instead',
E DeprecationWarning: "@coroutine" decorator is deprecated since Python 3.8, use "async def" instead
========================================================================= short test summary info ==========================================================================
ERROR tests/integration/test_real_browser.py - FileNotFoundError: [Errno 2] No such file or directory: '/usr/lib/python3.8/site-packages/selenium/webdriver/remote/getAtt...
ERROR tests/unit/test_cors_config.py - DeprecationWarning: "@coroutine" decorator is deprecated since Python 3.8, use "async def" instead
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 2 errors during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
============================================================================ 2 errors in 0.64s =============================================================================
pytest-xprocess reminder::Be sure to terminate the started process by running 'pytest --xkill' if you have not explicitly done so in your fixture with 'xprocess.getinfo(<process_name>).terminate()'.
I need to provide CORS permissions for many subdomains (i do not know all), that are located on known list of domains. E.g. *.example.com, *.corp-example.com, etc.
To allow CORS for any origin, i can do the following:
import aiohttp_cors
from aiohttp.web_app import Application
app = Application()
aiohttp_cors.setup(app, defaults={
"*": aiohttp_cors.ResourceOptions(
allow_credentials=True,
expose_headers="*",
allow_headers="*",
)
})
for handler in handlers:
# Register handler
route = app.router.add_route('*', handler.URL_PATH, handler)
# Handler should be handled with CORS
app['aiohttp_cors'].add(route)
It works, but is not secure. What is simplest way to check if client origin meets some requirements (e.g. that origin matches ^[a-z0-9_-]+.example.com$
) and if does not - to deny request?
I supposed that it is possible to extend some basic method to add such checks, or to provide lambda to aiohttp_cors.setup
defaults, that would accept origin as input parameter and return appropriate config.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.