connecting angular2 with django api - python

So I am trying to connect my angular2 app hosted on localhost:4200 to my django api hosted on localhost:8000 , i already have an angular 1,6 app hosted over localhost:800 that manages the login and all the other stuff,
so in my angular2 app i received the token stored in my cookies and i am trying to send a get request using it in the header to the django api .
ps: i already checked my django api and its currently allowing access to all servers with no exception .
fetchUser(){
console.log("Here");
let headers = new Headers({'Accept': 'application/json','X-CSRFToken': this.token});
this.http.get( 'http://localhost:8000/api/orgs', {headers: headers}).subscribe(
(response: Response) => {
const testResponse = response.json();
this.outerLinks.data = testResponse;
this.data =testResponse;
this.dataChange.next(this.data);
}
);
}
So I am receiving this error:
XMLHttpRequest cannot load localhost:8000/api/orgs. Response for preflight is invalid (redirect)

You can try Allow-Controll-Allow-Origin: *
if you use Chrome try this ext
https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi?hl=en

Modify your settings.py by adding the following code:
CORS_ORIGIN_ALLOW_ALL = False
CORS_ORIGIN_WHITELIST = (
'localhost:4200'
'<YOUR_DOMAIN>[:PORT]',
)

Related

Sending cookies/sessions to subdomains

As the title says, I'm trying to set cookies/sessions on the browser.
To preface:
Frontend: https://www.example.com
Backend: https://api.example.com
Frontend makes a request to the backend, the backend creates a session, and a cookie is sent back to the frontend in the response.
Problem:
The request is successful and the response shows that there is a session, however it was not set. The error message is as follows:
This attempt to set a cookie via a Set-Cookie header was blocked because its Domain attribute was invalid with regards to the current host url.
Research:
Based off this and this, it appears that:
cookies can be shared is that both domains have the same main-domain
Which is the case for my scenario. The main domain is example.com and the subdomains are www.example.com and api.example.com.
In addition, Mozilla official documentation states that:
if a domain is specified, then subdomains are always included
Implementation
The frontend is developed in React and the backend is developed in Python (Flask). Both are hosted Heroku. Domain registrar is with GoDaddy and I'm using Cloudflare as my DNS to re-route traffic and setting the correct domains.
A sample request looks like this:
const headers = {
'Content-Type': 'application/json',
'X-CSRF-Token': csrfToken
};
...
const handleFormSubmission = async e => {
e.preventDefault();
await axios.post('https://backend.com/add-results', { tokenId: tokenId }, { withCredentials: true, headers: headers })
}
And the backend has the following settings:
...
CORS(app, origins=["https://www.example.com"], expose_headers=["Content-Type", "X-CSRFToken"], supports_credentials=True)
...
app.config['SESSION_COOKIE_SECURE'] = True
app.config['SESSION_COOKIE_HTTPONLY'] = True
app.config['REMEMBER_COOKIE_SECURE'] = True
app.config['REMEMBER_COOKIE_HTTPONLY'] = True
app.config['SESSION_COOKIE_DOMAIN'] = 'example.com'
Was wondering if anyone has experienced a similar problem and found a solution. I got the idea of using subdomains from here, but I have had no luck with my implementation.
Here's a screen shot of what I'm getting
The fix was actually pretty simple:
CORS(app, origins=["https://www.example.com", "https://example.com"], expose_headers=["Content-Type", "X-CSRFToken"], supports_credentials=True)
app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY')
app.config['SESSION_COOKIE_SECURE'] = True
app.config['SESSION_COOKIE_HTTPONLY'] = True
app.config['REMEMBER_COOKIE_SECURE'] = True
app.config['REMEMBER_COOKIE_HTTPONLY'] = True
app.config['SESSION_COOKIE_SAMESITE'] = 'None'
app.config['SESSION_COOKIE_DOMAIN'] = '.example.com'
app.config['WTF_CSRF_SSL_STRICT'] = False
Main changes were:
app.config['SESSION_COOKIE_SAMESITE'] = 'None'
And:
app.config['WTF_CSRF_SSL_STRICT'] = False
SESSION_COOKIE_SAMESITE needed to be 'None' to avoid the default value of 'Lax' which would prevent the cookie from being received and set on the browser.
WTF_CSRF_SSL_STRICT was set to false because the origins of the request and the server needed to be the same (same origin policy). However, I have configured a whitelist of allowed origins in my CORS configuration. That said, I think that covers that case.
Also, I cleared my caches on my browser and the DNS. In addition, I restarted my servers where the frontend and backend were hosted.
Hopes this helps others, cheers!

