AngularJS working with a Django CORS API

I have successfully implemented CORS in Django using the "django-cors" package:

https://github.com/ottoyiu/django-cors-headers

Upon following the installation instructions, I have configured the settings as follows:

CORS_ORIGIN_ALLOW_ALL = False

CORS_ORIGIN_WHITELIST = (
    'http://localhost:8000'
)

The Django application is running on

My frontend utilizes an Angular app that runs on "http:/localhost:8000", and I have made the necessary modifications to enable communication with the Django app.

RestangularProvider.setBaseUrl('http://localhost:3000/');

[Utilizing Restangular for resource APIs]

When attempting to make a GET API call, a pre-flight request of method "OPTIONS" is sent, resulting in the following error message:

XMLHttpRequest cannot load http://localhost:3000/users. Credentials flag is set to 'true', yet the 'Access-Control-Allow-Credentials' header is not defined. It should be 'true' in order to allow credentials. Origin 'http://localhost:8000' is thereby denied access.

After referencing the documentation, I learned that certain headers needed to be included in the request to meet server expectations. Consequently, I added the following line of code: RestangularProvider.setDefaultHeaders({"x-requested-with" : 'XMLHttpRequest'});

Despite this adjustment, another error persists without resolution: XMLHttpRequest cannot load http://localhost:3000/users. Response for preflight is invalid due to redirection.

Please note that the request/response headers are outlined below:

General:
Remote Address:127.0.0.1:3000
Request URL:http://localhost:3000/users
Request Method:OPTIONS
Status Code:301 MOVED PERMANENTLY

Response Headers
Access-Control-Allow-Headers:x-requested-with, content-type, accept, origin, authorization, x-csrftoken, user-agent, accept-encoding
Access-Control-Allow-Methods:GET, POST, PUT, PATCH, DELETE, OPTIONS
Access-Control-Allow-Origin:http://localhost:8000
Access-Control-Max-Age:86400
Content-Type:text/html; charset=utf-8
Date:Thu, 17 Dec 2015 11:10:16 GMT
Location:http://localhost:3000/users/
Server:WSGIServer/0.1 Python/2.7.10
X-Frame-Options:SAMEORIGIN

Request Headers
Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8
Access-Control-Request-Headers:accept, x-requested-with
Access-Control-Request-Method:GET
Cache-Control:no-cache
Connection:keep-alive
Host:localhost:3000
Origin:http://localhost:8000
Pragma:no-cache
Referer:http://localhost:8000/
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36

Answer №1

After various attempts, I successfully resolved the issue at hand. The core problem stemmed from a misstep in API naming.

Upon inspection, I discovered that my colleague had named the API incorrectly:

url(r'^users/', views.user_details)

Whenever I attempted to call "/users", the APPEND_SLASH setting in Django triggered a permanent redirect to "/users/". This behavior is outlined in the Django documentation for APPEND_SLASH:

When set to True, if the request URL doesn't match any specified patterns in the URLconf and lacks a trailing slash, an HTTP redirect will be generated with the slash appended. It's important to note that this redirection may result in loss of data submitted via a POST request.

This behavior associated with the APPEND_SLASH setting is only activated when the CommonMiddleware is included.

The most straightforward and effective solution to this dilemma was to adjust the API url by eliminating the trailing slash, like so:

url(r'^users', views.user_details)

By making this adjustment, the URL could be matched directly without triggering any redirects.

In cases where maintaining the trailing slash in the API is necessary, it is still achievable by implementing the following code in AngularJS:

resourceProvider.defaults.stripTrailingSlashes = false;
RestangularProvider.setRequestSuffix('/'); 

It should be noted that while the above approach is functional, it is not the recommended practice. Nevertheless, based on my experimentation, I wanted to share this insight.

Answer №3

It appears that the django-cors documentation specifically mentions using only hostnames (and not full URLs) in the django settings. For example:

Sample:

    CORS_ORIGIN_WHITELIST = (
        'example.com',
        'hostname.test.com'
    )


Default:

    CORS_ORIGIN_WHITELIST = ()

You could start by trying something simple, like localhost, and see if it works. Then, you can experiment with adding the port number to see if functionality is still retained.

Answer №4

I encountered an issue with CORS while setting

$httpProvider.defaults.withCredentials = true;
in my Angular app. Despite trying multiple solutions, I finally found a fix that worked for me and will hopefully work for you as well.

To resolve this, simply add the following code to your Django Apache config file, which is typically located in a *.conf file like httpd.conf or apache.conf, or within a .htaccess file:

<IfModule mod_headers.c>
SetEnvIf Origin (.*) AccessControlAllowOrigin=$1
Header add Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin
Header set Access-Control-Allow-Credentials true
</IfModule> 

If there is existing code, locate the directory in the file and insert the code below:

SetEnvIf Origin (.*) AccessControlAllowOrigin=$1
    Header add Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin
    Header set Access-Control-Allow-Credentials true

Additionally, make sure to update your Angular app configuration with the following changes:

angular.module('app', ['ngCookies'])
    .config([
   '$httpProvider',
   '$interpolateProvider',
   function($httpProvider, $interpolateProvider, $scope, $http) {
       $httpProvider.defaults.withCredentials = true;
       $httpProvider.defaults.xsrfCookieName = 'csrftoken';
       $httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
   }]).
   run([
   '$http',
   '$cookies',
   function($http, $cookies) {
       $http.defaults.headers.post['X-CSRFToken'] = $cookies.csrftoken;
   }]);

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Digital Repeater and Angle Measurer

