0

This has been plaguing me for quite a while now. I've set up a basic set of apis in Django and am building an angularJS based front end. However for some weird reason the following code results in a CORS error.

    var req = {
  method: 'POST',
  url: url,
  headers: {'Content-Type': 'application/x-www-form-urlencoded'},
  withCredentials: true,
  param: data,
  data: data
}

return $http(req).then(
        function(response){
          callbackSuccess(response);
        },
        function(response){
          callbackError(response);
        }
      );

I found out two things that when I do a post an OPTIONS request is made and secondly none of what I post is even posted. I try to out put the request.POST contents and its empty.

Internal Server Error: /api/users/auth/
Traceback (most recent call last):
  File "/home/ali/eb-virt/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 149, in get_response
    response = self.process_exception_by_middleware(e, request)
  File "/home/ali/eb-virt/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 147, in get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/ali/eb-virt/local/lib/python2.7/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view
    return view_func(*args, **kwargs)
  File "/home/ali/eb-virt/local/lib/python2.7/site-packages/django/utils/decorators.py", line 149, in _wrapped_view
    response = view_func(request, *args, **kwargs)
  File "/home/ali/Projects/api.project.local/project/api/views.py", line 50, in loginUser
    emailAddress = request.POST["emailAddress"]
  File "/home/ali/eb-virt/local/lib/python2.7/site-packages/django/utils/datastructures.py", line 85, in __getitem__
    raise MultiValueDictKeyError(repr(key))
MultiValueDictKeyError: "'emailAddress'"
[21/Nov/2016 07:56:59] "OPTIONS /api/users/auth/ HTTP/1.1" 500 81083

And this is my server code:

def loginUser(request):
  emailAddress = ''
  password = ''
  emailAddress = request.POST["emailAddress"]
  password = request.POST["password"]



  data = auth.login(emailAddress, password)

  return data

I've installed the django-cors-headers and followed all the instructions to the core but its still not working...

Ali
  • 7,353
  • 20
  • 103
  • 161
  • 1
    post your server code. you are accepting `OPTION` method inside view.' – itzMEonTV Nov 21 '16 at 08:29
  • I added the server code - I'm checking for POST - how do I accept OPTION method? doing a pp.pprint of the request.POST outputs an empty dict object – Ali Nov 21 '16 at 08:56
  • 1
    You need to tell your server what requests to accept (POST, GET ...) and also from whom it can accept. Those are 2 headers that you need to set. Did you set them ? –  Nov 21 '16 at 09:01
  • How do I do that - I've made the setting CORS_ALLOW_METHODS in settings to include POST and GET but it seems to be ignored here.. – Ali Nov 21 '16 at 09:04

3 Answers3

2

The problem is in Line :

emailAddress = request.POST["emailAddress"]

In the place of this line,use this code:

def loginUser(request):

  if request.method == 'POST':
    emailAddress = request.POST.get('emailAddress')  
    password = request.POST.get('password') 

    data = auth.login(emailAddress, password)

    return data

request.POST["emailAddress"] will raise a KeyError exception if 'emailAddress' is not in request.POST.

While request.POST.get('emailAddress') will return None if 'emailAddress' is not in request.POST.

Prakhar Trivedi
  • 8,218
  • 3
  • 28
  • 35
  • Thats the problem even if I do this nothing is POSTED even though I'm doing a post request with actual values. The above code sets emailAddress to None. – Ali Nov 21 '16 at 09:03
  • 1
    @Ali Updated my answer.Please check now. – Prakhar Trivedi Nov 21 '16 at 09:04
  • Noted but heres where another problem occurs. from the front end I'm doing a POST request but on the back end its treated as an OPTIONS request so the above updated code is never executed as request.method is equaling OPTIONS for some weird reason. – Ali Nov 21 '16 at 09:05
  • 1
    @Ali You need to make sure that the emailAddress and password fields are getting passed with post request. – Prakhar Trivedi Nov 21 '16 at 09:06
  • 1
    @Ali Did you use csrf token?? – Prakhar Trivedi Nov 21 '16 at 09:06
  • 1
    @Ali This is a new problem.I corrected your earlier code and this is not mentioned anywhere in the original question. – Prakhar Trivedi Nov 21 '16 at 09:09
  • 1
    @Ali try this answer http://stackoverflow.com/questions/20671619/angularjs-options-preflight-call-preceding-a-http-post-request – Prakhar Trivedi Nov 21 '16 at 09:10
  • A csrftoken is passed - I can see it in my firebug console panel. However what beats me is that ist passed as POST but django registers an OPTIONs request and the values passed are all lost :( – Ali Nov 21 '16 at 09:11
  • 1
    Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/128611/discussion-between-prakhar-trivedi-and-ali). – Prakhar Trivedi Nov 21 '16 at 09:15
1

OPTION request is doing by your browser for a safety whether it can send POST request(in case of cross domain). It should return a 200 with some headers(will take care of cors-headers middleware if you added it). So In server, accept POST request this way(assume function based views).

if request.method == 'POST':
    #access POST variables here.
itzMEonTV
  • 19,851
  • 4
  • 39
  • 49
0

Found the issue - was a total noob mistake.

My version of Django in my virtual environment was 1.9 whereas I had generated the project from a version 1.10 so in the settings the MIDDLEWARE option had to be named as MIDDLEWARE_CLASSES - silly mistake had me stuck for two days - thanks everyone for all your answers :)

Ali
  • 7,353
  • 20
  • 103
  • 161