I exposed API in Django backend. I want to get that API request from Angular 7. so I implemented the code that
this.HttpClient.get('Http://127.0.0.1:8000/myapp/posts')
.subscribe(
(data:any[]) => {
console.log(data)
}
)
But I'm getting an error that
Access to XMLHttpRequest at 'http://127.0.0.1:8000/myapp/posts' from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
HttpErrorResponse {headers: HttpHeaders, status: 0, statusText: "Unknown Error", url: null, ok: false, …}error: ProgressEvent {isTrusted: true, lengthComputable: false, loaded: 0, total: 0, type: "error", …}headers: HttpHeaders {normalizedNames: Map(0), lazyUpdate: null, headers: Map(0)}message: "Http failure response for (unknown url): 0 Unknown Error"name: "HttpErrorResponse"ok: falsestatus: 0statusText: "Unknown Error"url: null__proto__: HttpResponseBase
Could anyone suggest any solution to solve this error?
When sending HTTP requests from your front-end application, using the browser's fetch API, the Axios client or the jQuery $.ajax() method (a wrapper for the JavaScript XHR interface), to your back-end API built with Django REST framework the web browser will throw an error related to the Same Origin Policy.
Cross Origin Resource Sharing or CORS allows client applications to interface with APIs hosted on different domains by enabling modern web browsers to bypass the Same origin Policy which is enforced by default.
Ref how to do it here: https://www.techiediaries.com/django-cors/
you need to add a middleware file app/cors.py:
class CorsMiddleware(object):
def process_response(self, req, resp):
response["Access-Control-Allow-Origin"] = "*"
return response
This will add an Access-Control-Allow-Origin:* header to every Django request but before that you need to add it to the list of middleware classes:
MIDDLEWARE_CLASSES = (
#...
'app.CorsMiddleware'
)
Then install the django-cors-headers
Start by installing django-cors-headers using pip
pip install django-cors-headers
Related
I'm having trouble connecting my Django backend to my Flutter frontend on web.I have not tested on Android or iOS yet.
I want to be able to do an API call and have it return a response that I can convert to a json. However it's been throwing errors no matter what I've tried. I've tried converting it into an https request with no avail.
If anyone needs anything on the Django side please let me know
This is what the error looks like:
Error: XMLHttpRequest error.
dart-sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart 909:28 get current
packages/http/src/browser_client.dart 71:22 <fn>
dart-sdk/lib/async/zone.dart 1613:54 runUnary
dart-sdk/lib/async/future_impl.dart 155:18 handleValue
dart-sdk/lib/async/future_impl.dart 707:44 handleValueCallback
dart-sdk/lib/async/future_impl.dart 736:13 _propagateToListeners
dart-sdk/lib/async/future_impl.dart 533:7 [_complete]
dart-sdk/lib/async/stream_pipe.dart 61:11 _cancelAndValue
dart-sdk/lib/async/stream.dart 1219:7
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 324:14 _checkAndCall
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 329:39 dcall
dart-sdk/lib/html/dart2js/html_dart2js.dart 37307:58
at Object.createErrorWithStack (http://localhost:63593/dart_sdk.js:5362:12)
at Object._rethrow (http://localhost:63593/dart_sdk.js:39509:16)
at async._AsyncCallbackEntry.new.callback (http://localhost:63593/dart_sdk.js:39503:13)
at Object._microtaskLoop (http://localhost:63593/dart_sdk.js:39335:13)
at _startMicrotaskLoop (http://localhost:63593/dart_sdk.js:39341:13)
at http://localhost:63593/dart_sdk.js:34848:9
And this is a code snippet
import 'package:http/http.dart' as http;
var url2 = 'https://0.0.0.0:8809/test/';
try{
response = await http.get(Uri.parse(url2));
print(response.body);
}
catch(exception){
print('could not access');
response = await http.get(Uri.parse(url2));
}
},
I had it print out the error.
It might be caused because CORS is not enabled in your backend. It happens because your server and frontend are present on different IPs (Even if you are doing your work on localhost, the port is still different).
To solve this you you just have to add parameters to enable CORS in your response header. There are packages available for that acts as a middleware so you wont have to add it in every response. Refer the below question :
How can I enable CORS on Django REST Framework
I'm getting the error
Access to fetch at 'http://hpap-dev.pmacs.upenn.edu:5801/get-categories' from origin 'http://hpap-dev.pmacs.upenn.edu:5802' 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.
despite using flask_cors. My flask app and route look like this
#Start flask app
app = Flask(__name__)
#Open flask for querying from domains outside of the app
CORS(app)
<snip>
#app.route('/get-categories')
#cross_origin()
def get_categories():
frame_dict = file_cat_wrangle.get_wrangle_dict()
# orig
# return jsonify(response=frame_dict)
# stauffer - try this to resolve CORS problem
response = jsonify(response=frame_dict)
response.headers.add('Access-Control-Allow-Origin', '*')
return response
As you can see, the code's calling CORS(app) as well as #cross_origin() under the route. And I also tried adding the Access-Control-Allow-Origin header explicitly to the response, per another stackoverflow post.
I've rebuilt and restarted the flask server. AFAIK this used to work on this server (I've taken over this project at work and am pretty new to web dev). Other API calls that go between the front-end (node server) and back-end (the flask app) are working. I also checked that the route path and the call to it are identical.
Here's the call from the front end:
export const fetchCategories = () => {
return fetch(`${flask_url}/get-categories`)
.then(response => {
if (response.status >= 400) {
throw new Error(`${response.status}: ${response.statusText}`);
}
return response.json();
}).then(categories => categories);
}
Any suggestions??
Check if the header is really present in the network tab in your browser.
You can use hooks to enable cors as below:
#app.after_request
def after_request(response):
response.headers['Access-Control-Allow-Origin'] = '*'
return response
Turns out it was not actually a CORS-related error but some kind of odd error response. See my comment to the original question.
From the Django docs:
Django’s CSRF protection requires that the request have a Referer header that matches the origin present in the Host header.
Using Ionic 3.9.2 (Angular 5.2.10), how does one satisfy this requirement when posting forms since one can't add the referer header? Disabling csrf protection is not an option. The same URL works via browser (even Ionic's in-app browser but the experience is just not desirable). I'm posting JSON data.
My code:
let headers = new Headers({'Content-Type': 'application/x-www-form-urlencoded', 'HTTP_X_CSRFTOKEN': csrftoken});
return this.http.post(
hostUrl + "/auth/reset_password?org=" + org, body, {headers: headers}
).toPromise();
I am stuck with the following error message in the Chrome browser:
Failed to load http://localhost:5000/my_endpoint: Request header field
Access-Control-Allow-Origin is not allowed by
Access-Control-Allow-Headers in preflight response.
The browser is loading a webpage from a Vue.js frontend app with webpack etc. and vue-resource to perform HTTP requests to the REST backend.
The URL http://localhost:5000/my_endpoint is a HTTP GET/POST endpoint served by a python Flask application.
On the frontend Javascript I have these CORS settings:
import VueResource from 'vue-resource'
Vue.use(VueResource)
Vue.http.options.crossOrigin = true
Vue.http.headers.common['Access-Control-Allow-Origin'] = '*'
On the backend python code in the Flask app I have the following CORS configuration details:
#app.after_request
def add_header(response):
response.headers['Access-Control-Allow-Origin'] = '*'
response.headers['Access-Control-Allow-Headers'] = 'Access-Control-Allow-Headers, Origin, X-Requested-With, Content-Type, Accept, Authorization'
response.headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, DELETE, OPTIONS, HEAD'
response.headers['Access-Control-Expose-Headers'] = '*'
return response
When performing this HTTP POST request in the Javascript frontend:
this.$http.post("http://localhost:5000/my_endpoint", { my_custom_key: "my custom value"})//, {emulateJSON: true})
.then((response) => {
// do stuff
})
where { my_custom_key: "my custom value"} is the JSON body of the HTTP POST request, then in the Flask backend for some reason I see an HTTP OPTIONS request coming, cf. the Flask log:
127.0.0.1 - - [26/Jun/2018 21:45:53] "OPTIONS /ad HTTP/1.1" 200 -
There must be some sort of back/forth ceremony to honor before being able to retrieve the JSON data from the backend, but I am lost in these details.
On the internet I've seen all sorts of explanations, and I've been playing a bit with the vue-resource configuration details like:
adding/removing {emulateJSON: true} to the HTTP POST request
adding/removing Vue.http.options.xhr = { withCredentials : true }; to the configuration of Vue.js
but I am not able retrieve the JSON data coming from the backend.
Searching for "CORS" on the Vue.js documentation or on https://github.com/pagekit/vue-resource does not give any information on how to fix these issues with Cross-origin resource sharing (CORS).
How do I get a Vue.js frontend working with a Flask backend on these CORS issues?
The solution was to remove from the frontend: Vue.http.headers.common['Access-Control-Allow-Origin'] = '*' (which actually does not make sense as it's an HTTP header that usually goes into the response from the backend).
Also to clean up a bit more the backend I found out that response.headers['Access-Control-Expose-Headers'] = '*' was not needed. Probably the other HTTP headers could be more slim, but for now I keep them as they are.
I'm building my first app with Ionic and I'm using Django Rest Framework as API.
I just want to create a simple page in Ionic that shows a list of categories.
I've created the model Category, and the ViewSets for the API. When I go to the Django-rest-framwork viewer (http://localhost:3010/category/) everything works fine.
But when I try to get the results (with Ionic) I get this error:
XMLHttpRequest cannot load http://localhost:3010/category/. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8100' is therefore not allowed access.
My code:
import {Page, Platform, NavController} from 'ionic/ionic';
import {EmployeeDetailsPage} from '../employee-details/employee-details';
import {Http} from 'angular2/http';
#Page({
templateUrl: 'build/pages/getting-started/getting-started.html'
})
export class GettingStartedPage {
constructor(platform: Platform, nav: NavController, http: Http) {
this.platform = platform;
this.nav = nav;
this.http = http;
this.http.get("http://localhost:3010/category/")
.subscribe(data =>{
this.items=JSON.parse(data._body).results;//Bind data to items object
},error=>{
console.log(error);// Error getting the data
} );
}
}
You need to send CORS headers to Ionic Framework to let cross-domain ajax work, since your ionic app is hosted on port 8100, and django-server is running on port 3010, this is considered a cross-domain request.
For django, install CORS headers app through pip.
In your settings, enable 'corsheaders' app, and also add the allowed urls.
# this disables Cross domain requests
CORS_ORIGIN_ALLOW_ALL = False
# this allows cookie being passed cross domain
CORS_ALLOW_CREDENTIALS = True
# this is the list of allowed origins for cross domain ajax
CORS_ORIGIN_WHITELIST = (
'localhost:8100',
)
You may need to install CORS.
If you are testing on chrome you might also need to allow cross origin (There is an extension for it) which should get you around the CORS issue.