How do I fix CORS issue in Fetch API - javascript

I'm building a front-end only basic Weather App using reactjs. For API requests I'm using Fetch API.
In my app, I'm getting the current location from a simple API I found
and it gives the location as a JSON object. But when I request it through Fetch API, I'm getting this error.
Failed to load http://ip-api.com/json: Request header field Access-Control-Allow-Origin is not allowed by Access-Control-Allow-Headers in preflight response.
So I searched through and found multiple solutions to fix this.
Enabling CORS in Chrome solves the error but when I deploy the app on heroku, how can I access it through a mobile device without running into the same CORS issue.
I found an proxy API which enables the CORS requests. But as this is a location request, this gives me the location of the proxy server. So it's not a solution.
I've gone through this Stackoverflow question and added the headers to the header in my http request but it doesn't solve the problem. (Still it gives the same error).
So how can I solve the issue permanently ? What's the best solution I can use to solve the CORS issue for http requests in Fetch API ?

if you are making a post, put or patch request, you have to stringify your data with body: JSON.stringify(data)
fetch(URL,
{
method: "POST",
body: JSON.stringify(data),
mode: 'cors',
headers: {
'Content-Type': 'application/json',
}
}
).then(response => response.json())
.then(data => {
....
})
.catch((err) => {
....
})
});

To the countless future visitors:
If my original answer doesn't help you, you may have been looking for:
Trying to use fetch and pass in mode: no-cors
What is an opaque response, and what purpose does it serve?
Regarding the issue faced by the OP...
That API appears to be permissive, responding with Access-Control-Allow-Origin:*
I haven't figured out what is causing your problem, but I don't think it is simply the fetch API.
This worked fine for me in both Firefox and Chrome...
fetch('http://ip-api.com/json')
.then( response => response.json() )
.then( data => console.log(data) )

You should use the proxy solution, but pass it the IP of the client instead of the proxy. Here is an example URL format for the API you specified, using the IP of WikiMedia:
http://ip-api.com/json/208.80.152.201

Related

Enable Cross-Origin Requests (CORS) in POCO C++ Libraries

I'm building a C++ backend with heavy calculations that are meant to work as an JSON API for connecting clients. To accomplish this, I've used HTTPServer in Poco::Net from POCO C++ Libraries.
Unfortunately when building two different clients it turned out that a regular webpage (HTML+JS) can't use Fetch to communicate with the backend due to CORS error. My understanding is that they need to use the same localhost: and that's not the case when manually opening the HTML document on the computer that's also running the backend.
All I can come up with when searching is the generic advice that servers need to enable CORS and whitelist relevant domains. Unfortunately I can't find documentation on how to accomplish this. The only relevant result was an answer on a related question where he recommended the following:
response.set("Access-Control-Allow-Origin", "*");
Naturally whitelisting everything isn't recommended from a security point of view but the main goal here is to just get it running locally to continue the development. Unfortunately it seems to make no difference and the browser console still says:
Access to fetch at 'http://localhost:6363/' from origin 'null' 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.
Hovering the error in the Chrome Network tab I get the following:
Cross-Origin Resource Sharing error: PreflightMissingAllowOriginHeader
My current JavaScript call:
const data = { test: 'test' }
fetch('http://localhost:6363', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
})
.then(response => response.text())
.then(message => {
console.log('Data retrieved:', message);
})
.catch((error) => {
console.error('Error:', error);
});
Any suggestions on how to proceed?

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.

can't get api responce using fetch()

I am trying to get data using fetch() using browser console number of time but can't get.
for the cross browser issue I also use mode: no-cors but no solution I found .
please help me out I am fully in depressed now
the code that i already tried:
await fetch("https://api.sandbox.bigbuy.eu/rest/catalog/productsstock.json", {
method: "GET",
mode: 'no-cors',
headers: { Authorization: `Bearer XXXXXXXXXXXX` }
})
.then(response => response.json())
response is:
SyntaxError: Unexpected end of input
You said mode: 'no-cors' but you are making a cross-origin request.
You cannot read data across origins without permission from CORS.
By explicitly turning off CORS you are telling fetch to set the response to nothing and not raise errors for trying to read across origins without permission from CORS.
Change it to mode: 'cors'. Note that api.sandbox.bigbuy.eu will have to grant you permission to read the data.

Binance API and angular 4 httpClient

I have a question about cryptomarket Binance.
They have public api which I though I could use in angular to create trading app.
But I have some troubles.
Using that link in chrome I get json result.
https://api.binance.com/api/v1/exchangeInfo
But using with angular 4 httpClient:
this.http.get('https://api.binance.com/api/v1/exchangeInfo').subscribe(res => console.log(res));
I have error: Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at api.binance.com/api/v1/exchangeInfo. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing)
It doesn't work. I don't get it, why I can't use that API in angular app?https://github.com/binance-exchange/binance-official-api-docs/blob/master/rest-api.md
What should I do?
Should I set headers like that:
getMarkets() {
const headers = new HttpHeaders();
headers.set('Content-Type', 'application/json');
headers.set('Accept', 'application/json');
headers.set('Access-Control-Allow-Headers', 'Content-Type');
headers.set('Access-Control-Allow-Origin', '*');
const path = 'https://api.binance.com/api/v1/exchangeInfo';
return this.http.get(path, {headers: headers});
}
Thanks in advance
You can't quite use it directly like that, Binance API does not set CORS headers, so Chrome and all major browsers will block the requests.
There is a bit more to it, but essentially, the api servers that need to enable support for CORS should set Access-Control-Allow-Origin to be * or a single domain www.example.com, this allows the browsers to prevent malicious code on a site to call and read the response of some data from other site you might be logged on to ( eg: bank info )
You can read more about it here
One possible solution is to have your own server that proxies calls to binance
Another solution if you're testing things out is to use a CORS enabling extension like this one
Update: You can also use the websocket API if that satisfies your data needs docs
Update 2: Here's a good stackoverflow question on cors
Side note: If your bank's API server sets the Access-Control-Allow-Origin to * then change banks :)
Try this simple request without headers.
this.http.get('https://api.binance.com/api/v1/exchangeInfo').subscribe(data => {
this.results = data;
});
}
It work for me
HttpHeaders is immutable. So you must write
const headers = new HttpHeaders().
set('Content-Type', 'application/json').
set('Accept', 'application/json').
set('Access-Control-Allow-Headers', 'Content-Type').
set('Access-Control-Allow-Origin', '*');
or
const headers = new HttpHeaders(
{
Content-Type:'application/json'),
Accept:'application/json'),
Access-Control-Allow-Headers:'Content-Type'),
Access-Control-Allow-Origin:'*')
})

Cookie is not set automatically by the browser

I am trying to login by calling an API via a POST HTTP request.
post(
postLogin(email),
JSON.stringify({password: passwd}),
{ headers: { "Content-Type":"application/json" },
credentials: 'include' // i also tried with 'same-origin'
}
)
I am using Redux and React. In the API response, I receive the Set-Cookie header (I can see it in browser dev tools), but for some reason I cannot access it in my code and the browser doesn't set the cookie. I'm using Chrome Version 63.0.3239.84. It is a cross-origin request, so I have the following CORS headers set so I think it is not from here.
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:*
Access-Control-Allow-Methods:GET, OPTIONS
Access-Control-Allow-Origin:*
Do you have any suggestions or someone has this issue too? Thank you!
I have finally fixed it. The problem was that my application and the API were not in the same domain. I configure a local NGINX in order to have them under the same domain and it works fine.

Categories

Resources