Cannot POST data cross domain in Angular app - javascript

EDIT:
Problem is resolved. My front end code is fine, it's error of back end guys.
I have problem when POST data cross domain. I don't know why, just 3 hours ago it worked fine. At that time I just made some changes in CSS and HTML, I was not touch to any JS file. I also asked the Back end team (They're using Ruby on Rails) and they told me that they still working on localhost.
This error appear every time I try to POST to server when using both Firefox and Chrome:
XMLHttpRequest cannot load https://time-traveler-back.herokuapp.com/api/sessions/login. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:9000' is therefore not allowed access. The response had HTTP status code 503.
For Chrome, I already installed CORS app. But if I turned it on, another error appear:
XMLHttpRequest cannot load https://time-traveler-back.herokuapp.com/api/sessions/login. A wildcard '*' cannot be used in the 'Access-Control-Allow-Origin' header when the credentials flag is true. Origin 'http://localhost:9000' is therefore not allowed access.
Here is my app config:
// Config for POST data cross domain
app.config(['$routeProvider', '$httpProvider', function($routeProvider, $httpProvider) {
$httpProvider.defaults.useXDomain = true;
$httpProvider.defaults.withCredentials = true;
delete $httpProvider.defaults.headers.common["X-Requested-With"];
$httpProvider.defaults.headers.common["Accept"] = "application/json";
$httpProvider.defaults.headers.common["Content-Type"] = "application/json";
}]);
This is how I POST data:
var apiUrl = 'https://time-traveler-back.herokuapp.com/api/';
$http({
method: 'POST',
url: apiUrl + 'sessions/login',
data: $.param(formData), // pass in data as strings
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
} // set the headers so angular passing info as form data (not request payload)
})
.then(function successCallback(response) {
// my stuffs
}, function errorCallback(response) {
// my stuffs
});
Please help me. Thanks.

Credentials and CORS
One thing to note when using withCredentials: true in your app and
configuring the server for CORS is that you may not have your
Access-Control-Allow-Origin header set to '*'. It must be configured
to a few select origins. If you absolutely must have this set to *,
then I suggest doing something beyond cookie based authentication,
such as token-based authentication.
See AngularJS Authentication and CORS

Looks like a standard CORS error.
You already fixed, but in case of doubt, I'll give some recommendations:
Rack-CORS
If using rails as the backend, you should definitely check out the rack-cors gem. This basically sets up all the CORS policies for your server through the middleware in the most simple way possible:
#config/application.rb
...
config.middleware.insert_before 0, "Rack::Cors" do
allow do
origins '*'
resource '*', headers: :any, methods: [:get, :post, :options]
end
end
This allows you to permit particular domains "origins" & methods to your app.
--
You must also remember that to prevent cross domain XML requests, "CORS" (Cross Origin Resource Sharing) was instituted to apply a "lock" on which resources / urls are accessible by JS requests.
As a rule of thumb, if you're ever using JS to automagically update the front-end with an XML request of a separate domain (not just Ajax), you'll need to permit the domain in your server's CORS policy.
There are a number of ways to do this; simplest with rails is to use the rack-CORS gem (as above).

Related

Cannot call Apache Airflow REST API using JavaScript Fetch API (CORs Error)

