1

I have a react frontend running on localhost port 8080 and a django backend on port 8000. I build an API that I call through javascript fetch requests. The django backend has cors-headers installed and set to CORS_ORIGIN_ALLOW_ALL=True. The fetch does work for all endpoints in the API, except a new endpoint called metrics I just added. Once I call this view on a GET request I recieve the following error:

Access to fetch at 'http://localhost:8000/api/v1/metrics/' from origin 'http://localhost:8080' has been blocked by CORS policy: Request header field authorization is not allowed by Access-Control-Allow-Headers in preflight response.

I use the same fetch method to call all API endpoints:

return fetch(url, {
    method: 'GET',
    mode: 'cors',
    cache: 'no-cache',
    credentials: 'same-origin',
    headers: {
      'Authorization': 'Token ' + token
    },
    redirect: 'follow',
    referrer: 'no-referrer',
  })

Also the call does work through postman, however not from the React-App. I suppose the error is originated in the preflight OPTIONS response the django server gives, however I fail to see how the response is different from other endpoints. The definition of the view is:

class ListMetrics(generics.ListCreateAPIView):
  '''Lists and creates new Metrics.'''
  queryset = models.Metric.objects.all()
  serializer_class = serializers.MetricSerializer

(Authorization is enabled in the django settings by default and does work with the same token for all other endpoints).

Update

Adding the authorization header explicitly in the django config does yield the same error:

CORS_ALLOW_HEADERS = (
    'accept',
    'accept-encoding',
    'authorization',
    'content-type',
    'dnt',
    'origin',
    'user-agent',
    'x-csrftoken',
    'x-requested-with',
)

Update 2

Here are urls.py and views.py for completeness:

urls.py from the Django App (only relevant parts):

urlpatterns = [
  # tags endpoint
  path("tags/", views.ListTags.as_view(), name="list-user-tags"),

  # ... some other endpoints  

  # metrics endpoint
  path("metrics/", views.ListMetrics.as_view(), name="list-global-metrics"),

  # ... some authentication endpoints
]

Views for the two endpoints described above:

class ListTags(generics.ListCreateAPIView):
  queryset = models.Tag.objects.all()
  serializer_class = serializers.TagSerializer

  def get_queryset(self):
    return perm.filterModelCreator(models.Tag, self.request.user)

class ListMetrics(generics.ListCreateAPIView):
  '''Lists and creates new Metrics.'''
  queryset = models.Metric.objects.all()
  serializer_class = serializers.MetricSerializer

The tags view has a get_queryset function to filter only tags created by the user.

Uodate 3

Sending the same request through jquery ajax instead of fetch leads to the same error:

Access to XMLHttpRequest at 'http://localhost:8000/api/v1/metrics/?_=1565265240772' from origin 'http://localhost:8080' has been blocked by CORS policy: Request header field authorization is not allowed by Access-Control-Allow-Headers in preflight response.

Thank you!

  • have you added the corsheaders in INSTALLED_APPS ? –  Aug 08 '19 at 11:14
  • Yes. I do have `corsheaders` in installedApps and added the middleware. Strange thing is, the cors actually works for every other view I have. Just not for this one. However I do not see any difference to the other views. – Felix Geilert Aug 08 '19 at 11:16
  • I couldn't find what your exact issue is, but could you please try with setting `CORS_ORIGIN_ALLOW_ALL = True` in the settings.py –  Aug 08 '19 at 11:18
  • Already have that setting – Felix Geilert Aug 08 '19 at 11:19
  • OK, let me check once again, and will update soon –  Aug 08 '19 at 11:20
  • Issue is: I have a react app, trying to fetch from the api using a GET request, as described above. However for this one particular dajngo view `/metrics/` the request (or more specific the CORS preflight request) fails, while the same fetch structure (i.e. same headers, etc) work for every other django view in the same App. – Felix Geilert Aug 08 '19 at 11:20
  • Please post urls.py and views.py – somsgod Aug 08 '19 at 11:22
  • Okay, I need to see the processing (views.py) and also could you please check the GET request with a CURL command and tell me the response? –  Aug 08 '19 at 11:25
  • @somsgod I did an update above – Felix Geilert Aug 08 '19 at 11:26
  • @Sreenath: I used the following curl command: `curl -X GET http://localhost:8000/api/v1/metrics/ -H 'Accept: */*' -H 'Authorization: Token b05b128b737ee499e8cac733e2ba21197b1557ac' -H 'Cache-Control: no-cache' -H 'Host: localhost:8000' ` and retrieved the correct json response: `[{"id":9,"name":"Task Metric", ...}, ...]`. – Felix Geilert Aug 08 '19 at 11:30
  • Try running app on some different port and then check if that might help. – somsgod Aug 08 '19 at 11:31
  • Notably, I also test the requests through postman, which works with no problem. It only appears to be a problem running from the React App in Browser and only for this specific view. I also assume that curl does not send the CORS preflight Request? – Felix Geilert Aug 08 '19 at 11:31
  • @somsgod Different port did not solve the problem – Felix Geilert Aug 08 '19 at 11:33
  • okay cool. so the issue is with the way you make the request from the front end Could you please try ajax request? https://stackoverflow.com/questions/29990809/handling-ajax-with-react –  Aug 08 '19 at 11:34
  • Tested the ajax request, still fails. Provides error: 'Unexpected end of json input` I assume that happens if he tries to decode the actual error message. – Felix Geilert Aug 08 '19 at 11:42
  • Another solution for this case is, check your server logs and find the API request log. Once you set `CORS_ALLOW_HEADERS` it allows those headers in the list to your API, which means if you have a custom header along with the default headers, it will not be accepted. So find the Log and find the Header part of the request and add the custom header part to your code. You can refer this link to check how to allow custom headers https://pypi.org/project/django-cors-headers/ –  Aug 08 '19 at 11:43
  • As mentioned in the question, already tried to add `CORS_ALLOW_HEADERS`, sadly it did not help. Also I use a function that creates the same fetch command (with the same headers) for every request. I do not see, how this call would have headers that are not present in calls to other views? – Felix Geilert Aug 08 '19 at 11:47
  • 'Unexpected end of json input' is an error from the React End, I guess if so, the request is not done. there is some syntax issue in the front end fix it and make the AJAX request properly –  Aug 08 '19 at 11:47
  • You can print a request header in the back end like this https://stackoverflow.com/questions/20658572/python-requests-print-entire-http-request-raw –  Aug 08 '19 at 11:51
  • Adjusted Ajax command delivers the same problem: `Access to XMLHttpRequest at 'http://localhost:8000/api/v1/metrics/?_=1565265240772' from origin 'http://localhost:8080' has been blocked by CORS policy: Request header field authorization is not allowed by Access-Control-Allow-Headers in preflight response` – Felix Geilert Aug 08 '19 at 11:55
  • @Sreenath I do not see any incoming requests on the view in django, does react stop requests before even sending? – Felix Geilert Aug 08 '19 at 12:06

1 Answers1

0

Okay, I isolated the problem. It appears that the integrated adblock of the browser blocked the CORS request. However, I don't know why this only happened to this one request...

Anyway, if I disable the protection features for the site the request works as it should.