8

I'm using Django as a backend, and have run into cross origin issues which I had fixed using the corsheaders package in settings. So far, all my GET endpoints work, thanks to:

CORS_ORIGIN_ALLOW_ALL = True

However, I'm now trying to access a static file on the django backend, located as such:

http://localhost:8000/static/image.jpg

The browser client however gets the familiar error as before:

Access to XMLHttpRequest at ... from origin ... has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Any ideas? Thanks

user339946
  • 5,961
  • 9
  • 52
  • 97

2 Answers2

5

I'm assuming you're using the built-in staticfiles app to serve your static files in development. When using the runserver managment command along with staticfiles, it uses a WSGI handler to serve static files that bypasses middleware. (Django docs)

The solution is to disable the WSGI handler and instead set up normal Django URL routing to the staticfiles views that do get processed by middleware. You can disable the WSGI handler by running python manage.py runserver --nostatic. When you use --nostatic it will handle static URLs the same as all other URLs, through your Django urlconf, so you'll need to include the staticfiles URLs in your root urlconf like so: (see Static file development view)

if settings.DEBUG:
    from django.contrib.staticfiles.urls import staticfiles_urlpatterns
    urlpatterns += staticfiles_urlpatterns()
sparkyb
  • 371
  • 3
  • 6
  • This does not really answer the question, it is a workaround to avoid facing the problem. I'm experiencing the same problem and this is breaking my code on development. – Martin Massera May 11 '22 at 17:41
  • @MartinMassera This is the correct answer to the question. What different solution would you like? Django is not meant to serve static files. In production you're supposed to use a separate static file server (like Apache or Nginx) to serve static files, which you can separate configure to send CORS headers. Django's development server's ability to serve static files is a development workaround, but it is limited and not configurable and doesn't interact with middleware (nor should it). This change is the proper way to funnel static files through middleware in development. – sparkyb May 11 '22 at 21:36
  • Django includes staticfiles for development, not production, so telling him to not serve staticfiles in development makes no sense, and does not answer the question. The answer should include a way to serve these files in development and fix the CORS problem. As you said, this is not a problem in production. But he is clearly accessing a localhost file so he should be able to fix this in development to continue his development process. – Martin Massera May 11 '22 at 22:37
  • My comment does exactly that. It serves static files in development (when DEBUG is true), it just does it through normal Django request processing which respects the corsheaders middleware instead of at the wsgi layer that bypasses middleware. It uses the same staticfiles module to do it. I really don't understand what is unacceptable about that. It achieves the objective and doesn't have any downsides that I'm aware of. – sparkyb May 12 '22 at 02:06
  • Django's `staticfiles` has a separate, custom runserver so its requests don't follow the same path as normal views, and the `CORS_ORIGIN_ALLOW_ALL` setting does not affect it. So what happens is that in development, normal views will not suffer from CORS but static files will. As you say, in production this is not a problem. – Martin Massera May 12 '22 at 04:29
  • Ups, I think only now I understand you are actually saying that same thing... My bad, I thought you were suggesting to not use staticfiles at all. I now understand your answer. Apologies! – Martin Massera May 12 '22 at 04:35
  • I can't undo my down-vote unless the answer is edited :( if you can edit it, I can undo it – Martin Massera May 12 '22 at 04:41
  • No worries. I see where you were getting confused. I edited the answer to be hopefully be more clear. Thanks for helping me improve it! – sparkyb May 12 '22 at 14:15
  • Thanks for being understanding!! – Martin Massera May 13 '22 at 14:01
2

As explained by the creators of the django-cors-headers in this issue:

I believe the issue here is that staticfiles uses a custom runserver that serves files directly at the WSGI handler layer: https://github.com/django/django/blob/main/django/contrib/staticfiles/management/commands/runserver.py . This is before middleware.

staticfiles requests do not go the same way as Django views, and they are not getting the CORS headers, even if you use a library as django-cors-headers.

Their recommendation is to use whitenoise, but I have not tried it.

Martin Massera
  • 1,718
  • 1
  • 21
  • 47