Working with Apache Airflow REST API, and having issues with CORS.
When calling the endpoint using the fetch API in JavaScript I get the following error:
Access to fetch at 'my_url/api/v1/dags/example_bash_operator/tasks' from origin 'my_url' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: 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.
This is how I am calling it:
let url = "my_url/api/v1/dags/example_bash_operator/tasks";
let username = 'my_username';
let password = 'my_password';
let headers = new Headers();
headers.set('Authorization', 'Basic ' + btoa(username + ":" + password));
fetch(url, {
headers: headers,
method: 'GET',
})
.then(response => response.json())
.then(data => {
console.log('Success:', data);
})
.catch((error) => {
console.error('Error:', error);
});
I also tried adding mode: 'no-cors' but just get the "unexpected end of input" error.
For some background, the following works fine:
starting the airflow webserver and scheduler
accessing the airflow UI
accessing the SwaggerUI authenticating Swagger and calling the REST endpoints with this tool
calling my_url in the address bar of a new browser tab (returns the expected JSON)
I have set the auth_backend in airflow.cfg:
auth_backend = airflow.api.auth.backend.default
Although with the latest REST API version I don't think this makes a difference since everything is set to deny.
I have also set the access control headers in airflow.cfg as described in the docs:
access_control_allow_headers = origin, content-type, accept
access_control_allow_methods = POST, GET, OPTIONS, DELETE
access_control_allow_origin = my_url
...and also tried with wildcard for the access_control_allow_origin:
access_control_allow_origin = *
So the REST calls work fine through Swagger and through the browser address bar, but I cannot call it with fetch using JS. Note that the JS is in an index.html file on the same server (and same root directory) as the airflow files.
The described behavior makes sense, since CORS is used by the browser to prevent attacks from scripts of different resources.
You are still able to fetch via Swagger, Postman or other tools, even through the browser via address bar. But if the policy does not allow to fetch from a different origin, then the browser prevents fetching from your script, which is probably served on a different port. Origin contains host and port.
Your main issue, I cannot help with at the moment.
I've faced the issue of not being able to set the origin policy within the Airflow 2.0 server/API through the (docker-compose) environment variable AIRFLOW__API__ACCESS_CONTROL_ALLOW_ORIGIN.
Maybe it's related to your issue, since I can see from the url of your question (containing the v1), that you're are also using Airflow 2.x.
By the way, the message from chrome is CORS error: Preflight Missing Allow Origin Header, referring to the question in the comments of the original question.

How to solve CORS Origin issue when trying to get data of a json file from localhost

