XMLHttpRequest error in flutter web [Enabling CORS AWS API gateway]
Asked Answered
C

11

32

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.

enter image description here

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 ?

Cathode answered 12/2, 2020 at 15:26 Comment(1)
This solves disabling web security when running on flutter chrome local dev launch: https://mcmap.net/q/165796/-how-to-solve-flutter-web-api-cors-error-only-with-dart-codeWhilst
V
23

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)
};
Venetis answered 27/3, 2020 at 18:17 Comment(4)
Please add complete code snippet where we need to this, Client-side, or API side? If server-side I have already added in my API. https://mcmap.net/q/454711/-flutter-chopper-post-api-not-working-in-web/998676Softa
@RajaPeela would add that to the server response.Cathode
i have added headers in response of my lambda function but it doesn't help.Dahlberg
Making all http methods like put,get,delete into post resolved my issueAvril
G
13

Try

  • Go to flutter\bin\cache and remove flutter_tools.stamp file

  • Go to flutter\packages\flutter_tools\lib\src\web open file chrome.dart and edit it Add '--disable-web-security' next to '--disable-extensions' line

Galloway answered 6/12, 2022 at 4:53 Comment(1)
Just to add to the above answer, due to recent update in chrome, we need to comment out --disable-extensions' and add '--disable-web-security'Tussock
G
7

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.

Gentlefolk answered 30/6, 2021 at 7:7 Comment(0)
B
5

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?

Bossuet answered 23/1, 2021 at 11:28 Comment(0)
R
4

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.

  1. Specify the content-type as json in your Flutter frontend.
  2. Allow CORS in your Node backend.


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

Remindful answered 5/4, 2022 at 17:44 Comment(0)
A
1

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>

​ ​

Aronson answered 11/7, 2021 at 12:4 Comment(0)
C
1

Forgot to have an https endpoint

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):

Server


Nginx

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;
    

Backend

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);
});

Flutter client app:

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.

Coltson answered 16/11, 2022 at 15:28 Comment(0)
E
1

This worked for me:

flutter run -d chrome --web-browser-flag "--disable-web-security"
Espy answered 28/3 at 11:25 Comment(3)
Disabling security shouldn't be an answerShipley
Knowledge is power. Disabling security is handy if you know what you're doing.Parmenter
Nothing worked, except this solution. Thanks man, I can go and sleep now.Sauers
S
0

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.

Snuffle answered 21/4, 2022 at 18:5 Comment(0)
K
0

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

2 step: code line enter image description here

step 3 then add get the ip by following step enter image description here

Step 4 add in app/android studio enter image description here

Kassab answered 5/10, 2022 at 10:8 Comment(0)
S
0

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())
Stoop answered 14/11, 2022 at 17:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.