2
votes

I'm using django 1.11.7 and I've installed django-cors-hearders. I've been trying to send custom headers in POST request to my DRF application but I'm getting the following error:

Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. The response had HTTP status code 400

localhost:3000 is where the calling application is hosted. The javascript POST request has the following headers:

headers.append('Access-Control-Allow-Origin','*');
headers.append("Access-Control-Allow-Methods", "GET, HEAD, OPTIONS, POST, PUT");
headers.append("Access-Control-Allow-Headers","Origin, header-one, X-Requested-With, Content-Type, Accept, Authorization, If-Modified-Since, Cache-Control, Pragma");
headers.append('Content-Type', 'application/json');
headers.append('header-one', "value@123");

I have tried the following:

1) Modified my django app views function

if str(request.method).lower() == 'options':
        headers = {
            "Access-Control-Allow-Origin": "*",
            "Access-Control-Allow-Methods": "POST",
            "Access-Control-Allow-Headers": "HTTP_HEADER_ONE"
        }
        return Response({}, headers=headers, status=status.HTTP_200_OK)

2) Commented out this line in MIDDLEWARE = [...] of settings.py:

'django.middleware.clickjacking.XFrameOptionsMiddleware'

because apparently it intereferes with the cors middleware.

3) Added the following code to settings.py

INSTALLED_APPS = [....
'corsheaders',
...
]
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
...
]

4) CORS configuration:

CORS_ORIGIN_ALLOW_ALL = True

from corsheaders.defaults import default_headers
CORS_ALLOW_HEADERS = default_headers + (
    'header-one',
) 

And now I get this error:

Request header field Access-Control-Allow-Origin is not allowed by Access-Control-Allow-Headers in preflight response.

5) Server configuration (in settings.py itself)

from connector import Server

def load_server_list():
    for s in SERVER_LIST:  # from CUSTOM_SETTINGS_MAPPINGS  # noqa
        server = (len(s) > 2) and unicode(s[2]) or None
        Server(host=unicode(s[0]), port=int(s[1]), server=server)
    Server.freeze()
load_server_list()

This also throws an error saying 'no module named connector'. I did some more research related to 'connector' and apparently that's for MySQL type databases, but I'm using mongodb (mongoengine to work with django).

What am I doing wrong?

2
I feel like client side configuration seems fine but may be missing some django enable CORS configurations - github.com/crs4/ome_seadragon/wiki/… - Keshan Nageswaran
@KeshanNageswaran I followed the link and added the load_server_list() method but it gave me an error: No module names 'connector'. Is there something else to install? - Shamail Mulla

2 Answers

0
votes

This might help you. I used this config for my djangularjs app

(function() {
    'use strict';

    angular
        .module('app_name.config')
        .config(config);

    config.$inject = ['$locationProvider', '$httpProvider'];

    /**
     * @name config
     * @desc Enable HTML5 routing
     */
    function config($locationProvider, $httpProvider) {
        $locationProvider.html5Mode(true);
        $locationProvider.hashPrefix('');

        $httpProvider.defaults.xsrfCookieName = 'csrftoken';
        $httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
    }

})();
0
votes

I figured this out.

1) On the client side the headers should only include the custom headers which would make the code:

headers.append('Content-Type', 'application/json');
headers.append('header-one', "value@123");

2) Make no changes in the django app views. So remove the following lines from your view function if it is there:

if str(request.method).lower() == 'options':
        headers = {
            "Access-Control-Allow-Origin": "*",
            "Access-Control-Allow-Methods": "POST",
            "Access-Control-Allow-Headers": "HTTP_HEADER_ONE"
        }
        return Response({}, headers=headers, status=status.HTTP_200_OK)

3) Add these lines in your settings.py:

(to use CORS settings when running your django app)

INSTALLED_APPS = [....
'corsheaders',
...
]
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
...
]

(for urls accessing your django app)

CORS_ORIGIN_ALLOW_ALL = True

or

CORS_ORIGIN_ALLOW_ALL = False
CORS_ORIGIN_WHITELIST = ('tuple of urls allowed to access your app')

(for request object headers coming from the client side)

from corsheaders.defaults import default_headers
CORS_ALLOW_HEADERS = default_headers + (
    'header-one',
) 

(for response object headers being sent to the client side)

CORS_EXPOSE_HEADERS = ['list of headers to send']

4) load_server_list() function using connector.Server is not required

These headers will be accessible at your project level so every view function will not need to explicitly return a response for OPTIONS request. django-cors-headers takes care of it for you. For more explicit configuration settings check out: https://github.com/ottoyiu/django-cors-headers