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?
Related
How can I get data from a server with no 'Access-Control-Allow-Origin' ?
I can get an Opaque answer only.
Problem is that I need to call a public API on a server with no Access-Control-Allow-Origin - I can try to convince site owner to add it, but how do I do it in the meantime ? I am trying to not run a proxy on my own domain. The data is personal data (electric power consumption), which I want the browser to download and process, and I do not want my server to see the users private API key, which is stored in localStorage only. At some point I want to it to become a true web app.
Fetch with no-cors mode gives me Opaque data, and with cors enabled I get:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://api.eloverblik.dk/. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing)
Any other way to call an API / Get data from a 3rd party site on the web ?
Here is example code:
fetch( 'https://www.eloverblik.dk', { method: 'GET', redirect: 'follow'})
.then( (response) => { console.log('x'); console.log('Resp: ' + response.type) })
.then((result) => { console.log('Res: ' + result )})
.catch( (error) => { console.error('Error:', error); })
Thanks for the help here.
Basically, the answer is, that it is not possible.
The workaround is to use a reverse proxy like nginx and add the header.
I have contacted the site owner and asked them to add the header. It is a public available API, that requires login with an API key you can generate on a website.
They do run another api server, giving anonymous access to public data. That one is run on cloudapp.net. The one where they "forgot" the header has personal electricity consumption measurements - Down to 15m intervals. It is hosted under t-msedge.net. Hope they will do the change, so I can do away with the proxy.
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.
I'm trying to get an access token from Azure. I was following this tutorial, but the thing is that the guy's using postman. It works for me in postman as well, but it fails in javascript and I don't understand why.
function getAccessToken() {
fetch(`${loginUrl}${tenantId}/oauth2/token`, {
method: "POST",
body: JSON.stringify({
grant_type: "client_credentials",
client_id: clientId,
client_secret: clientSecret,
resource: resource,
})
})
.then((response) => {
console.log(JSON.stringify(response));
})
.catch((err) => {
console.log(JSON.stringify(err));
});
}
The credentials are good, i.e. the clientId, secret, tenantid etc.
I also tried in PowerShell and it worked:
Invoke-RestMethod `
-Uri "$loginUrl$tenantId/oauth2/token" `
-Method Post `
-Body #{"grant_type"="client_credentials"; "resource" = $resource; "client_id" = $clientId; "client_secret" = $clientSecret }
But on js I get the following error:
Access to fetch at 'https://login.microsoftonline.com/myTenantId/oauth2/token' from origin 'null' 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.
I'm running this script in an HTML file for testing purposes at the moment.
If we directly call the rest api from a domain different from your website in the HTML page, we will get CORS issue. This is for safety reasons. For more details, please refer to here.
So if you want to get Azure AD token in HTML page, I suggest you use package msaljs to implement implicit flow to get token. The package has fixed cors issue. Regarding how to do that, please refer to here.
Besides, if you still want to use client credentials flow to get token in your HTML page. You have two choices. One choice is to use proxy server. The proxy acts as an intermediary between a client and server. For future details about it, please refer to the blog.
I have this block of code that I'm testing to see if it'll send a tweet if it's button is clicked.
const onTweet = () => {
client.post('statuses/update', {status: 'Testing'})
.then(function (tweet) {
console.log(tweet);
})
.catch(function (error) {
console.log(error + " error")
});
}
However, every time I click on the button I get this exact error
Access to fetch at 'https://api.twitter.com/1.1/statuses/update.json' from origin 'http://localhost:1234' 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.
I've tried to research online to see how to fix it or work around it, but I don't think the solution I've found apply to my problem. For example, this post Access to fetch at from origin 'http://localhost:3000' has been blocked by CORS policy, says to set the mode to no cors but I don't think that applies to my problem since I'm not using CORS to post this tweet. This is in nodeJS and the backend was built with firebase and react router dom.
Also, if someone can link the official twitter api nodejs documentation I'd appreciate it. Haven't found it if there is any.
It looks like twitter API doesn't have CORS support . You may try workarounds like extensions or Postman/Curl etc as mentioned here -
https://stackoverflow.com/a/35898961/7895283
https://twittercommunity.com/t/will-twitter-api-support-cors-headers-soon/28276/6
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