gornvix
gornvix

Reputation: 3384

Beginning client development for a Django REST API based system (CORS error)?

I have developed some API functions in Django REST framework, and now I want to develop some client forms / API calls to match. OK, the REST API is available at locally after entering the command:

python3 manage.py runserver

I put together some HTML and JavaScript / jquery.rest, so the client can call a (authorization) end point with the following function linked to an onclick event:

function auth()
{
  var client = new $.RestClient('http://127.0.0.1:8000/auth/');
  client.add('token');

  var client_id = 'xxx...etc';
  var client_secret = 'yyy...etc';
  var username = $('.inputUsername').val();
  var password = $('.inputPassword').val();

  request = client.token.create({
    client_id: client_id,
    client_secret: client_secret,
    grant_type: 'password',
    username: username,
    password: password
  });

  request.done(function (data, textStatus, xhrObject){
    alert('I have data: ' + data);
  });
  return false;
}

Firstly, perhaps naively, I opened the HTML file in a browser, to test out this client function, but Django refused the request with the error:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://127.0.0.1:8000/auth/token/. (Reason: CORS header 'Access-Control-Allow-Origin' missing).

Then I thought that if I served up the page locally using Apache (with the Django server still in development mode) then the origins would at least be the same, but that gave the same error. I'm guessing that this is because of the different ports. I'm aware that it is possible to set Django so that other origins are allowed, however I'm confused as to how this would work if the client was a web based phone app for example. Wouldn't it be best if the pages were stored locally on the phone (perhaps encrypted), rather than at a different domain or would that be insecure? What is the common solution to this problem?

(Update) I installed the middleware with:

pip install django-cors-headers

...and edited settings.py:

INSTALLED_APPS = (
    ...
    'corsheaders',
    ...
)

MIDDLEWARE_CLASSES = (
    ...
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
    ...
)

CORS_ORIGIN_WHITELIST = (
    'localhost',
)

Nothing appears in the console now, but Django REST framework still refuses the request:

[07/Mar/2016 23:07:00] "POST /auth/token/ HTTP/1.1" 401 27

Upvotes: 1

Views: 1446

Answers (1)

ilse2005
ilse2005

Reputation: 11439

I think the usual way is that your backend (api) will run on a separate server than your frontend and you make CORSCORS requests. Therfore you have to set the CORS-Header correctly. This is quite simple using django-cors-headers.

#settings.py
INSTALLED_APPS = (
    ...
    'corsheaders',
    ...
)

MIDDLEWARE_CLASSES = (
    ...
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
    ...
)

CORS_ORIGIN_ALLOW_ALL = True  # allows all 
# or use whitelist:
CORS_ORIGIN_WHITELIST = (
    'google.com',
    'hostname.example.com'
)

If you develop for a website only, you could run frontend and backend on the same server. but if you develop a mobile app you can't install and run django on the phone.

Upvotes: 2

Related Questions