Search code examples
djangocorsdjango-cors-headers

How to fix cors error when loading static file served by Django runserver


Relevant info : Django version 2.2

I have installed django-cors-headers and added it to enabled apps and added the middleware to middleware settings as first middleware.

I have also configured the settings:


INSTALLED_APPS = [
    ...
    "corsheaders",
    "rest_framework",
    "django.contrib.admin",
    ...
]


MIDDLEWARE = [
    ...
    "corsheaders.middleware.CorsMiddleware",
    "django.contrib.sessions.middleware.SessionMiddleware",
    "django.middleware.common.CommonMiddleware",
    ...
]

CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_CREDENTIALS = True

My setup has 2 projects running on different ports. Django server running on 8000 and my front-end running on 8080.

All API requests the front-end sends against back-end work just fine. But when I try to load one.js file served by the back-end project it fails with this error:


Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://127.0.0.1:8000/static/myscript.js. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing)

The way I load the script is by creating a new script element and add the URL http://127.0.0.1:8000/static/myscript.js as value for the src attribute on the script tag.

This error does not occur when I use a value like https://code.jquery.com/jquery-3.5.1.min.js instead of http://127.0.0.1:8000/static/myscript.js so it looks like there is some issue with static files being served by Django runserver, but what exactly and why is beyond me.

I know that there is a bunch of cors related issues like Django CORS on static asset, but they are not about my issue or have gone unanswered. Also, I noticed, that the requests going at static files bypass the cors middleware anyway, so perhaps I should be doing something else here instead?

Perhaps someone can help me out here?

Thanks


Solution

  • A slightly different approach based on Odif Yitsaeb's idea, however you don't need to remove staticfiles or mess with urlpatterns. Simply place the following code into your settings.py:

    from django.contrib.staticfiles import handlers
    
    # extend StaticFilesHandler to add "Access-Control-Allow-Origin" to every response
    class CORSStaticFilesHandler(handlers.StaticFilesHandler):
        def serve(self, request):
            response = super().serve(request)
            response['Access-Control-Allow-Origin'] = '*'
            return response
    
    # monkeypatch handlers to use our class instead of the original StaticFilesHandler
    handlers.StaticFilesHandler = CORSStaticFilesHandler
    

    Notes:

    • Don't use that in production (you shouldn't use devserver in production anyway)
    • The handler must be monkeypatched very early, before any requests are served. Placing the code in settings.py will do the trick