Can't fetch data with fetch API - javascript

I can't get the fetch() API to work. I get the strong feeling I'm doing something incorrectly.
I have a simple express server running on PORT 3005, which return data in json format, and a react.js client running on PORT 3000.
I'm using fetch() to make a GET request to http://localhost:3005/api but am getting these messages on the console
Cross-Origin Request Blocked: The Same Origin Policy disallows reading
the remote resource at http://localhost:3005/api.
(Reason: CORS header ‘Access-Control-Allow-Origin’ missing).
TypeError: NetworkError when attempting to fetch resource.
I added a header and read through similar questions but I still can't get it to work, and I'm still getting the same messages.
What am I doing wrong? (Here's the code)
let url = 'http://localhost:3005/api';
fetch(url, {
method: 'GET',
headers:{
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Credentials':true,
'Access-Control-Allow-Methods':'POST, GET'
}
}).then(response => response.json)
.then(data => console.log(data))
I've run into this issue several times in the past, and usually just use axios. But this time, I want to get fetch() to work...!

Your server endpoint needs to support the Access-Control-Allow-Origin Header, not just the client.
The general flow is:
The client is doing a pre-flight request to check if the requested cors policy is supported by the server.
The server receives the pre-flight and answers with the right header when it deems the request allowed.
The client receives the answer and by the included headers knows if it is allowed the actual request.
(In your case) When the Header is not returned by the server, the browser will not allow the actual call and give the error you are experiencing.
So in order to solve it you need to modify the server code to return the correct Header for the preflight request.
Also see this stackoverflow answer.
See this link. Specifically look at the section about Preflight Requests.

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.

PayPal node sdk causing CORs error "Redirect is not allowed for a preflight request" even after enabling headers

I'm trying to redirect using a POST request handled by nodejs backend with the following headers:
'Content-Type': 'application/json',
'Accept': 'application/json'
We want to redirect the customer to the Paypal payment link using res.redirect on the server side. However we experience the cors error:
Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request.
Originally, we had a CORs issue that stated that
Access to fetch at *** from origin *** has been blocked by CORS policy: No 'Access-Control-Allow-Origin'
However, now our error relates to the preflight request. We have tried changing the headers (which fixed the previous issue) however it is essential that we keep the application/json header (on the client side) as this is our method of sending basket (item ID and quantity) to the backend to be verified before redirecting to the payment page. We think that this could be an issue with the fact that this is a POST request not allowing information from the body to be sent back and then going ahead with a redirect. We have gone on basically every similar thread trying to resolve this problem without any luck.
Any help would be appreciated.

CORS issue when calling a localhost API hosted on one port from another port

I have a localhost Rest API POST query hosted using Docker at port 8501: http://localhost:8501/v1/models/model:predict. I have an HTML file which runs with a JavaScript script and it is hosted at http://127.0.0.1:8887/ using WebServer for Chrome. I am able to call global Rest API POST queries from my HTML-JS files and my local Rest API works fine from POSTMAN. But I am unable to call my API from my HTML-JS files.
Below is my JS file:
function foo() {
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
myHeaders.append("Access-Control-Allow-Origin", "*");
myHeaders.append("Access-Control-Allow-Methods", "POST");
var raw = JSON.stringify({"instances":[[0]]});
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: raw,
redirect: 'follow'
};
fetch("http://localhost:8501/v1/models/model:predict", requestOptions)
.then(response => console.log(response.text()))
.then(result => console.log(result))
.catch(error => console.log('error', error));
}
I get the below error:
Access to fetch at
'http://localhost:8501/v1/models/model:predict' from origin
'http://127.0.0.1:8887' 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.
Can anyone please help me?
You seem to have understood CORS slightly "backwards" -- the Access-Control-Allow-Origin and Access-Control-Allow-Methods headers are specified on HTTP responses, not requests. This obviously implies that it's the HTTP server that sets them, not the client.
It would make for a terrible cross site security model if a script of arbitrary origin could effectively dictate to the HTTP server what kind of requests and from which origins the latter must accept.
It's the HTTP service that ultimately controls access by specifying appropriate headers in the responses it serves, and the user agent validates the cross origin request where it refuses to proceed if the server didn't indicate it allows requests from the different origin the script was served from -- the response will be discarded and an error will be thrown.
In short, you need to add the headers to the responses your REST service at localhost:8501 generates, instead of specifying them for requests your client side script creates where they don't do anything.
Your server is missing header Access-Control-Allow-Origin in response, as it is responsible what to allow or not. See https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

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.

'Access-Control-Allow-Origin' error when getting data from the API with Axios (React)

I'm getting an a "XMLHttpRequest cannot load https://example.com. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8000' is therefore not allowed access."
This is my componenDidMount(), and I'm using axios to get the data from my API.
componentDidMount() {
this.serverRequest = axios.get(this.props.source).then(event =>{
this.setState({
title: event.data[0].name
});
});
}
I'm using "python -m SimpleHTTPServer" on the terminal, to run 'http://localhost:8000'.
I'm using the Chrome browser, and if I turn on the Chrome CORS plugin (to enable cross origin resource sharing), the app works, and I see data displayed from the API on the DOM. But I know that using the CORS plugin is bad, so how should I fix the 'Access-Control-Allow-Origin' error officially?
With Axios, can I somehow add dataType: "jsonp", if that would fix it?
This is a restriction made by the browser for security reasons when you try to access content in some domain from another domain. You overcome this, you need to set the following in your header
Access-Control-Request-Method
Access-Control-Request-Headers
Many sites restrict CORS. The best way to achieve your goal is to make your python server as a proxy. See the example.
//Request from the client/browser
http://localhost:8000/loadsite?q=https%3A%2F%2Fexample.com
//In your server
1. Handle the request
2. Get the query param(url of the website)
3. Fetch it using your python server
4. Return the fetching data to the client.
This should work.

Categories

Resources