How to allow CORS from Axios get request in Django backend?

Question:

I’ve been looking for a solution to this problem but nothing seems to work. I’ve arrived at the django-cors-headers package but can’t get it to work.

I’m sending an axios request form my vue frontend:

axios.get('data/')
    .then(res => { console.log(res) })

but it throws a 200 network error error:

Access to XMLHttpRequest at 'http://localhost:8000/data/' from origin 'http://localhost:3000' has been blocked by CORS policy: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
GET http://localhost:8000/data/ net::ERR_FAILED 200
AxiosError {message: 'Network Error', name: 'AxiosError', code: 'ERR_NETWORK', config: {…}, request: XMLHttpRequest, …}
code
: 
"ERR_NETWORK"
config
: 
{transitional: {…}, adapter: Array(2), transformRequest: Array(1), transformResponse: Array(1), timeout: 0, …}
message
: 
"Network Error"
name
: 
"AxiosError"
request
: 
XMLHttpRequest {onreadystatechange: null, readyState: 4, timeout: 0, withCredentials: true, upload: XMLHttpRequestUpload, …}
stack
: 
"AxiosError: Network Errorn

Django backend

I am redirecting the incoming request in myProject/urls.py:

from django.urls import path, include


urlpatterns = [
    path('', include('myApp.urls')),
]

to myApp/urls.py:

from django.urls import path
from . import views


urlpatterns = [
    path('data/', views.getData)
]

which invokes myApp/views.py:

from rest_framework.response import Response
from rest_framework.decorators import api_view
from base.models import Item
from .serializers import ItemSerializer


@api_view(['GET'])
def getData(request):
    items = Item.objects.all()
    serializer = ItemSerializer(items, many=True)
    return Response(serializer.data)

with base/models.py:

from django.db import models


class Item(models.Model):
    name = models.CharField(max_length=200)
    created = models.DateTimeField(auto_now_add=True)

and myApp/serializers.py:

from rest_framework import serializers
from base.models import Item


class ItemSerializer(serializers.ModelSerializer):
    class Meta:
        model = Item
        fields = '__all__'

I’ve installed the django-cors-headers package and configured it in myProject/settings.py:

INSTALLED_APPS = [
    'corsheaders',
    ...
]

MIDDLEWARE = [
    "corsheaders.middleware.CorsMiddleware",
]

with either:

CORS_ALLOWED_ORIGINS = [
    "http://localhost:3000",
]

or

CORS_ALLOW_ALL_ORIGINS = True

but none of both works. I’ve tried reading up on the package docs but can’t find the mistake.

Answers:

it throws a 200 network error error

There’s no such thing as a "200 network error": if you got a 200 status code, there was no problem with the network, since the browser did receive a response from the server. Instead, what happens is that the CORS check failed, for some reason; as a result, the browser denied your client access to the response and raised a CORS error.

Access to XMLHttpRequest at ‘http://localhost:8000/data/’ from origin ‘http://localhost:3000’ has been blocked by CORS policy: The value of the ‘Access-Control-Allow-Origin’ header in the response must not be the wildcard ‘*’ when the request’s credentials mode is ‘include’. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.

If you’re getting such an error message, it’s because

  • your client code is sending a credentialed request, but
  • your server’s CORS configuration doesn’t allow such requests.

Your question doesn’t show it but I suspect you have configured your Axios client to always send requests with credentials. However, setting CORS_ALLOW_ALL_ORIGINS in your CORS config without also setting CORS_ALLOW_CREDENTIALS results in the following response header,

Access-Control-Allow-Origin: *

and the wildcard happens to be incompatible with credentialed requests. If you want to allow credentialed requests, you need to also set the following in your CORS configuration:

CORS_ALLOW_CREDENTIALS = True

Otherwise, instruct your Axios client not to send credentialed requests.

Answered By: jub0bs
Categories: questions Tags: , , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.