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.