Why does my Flask API endpoint get a CORS error, but other similarly programmed endpoints do not?

Problem
I have a Flask API with two different kinds of routes. I am making requests to my API endpoints from a JavaScript/D3.js application. I need help troubleshooting a CORS error.
Endpoint format
One kind of endpoint follows the format http://127.0.0.1:5000/api/v0.1.0/infrastructure/primary_type/secondary_type
And the other kind follows the format http://127.0.0.1:5000/api/v0.1.0/infrastructure/primary_type/
I am getting a CORS error for the one following the format http://127.0.0.1:5000/api/v0.1.0/infrastructure/primary_type/
CORS Error
Access to fetch at 'http://127.0.0.1:5000/api/v0.1.0/infrastructure/primary_type' from origin 'http://127.0.0.1:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
Endpoint Code
Working Endpoint
#bp.route("<primary_type>/<secondary_type>")
def get_infrastructure(primary_type, secondary_type):
infrastructure = ''
if primary_type == 'null':
infrastructure = shotgun_api.db.infrastructure.find({'properties.type.secondary': secondary_type}, projection = {'_id': False})
else:
infrastructure = shotgun_api.db.infrastructure.find({"$and": [{'properties.type.primary': primary_type},{'properties.type.secondary': secondary_type}]}, projection = {"_id": False})
response = jsonify([resource for resource in infrastructure])
response.headers.add("Access-Control-Allow-Origin", "*")
return response
Endpoint triggering errors
#bp.route('<primary_type>/')
def get_by_primary_type(primary_type):
infrastructure = shotgun_api.db.infrastructure.find({'properties.type.primary': primary_type}, projection = {'_id': False})
response = jsonify([resource for resource in infrastructure])
response.headers.add("Access-Control-Allow-Origin", "*")
return response
Expected behavior
I would expect that using the same response.headers.add... code would provide me with a 200 OK status but it only works for the more complex endpoint for some reason.
Client Side JavaScript/D3.js
for (let i = 0, num_draw_props = lyr.draw_props.length; i < num_draw_props; ++i) {
start_loading_layer();
Promise.all(lyr.draw_props[i].src.map(x => lyr.draw_props[i].d3_fetch(x)))
.then(function(files) {
lyr.context.restore();
lyr.context.save();
return files;
}).then(files => {
transform_layer(lyr.context, transform);
return files
}).then(files => {
console.time('draw_layer')
lyr.draw_props[i].draw_layer(lyr.context, files);
console.timeEnd('draw_layer')
});
}
Where d3_fetch is equal to d3.json(). When src is 'http://127.0.0.1:5000/api/v0.1.0/infrastructure/mines/coal' everything works fine, but when src is http://127.0.0.1:5000/api/v0.1.0/infrastructure/railroads I get the previously mentioned CORS error.
What I've tried
I have tried using Flask-CORS but was unable to get it accessible to my application despite installing it with pip. I would prefer to solve this without using Flask-CORS. I am otherwise at a loss for what to do here and any advice is appreciated.

allowing CORS request with Flask and React

