Open robd003 opened 5 years ago
Thanks. This requires quite a re-imagination of the way the library works and I'd like to engage in this but don't have time right now. What's your use case, do you have something you can't achieve with CORS_URLS_REGEX
, and how do you imagine the syntax working?
Thanks,
Adam
Coming from the flask world I feel the same. Working with a single regular expression to convey your rules is a bit clunky, I would much rather decorate an endpoint with specific options.
This is the decorator I typically use with flask-cors
: https://flask-cors.readthedocs.io/en/latest/api.html#decorator. It enables setting any of those options per endpoint.
Another vote for this here: I run the Django admin on a domain that also hosts a couple of API endpoints. I want to allow CORS for those endpoints, and I was hoping I could do it with a view decorator rather than having to add a middleware that affects every request to my site.
I'll use CORS_URLS_REGEX
for the moment (somehow I didn't spot that when scanning the README earlier but it turns out it's documented there, I just missed it).
Another request here as well. We run a subdomain and need to adjust some of the cors headers in various ways on the per api basis. Unfortunately these are public apis so can't be moved about now :(
I had to apply CORS to exactly one view and came up with this solution:
class CustomCorsMiddleware(CorsMiddleware):
def process_request(self, request):
response = super().process_request(request)
if response is not None:
# Force process_response to run
return super().process_response(request, response)
else:
return None
@method_decorator(decorator_from_middleware(CustomCorsMiddleware), name='dispatch')
class SomeView(View):
...
This is comparable to how Django does it for the CSRF decorators (https://github.com/django/django/blob/236e6cb5881168a79a194b43c2d8dff7a14c3f03/django/views/decorators/csrf.py#L1)
By adding a init method to the middleware class that takes extra configuration (overrides of defaults/settings) would make this even more flexible (using decorator_from_middleware_with_args
to pass these arguments). This might need some reworking on how the settings wrapper works, but it looks like a feasible solution.
Similarly to @jaap3's solution, but for function based views:
from corsheaders.middleware import CorsMiddleware
from django.utils.decorators import decorator_from_middleware
from django.views.decorators.csrf import csrf_exempt
cors = decorator_from_middleware(middleware_class=CorsMiddleware)
@cors
@csrf_exempt
def some_function(request):
...
It will read settings.py
, so the CORS_*
config values must be set there, but it does not require setting MIDDLEWARE
.
+1 for the decorators. I work on legacy code where the API is scattered across many different url's that don't have any sensible regex pattern. A view decorator would be very useful.
[
decorator_from_middleware
] assumes middleware that’s compatible with the old style of Django 1.9 and earlier [...]
https://docs.djangoproject.com/en/4.2/ref/utils/#django.utils.decorators.decorator_from_middleware
Turns out that PR #852 converted the CorsMiddleware
from "old style" to "new style". This means it is no longer possible to selectively decorate views with CorsMiddleware
using decorator_from_middleware
.
Sadly there seem to be no plans to make decorator_from_middleware
work with new style middleware (https://code.djangoproject.com/ticket/26626). Currently trying to come up with another way to decorate a select set of views.
I was able to get decorator_from_middleware
working again by wrapping the new middleware and implementing process_request
/process_response
:
class CustomCorsMiddleware(CorsMiddleware):
def process_request(self, request):
response = self.check_preflight(request)
if response is not None:
# Add the CORS headers to the preflight response
response = self.process_response(request, response)
return response
def process_response(self, request, response):
return self.add_response_headers(request, response)
Use at your own risk. It basically re-implements the __call__
implementation of the CorsMiddleware
, so if future versions change how that works this wrapper could stop working correctly (or at all).
I've seen in the past people were talking about having support for decorators instead of being stuck with just
CORS_URLS_REGEX
I'd like to re-open the request to support decorators so that it's very easy to limit CORS responses to specific views.