Seeking Guidance: What is the recommended approach for locating the Virtual Repeaters in Protractor? A Closer Look: The Angular Material design incorporates a Virtual Repeater to enhance rendering performance by dynamically reusing visible rows in the v ...

What should be the proper service parameter type in the constructor and where should it be sourced from?

Currently, I am faced with a situation where I have two Angular 1 services in separate files and need to use the first service within the second one. How can I properly type the first service in the constructor to satisfy TypeScript requirements and ensure ...

The function process_request() was called with 2 arguments but only 1 was provided - A Tutorial on Basic HTTP Authentication Decorator

My current task involves creating a simple decorator that will allow us to apply basic HTTP Authentication to specific django views. This is the decorator I have implemented: def basic_auth(func): def process_request(self, request): if reque ...

The changes to the grid options do not reflect immediately on the UI Grid interface

I am currently working on a project using the UI Grid module in AngularJS. I want to include row filtering as an option, but since not all users require it and the filter boxes take up a lot of space, I decided to disable filtering by default and add a but ...

Tips for implementing http requests with ng-repeat and nested JSON in AngularJS

My JSON code functions properly when it is not nested. It works best without any commas between the data, using only one block of JSON. Here's my Angular setup: <html> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angul ...

Leveraging the value service in AngularJS

Struggling to grasp the concept of .value() and how to utilize it in controllers... Here's an example where we declare the .value() in services.js : .value("ScanDatas",{ scanData: {} }) Once "scanData" is defined, it should be available througho ...

refreshing a seraph or seraph model with new values

I am looking to modify an object in a Neo4j database using Seraph. The code I have been using seems to always add a new object instead of updating the selected one. app.put('/contactlist/:name',function (req,res){ db.find({name: req.params.name ...

When the setDetached() function was called on an entity, it resulted in the removal of the getValidationErrors

When an entity is detached or not added to the manager, does the array of validations on the entity get destroyed? Will a newly created entity without being added to the manager lack the validation set on your model? This poses an issue for me as I am dy ...

Steps for assigning a $scope variable from within a different $scope variable

I am facing an issue with setting the value of a $scope variable after a promise (specifically, an $http request) is completed. Here's the code snippet in question: .controller('NewItemCtrl', function ($scope, $state, LabelFactory) { $sc ...

What is the best way to set the default display of the first option value in a dynamically populated <select> dropdown menu?

I have a field that displays options dynamically. I am looking to set the first option value as the default in the select field. Can someone provide assistance with this? <div class="col-lg-4"> <select name="trader" class="form-control" id="sele ...

Can you explain the significance of the syntax "require: ^"?

Can someone explain the significance of the ^ symbol under require in this Angular directive code snippet? I came across this code and am having trouble understanding its meaning. .directive('accordionGroupHeading', function() { return { ...

I must display the output in the proper format as illustrated below

angular.forEach(caseChangeRecord, function(change, key) { if (caseChangeRecord != 'undefined') { body += change.fieldName + ' : ' + change.newValue; } }); Expected Display Output: A:B A:B A:B ...

Tips for displaying lesser-known checkboxes upon clicking a button in Angular

I have a form with 15 checkboxes, but only 3 are the most popular. I would like to display these 3 by default and have an icon at the end to expand and collapse the rest of the checkboxes. Since I'm using Angular for my website, I think I can simply ...

The controller function is experiencing a reference error where a parameter is returning as undefined

Currently, I am following a learning lab for AngularJS which can be found here. I have managed to make the example work with a small bug fix. In addition to that, I am exploring good coding practices for AngularJS by referring to this guide. This has led ...

Exploring the intricacies of .$on() in AngularJS

Recently, in a tutorial I came across the following code snippet: $rootScope.$on('abc',function(event, next, current){ }); This has raised some questions for me. Namely, what exactly does the .$on() function do? And why is it prefixed with a $ ...

Is it possible to create a personalized serialize form when sending an AJAX POST request

How can I format form data on an AJAX POST request differently than the default $("#formid").serialze()? The current result is not suitable for my needs, as it looks like this: `poststring="csrfmiddlewaretoken=bb9SOkN756QSgTbdJYDTvIz7KYtAdZ4A&colname= ...

Invalid preflight response (redirect) error

I am a beginner in utilizing Laravel and Lumen frameworks for my projects. Currently, I am working on my first project using Lumen and attempting to create an API call from Angular. Below is the Angular code snippet: app.controller('ListCtrl', ...

Exploring the interception of ajax http responses beyond the scope of AngularJS

Is there a way to capture and manage http responses from outside of Angular? $httpProvider is not an option since the target script loads after Angular has initialized. I need a solution that functions similar to ajaxSuccess in jQuery. ...

Error callback not being invoked on save() method in AngularJS service

So I am currently using the AngularJS Restful Service $resource in my project. However, when I try to call the $save function and provide an error callback, it does not get invoked. Surprisingly, even though the server sends a 418 error, which is not a suc ...

Guide to dynamically generating Angular watchers within a loop

I'm looking to dynamically create angular watches on one or more model attributes. I attempted the following approach: var fields = ['foo', 'bar']; for (var i=0, n=fields.length; i<n; i++) { $scope.$watch('vm.model.&ap ...