35

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 ?

1

11 Answers 11

25

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)
};
Sign up to request clarification or add additional context in comments.

4 Comments

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. stackoverflow.com/q/61954922/998676
@RajaPeela would add that to the server response.
i have added headers in response of my lambda function but it doesn't help.
Making all http methods like put,get,delete into post resolved my issue
20

Try this:

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

  2. Go to flutter\packages\flutter_tools\lib\src\web and edit the file chrome.dart: Add '--disable-web-security' next to '--disable-extensions' line

2 Comments

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'
My question is that since we are solving the problem by disabling web security on our test chrome, wouldn't the problem appear after deploying the output on a server again?
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.

Comments

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?

Comments

5

This worked for me:

flutter run -d chrome --web-browser-flag "--disable-web-security"

3 Comments

Disabling security shouldn't be an answer
Knowledge is power. Disabling security is handy if you know what you're doing.
Nothing worked, except this solution. Thanks man, I can go and sleep now.
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

Comments

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>

​ ​

Comments

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.

Comments

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.

Comments

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

Comments

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.