I am trying to connect a client with a server via ajax requests.
My client, running on localhost:8080, has a button which invokes a function that does a simple ajax request to a locally running server, localhost:5000.
onClick function:
handleClick() {
console.log("check flights button was clicked!");
console.log(this.state);
const baseUrl = 'localhost:5000'
ajax.get(`${baseUrl}/flights/${this.state.origin}_${this.state.destination}`)
.end((error, response) => {
if (!error && response) {
console.log('got a valid response from the server')
} else {
console.log(`Error fetching data from the server: `, error)
}
});}
the (very) simple server, implemented with Flask, is as follows:
from flask import Flask, request
from flask_restful import Resource, Api
from json import dumps
app = Flask(__name__)
api = Api(app)
class Flights(Resource):
def get(self, origin, destination):
answer = 'we got some data ' + origin + ' ' + destination
print answer
api.add_resource(Flights, '/flights/<string:origin>_<string:destination>')
if __name__ == '__main__':
app.run()
I can access the server if i simply go to localhost:5000/flights/origin_destination, which prints a message saying it received the origin and destination.
However, when I try to do the ajax request, I get the following error:
XMLHttpRequest cannot load localhost:5000/flights/Porto_Lisboa. Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https.
Any suggestions on how to correct this behaviour?
Thank you in advance.
As the error suggest, you're missing the protocol name in your request. Try to add it at the start of the string :
const baseUrl = 'http://localhost:5000'
instead of just localhost:5000

How to connect a Django view with angular js Front end?

I'm fairly new to Django rest and angularjs. I'm trying to create a Django view which will have a function and this function has to be called via a button in angular js. Can anyone please help me out?
Thanks
This might help:
Django - Angular Tutorial
General answer would be:
1) Using for example Django REST expose your method (endpoint)
2) From Angular application send request to the previously exposed endpoint.
say this is your Django/python api end point (assume controller file to be random.py)
def getRandomInfo(request):
try:
result = database.getRandomInfo()
return JsonResponse(result, content_type="application/json", safe=False)
except Exception as e:
import traceback
traceback.print_exc(e)
return JsonResponse({error:'sorry'}, content_type="application/json", safe=False)
Via angular, provided you have resolved all the dependencies and have a functioning angular app and/or controller set up in your html/js
you can call the api using below code
app.controller("appControllerName", function ($scope, $http) {
$http.get("{% url 'getRandomInfo' %}")
.success(function (response, status) {
response_data = response
$scope.data = response_data;
}).error(function (response, status) {
$scope.status = status;
});
}
if you notice the {% url 'getRandomInfo' %} , this is defined in your urls.py , u'll have to add a line like this over there where getRandomInfo will have to be the 'name' of the url
url(r'^random/getRandomInfo/$',random.getRandomInfo, name='getRandomInfo'),
Over here you controller name is random and a function within that controller is def getRandomInfo, so django allows two ways to access this endpoint, either via the url r'^random/getRandomInfo/$ (yes regex is allowed here) or via the name as stated in the example here.
Best of Luck :)

google app engine python as backend and angular js as frontend for mobile web

I m trying to implement end to end data sharing between GAE via python and angularJS mobile app using JSON as request body from mobile with contentType as application/json.
I can see in my log that GAE is receiving data and sending a response i.e. {'status': true}.
My Firebug console shows red font(error) for POST request to my GAE server but response status is 200 (ok). Mobile app is getting a 200 status of response but does not get the data.
In my mobile app I'm using $http.post(url, data); to make an http request to GAE and I get this in my Firebug console:
POST http://<code>serverAddress_is_localhost_for_testing</code>:8080/serviceProvider
200 OK
23ms
In the GAE log I can see that the data is processed correctly. This is response code for Python:
self.response.headers['Content-Type'] = 'application/json'
self.response.out.write(response)
Try adding
self.response.headers.add_header("Access-Control-Allow-Origin", "*")
before
self.response.out.write(response)
If that works, replace "*" with your angular/mobile app's domain.
Read more on Cross-origin resource sharing here.

Categories