Reputation: 1932
Note: It turns out that this had nothing to do with flutter and everything to do with the fact that I had set the API gateway to a Lambda Proxy
I am trying to hit an API endpoint from a Flutter web application, every time it errors out and gives me the following error.
Error getting sensor data: DioError [DioErrorType.RESPONSE]: XMLHttpRequest error.
I know there are several questions here on SO(like this and this) discussing this issue and the solution seems to be to enable CORS support on the server-side. I am using the AWS API gateway to build the API, I followed these instructions to enable CORS support from my API. Here are my CORS setting from the API gateway console.
The text in the "Access-Control-Allow-headers" is
'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'
Enabling CORS on the API gateway didn't seem to help, I am still getting the same error on my flutter web app when I try to hit an API.
The funny thing is, the API work perfectly fine if I hit the API from chrome (i.e. pasting the API URL on the browser and hitting enter). It only fails when I try to hit the API from the flutter web app.
Question: How do I enable CORS support in my API gateway so my flutter web app can use the API ?
Upvotes: 35
Views: 126304
Reputation: 191
Try this:
Go to flutter\bin\cache
and remove the file flutter_tools.stamp
Go to flutter\packages\flutter_tools\lib\src\web
and edit the file chrome.dart
:
Add '--disable-web-security'
next to '--disable-extensions'
line
Upvotes: 19
Reputation: 59
This worked for me:
flutter run -d chrome --web-browser-flag "--disable-web-security"
Upvotes: 4
Reputation: 644
This is a problem with both your backend and frontend. I encountered the error while adding an authentication header. You need to do two things.
Frontend
var request = await http.post(
Uri.parse(url),
headers: {
"auth-token": idToken, // whatever headers you need(I add auth)
"content-type": "application/json" // Specify content-type as JSON to prevent empty response body
},
body: jsonEncode(<String, String>{
'name': name,
'email': email,
})
Backend
const cors = require('cors'); //Setup CORS
app.use(cors({
origin: '*',
allowedHeaders: 'X-Requested-With, Content-Type, auth-token',
})); //Add authentication token header
app.use("/api/user", authRoute); // Flutter Web calls this endpoint
Upvotes: 4
Reputation: 11219
Spent 3 hours on this "XMLHttpRequest error"...
Probably obvious for many developers but in my situation I was making a CORS request from an https to an http endpoint.
If you want to make it work, on top of the other answers (enabling CORS, allowing origin *, add headers to the request) it is critical to have an https endpoint .
Full code of what made it work (using nginx, node express server and flutter web):
In nginx config file /etc/nginx/sites-available/mywebsite.com
add these lines in location
:
location / {
#ALLOW CORS#
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
#
# Custom headers and headers various browsers *should* be OK with but aren't
#
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
#
# Tell client that this pre-flight info is valid for 20 days
#
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}
if ($request_method = 'POST') {
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
}
if ($request_method = 'GET') {
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
}
#END OF ALLOW CORS#
try_files $uri $uri/ =404;
index.js
const app = express()
const cors = require('cors');
app.use(cors());
// usual stuff
(you need to install cors: npm install cors
in the backend directory)
server.js
const app = require('./index')
const fs = require('fs')
const https = require('https')
const port = process.env.PORT || 3000;
var options = {
key: fs.readFileSync('./certs/privkey.pem'),
cert: fs.readFileSync('./certs/fullchain.pem'),
};
var server = https.createServer(options, app).listen(port, function(){
console.log("Express server listening on port " + port);
});
Future<String> testRequest() async {
Uri uri =
Uri(scheme: 'https', port: 3000, host: 'mywebsite.com', path: 'folder'); // to reach this endpoint: 'https://mywebsite.com:3000/folder'
var headers = {
"Access-Control-Allow-Origin": "*",
'Content-Type': 'application/json',
'Accept': '*/*'
};
try {
http.Response response = await http.get(uri, headers: headers);
return response.body;
} catch (e) {
return inspect(e).toString();
}
}
NB: There is a custom path for the endpoint
So after adding the certificates and https to the backend it was finally working.
Upvotes: 1
Reputation: 19
This worked for me:
Step 1: npm install cors
After installing cors, define it
Step 2: const cors = require('cors')
Add the middleware to enable cors
Step 3: app.use(cors())
Upvotes: 0
Reputation: 380
Issue solved by using these steps....in my case:
I was using Nodejs for my backend. When I sent a post request from HTTP there was this error:"XMLHttpRequest error.".
1): Install this in node dependency link
npm install cors
step 3
then add get the ip by following step
Step 4 add in app/android studio
Upvotes: 0
Reputation: 1
If you dont have access to the server side, it is a good idea set up a reverse proxy. I used a nginx proxy with minimum configuration, running in a docker container.
docker-compose.yml:
version : '3'
services :
nginx:
image: nginx:latest
container_name: nginx_container
ports:
- 3000:3000
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
nginx.conf:
events {
}
http {
server {
listen 3000;
location / {
proxy_pass http://original_address_and_port/;
}
}
}
Then, you can develop using http://localhost:3000 as API base, and nginx will send requests do original address and port.
Upvotes: 0
Reputation: 94
Enable CORS in cpanel to enable CORS in your hosting account. you can enable it adding the following lines in the .htaccess file in your hosting account.
<IfModule mod_headers. ...
Header set Access-Control-Allow-Origin "*"
</IfModule>
Upvotes: 1
Reputation: 729
I was using Nodejs for my backend. When I sent a post request from Dio there was this error :"XMLHttpRequest error.".
Reason Behind this error: Suppose your flutter is running at localhost:5500 and nodejs server on localhost:3000. So, your browser fails to handle the request as they are running on different ports. That's we use CORS or Proxies to solve these problems.
Remember, this is a problem mainly associated with your browser. If you will use postman and send the same request, you will find everything working.
To solve this: I installed a NPM Package called CORS.
npm i cors
Then, start using it....
const cors = require("cors");
app.use(cors());
By just doing that your error will get resolved. And you don't need to add anything more.
Upvotes: 7
Reputation: 408
this worked for me, I added the below header on the lambda function
return {
statusCode: 200,
headers: {
"Access-Control-Allow-Origin": "*", // Required for CORS support to work
"Access-Control-Allow-Credentials": true, // Required for cookies, authorization headers with HTTPS
"Access-Control-Allow-Headers": "Origin,Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,locale",
"Access-Control-Allow-Methods": "POST, OPTIONS"
},
body: JSON.stringify(item)
};
Upvotes: 25
Reputation: 511786
My server was using nginx so I solved the problem by adding the following two lines to the server block of the sites-enabled config file for my API server:
add_header Access-Control-Allow-Origin "*";
add_header Access-Control-Allow-Methods "GET, HEAD";
My app only uses GET
and HEAD
so you may need to add other methods depending on your situation.
See also: How to Enable CORS in Apache and Nginx?
Upvotes: 5