I was trying to get the data from a json file (which is on the remote server) from localhost and I am getting error 'from origin 'http://localhost:5000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.'
Below is the code I used to send the get request.
$.ajax({
url: 'http://abc/some.json',
type: "GET",
dataType: "json",
headers: {
"Access-Control-Request-Headers": "*",
"Access-Control-Request-Method": "*",
'Content-Type':'application/json'
},
success: function (data) {
alert(data);
chatbotConfig = data;
console.log(chatbotConfig);
}
})
I am able to get the data using postman. I understand that postman is not a browser so it is not limited by CORS policy. But I am able to download the content from json file directly from the browser. Nit able to understand why I am facing issue when I tried to access from localhost. Can any one please help me to resolve this issue.
Well, the CORS error may lie in different layers of your application. Usually, by allowing all (*) origins and headers in the server-side, your problem should be fixed. But sometimes it won't and it lies somewhere else like your HTTP request header or body, DNS settings (Making sure there are no third-party DNS set in your network by yourself through the OS), or browser settings. So I will describe all of the possible solutions here shortly.
NOTE: You can read more about CORS policy here.
How to solve CORS error
If you have access to your server-side settings and/or options you need to make sure (Or if you don't you need to ask your backend developer) that everything set correctly there or not. So the steps will be as follows:
First of all, you need to make sure your server configs for CORS are set correctly.
So for example, if you are using Apache you can set the CORS policy in your .htaccess file like this (or simply check if it exists):
// This will allow all origins to access your server
Header set Access-Control-Allow-Origin "*" // You can set * to whatever domain
Header add Access-Control-Allow-Methods "*"
If you are using nodeJS you can check or set it like this:
app.use((req, res, next) => {
res.setHeader("Access-Control-Allow-Origin", "*");
res.header(
"Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept"
);
next();
});
If you are using Nginx you can check or set it in nginx.conf like this:
server {
location / {
add_header Access-Control-Allow-Origin "*";
add_header Access-Control-Allow-Methods "*";
}
}
If you use any other service for your server-side you should read the documentation about it, but all of them are actually same.
If you checked the above step and CORS policy was set correctly in your server-side, you may need to check your HTTP request and make sure everything is set correctly there. For example, there is no need to add these two headers
"Access-Control-Request-Headers": "*",
"Access-Control-Request-Method": "*",
in your request, because they do not exist as a header in the client-side. Wrong HTTP request API end-point address or options (like dataType), wrong HTTP request body or headers may also cause the CORS error for your here. So you need to check them all and make sure you are set them correctly.
If none of the above was the problem you can try two other approaches. I mostly encourage to use the second one if none of the above solves your problem.
Mapping your localhost to a URL using your hosts file (Usually lies under etc folder in each operating system). You can do that like this (But it's better to read the documentation for each OS).
127.0.0.1 www.test.com ## map 127.0.0.1 to www.test.com
## or
localhost www.test.com
NOTE: Usually it is better to avoid this approach.
Use browser plugins like Allow CORS.
Basically if you clearly look into the issue logs:
'from origin 'http://localhost:5000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource
It's saying CORS not enabled at resource. which means it need to be fixed or allowed at server side.

Cannot 'GET' mLab Data b/c of CORS

I can't execute the 'GET' request with the getTasks() function.
$(document).ready(function(){
getTasks();
});
const apiKey = 'xxxxxxx';
function getTasks(){
$.ajax({
type: 'GET',
url: 'https://api.mlab.com/api/1/databases/taskmanager/collections/tasks?apiKey='+apiKey,
contentType: 'application/json',
xhrFields: {
withCredentials: true
},
success: function(data){
console.log(data);
},
error: function(){
console.log('FAIL')
}
})
}
The error that I get is:
api.mlab.com/api/1/databases/taskmanager/collections/tasks?apiKey=xxxxxxx
Failed to load resource: the server responded with a status of 400
(Bad Request)​
Response to preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'null' is therefore not allowed access. The response
had HTTP status code 400.
I understand that Google-Chrome on Windows is CORS enabled, and will not (by default) allow communication with a different domain. I'm not sure what a preflight request is. Regardless, I tried to implement what I saw from Using CORS - HTML5 Rocks​ (from the CORS from jQuery section), but to no avail.
At a guess, the remote API simply does not respond to pre-flight requests for GET calls (because it shouldn't have to).
Your code is triggering a pre-flight request because it is non-simple. This is due to your adding a Content-type: application/json header. A request Content-type header is used to indicate the request payload format. As it is a GET, there is no payload.
Try this instead...
$.getJSON('https://api.mlab.com/api/1/databases/taskmanager/collections/tasks', {
apiKey: apiKey
}).done(function(data) {
console.log(data)
}).fail(function() {
console.log('FAIL')
})
CORS is there to protect you. If you want some more info on it, wikipedia has a good entry on it.
It appears the issue here is that you're trying to access your mongodb hosted by mlab directly from your web app. As you can see in your code, you're providing credentials/api keys to make that request.
My guess is that mlab's intent of not allowing CORS is to prevent you from doing this. You should never put your private API keys in html to be hosted on a web page, as it's easily accessible by reading source code. Then someone would have direct access to your mongodb.
Instead, you should create a server-side application (node, or... ** Whatever **) that exposes an api you control on the same domain (or a domain you give permission to via CORS).
As far as the "preflight" request, if you look in your chrome debugging tools, you should see an additional request go out with the "OPTIONS" method. This is the request that chrome (and most other http clients) send out first to a server hosted on a different domain. it's looking for the Access-Control-Allow-Origin header to find out whether it's allowed to make the request. Pretty interesting stuff if you ever have some time to dig into it.

How can solve Access-Control-Allow-Origin error?

I have setup a small web application on heroku.com in Django which returns JsonResponse you can see it here.
{
name: "shubham",
college: "MAIT",
subject: "java"
}
And I also setup server locally on my computer which accepts that JSON and it appends with HTML element here my javascript file :
$(function (){
$.ajax({
type:'GET',
url:'https://justgiveme.herokuapp.com/',
dataType :"Json",
contentType: "application/json; charset=utf-8",
success: function(data) {
alert("Success !");
},
error : function()
{
alert("failed !");
}
});
});
but when I open localhost it gives me alert("failed !") instead of alert("success !"); .
I have check on Chrome console and I found this error :
Any helpful suggestion is appreciable .
You need to enable Cross-Origin-Resource-Sharing (CORS) on your heroku app. Right now its failing because the request isn't coming from the domain which the first resource was retrieved from. In your case, 127.0.0.1.
Here's a starting point for Django on CORS: http://www.django-rest-framework.org/topics/ajax-csrf-cors/
The error you are seeing is because the browser sends a preflight request to check if a cross origin request is allowed. You can see it being sent when viewing the Network tab in the Chrome Inspector. It will be an OPTIONS request to the url that is specified in the ajax.
In order to resolve this issue, the server needs to let the browser know that cross origin requests are allowed. To do this, Django must respond to the preflight request with the Access-Control-Allow-Origin header specified. The header's value must be either be the website you are requesting from or "*" to allow any website.
//Any website
Access-Control-Allow-Origin: *
//Specific website
Access-Control-Allow-Origin: http://www.example.com
A resource makes a cross-origin HTTP request when it requests a
resource from a different domain than the one which the first resource
itself serves. For example, an HTML page served from
http://domain-a.com makes an src request for
http://domain-b.com/image.jpg. Many pages on the web today load
resources like CSS stylesheets, images and scripts from separate
domains.
For security reasons, browsers restrict cross-origin HTTP requests
initiated from within scripts. For example, XMLHttpRequest follows
the same-origin policy. So, a web application using XMLHttpRequest
could only make HTTP requests to its own domain. To improve web
applications, developers asked browser vendors to allow XMLHttpRequest
to make cross-domain requests
you can read more about CORS here .
Detailed explanation of how to setup CORS in Django ?
This is because of no provision in the REST API to handle Cross-Origin-Resource-Request (CORS). To enable it in the REST API, we need django-cors-headers as recommended in Django REST Framework documentation. The minimal settings required are as follows.
Step 0 - install django-cors-headers .
pip install django-cors-headers
Step 1 - In settings.py, add the following entry in INSTALLED_APPS tuple.
INSTALLED_APPS = (
'......',
'corsheaders',
'......'
)
Step 2 - In settings.py, add the following entries at the top of MIDDLEWARE_CLASSES tuple.
MIDDLEWARE_CLASSES = (
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
)
Step 3 - Add the following flag variable in settings.py
CORS_ORIGIN_ALLOW_ALL = True
you can read more about CORS in django here .
We are done !!

CORS error in AngularJS

When I am using Fiddler or any browser side HTTP client extension like Advanced Rest Client, I can get data from a API easily.
But when I try to use the same API from Angular JS, CORS issue appear immediately. I have tried with following lines to solve the problem in AngularJS, But unfortunately it did not work.
appd.config(function ($httpProvider) {
// $httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
// $httpProvider.defaults.headers.post['Accept'] = '*/*'
$httpProvider.defaults.useXDomain = true;
$httpProvider.defaults.withCredentials = true;
delete $httpProvider.defaults.headers.common["X-Requested-With"];
$httpProvider.defaults.headers.common["Accept"] = "*/*";
$httpProvider.defaults.headers.common["Content-Type"] = "application/x-www-form-urlencoded";
$httpProvider.defaults.headers.common['Authorization'] = 'Basic encodedpassword=';
});
I get following error in mozilla:
Cross-Origin Request Blocked:
The Same Origin Policy disallows reading the remote resource at http://host/training_webapi. This can be fixed by moving the resource to the same domain or enabling CORS.
And following in Chrome:
XMLHttpRequest cannot load http://host/training_webapi The request was redirected to 'http:host/training_webapi/', which is disallowed for cross-origin requests that require preflight.
The service you are requesting is not allowing CORS (no Access-Control are sent as part of the response).
You would need to include the header Access-Control-Allow-Origin: * as part of the response (which it does not).
See this : http://www.html5rocks.com/en/tutorials/cors/
You might be able to use $http.jsonp.
var url = "http://host/training_webapi?callback=JSON_CALLBACK";
$http.jsonp(url)
.success(function(data){
console.log(data.found);
});
Working JSFiddle
Another option (since you don't own the server), could be to proxy the request on your server and access that URI using angular.
One more point, in your code the content header is set to form:
$httpProvider.defaults.headers.common["Content-Type"] = "application/x-www-form-urlencoded";
Your request should be expecting
content-type: application/json

Categories

Resources