Search code examples
darthttpserverflutter-web

(XMLHttpRequest error) Problem with serverside CORS policy


I created a flutter project with a web version and we already have a server for database access that another android/ios app uses. However the web version of the new app is running into problems with cors policy. I've been trying to solve this looking at other stock overflow questions and searching on google without success and was hoping someone can help me figure out what I might be doing wrong.

I've tested making the uri client side both with:

String url = "https://" + host + ":" + port;
Uri uri = Uri.parse(url + "/test");

and

String url = host + ":" + port;
Uri uri = Uri.https(url, "/test");

I then call the server using the http/http package:

Response response = await get(uri).timeout(const Duration(seconds: 17));

As for the structure of the server side code:

const createError = require('http-errors');
const express = require('express');
const path = require('path');
const cookieParser = require('cookie-parser');
const logger = require('morgan');
const https = require('https');

const routerOne = require('./path/to/router/file');
const routerTwo = require('./path/to/router/file');

const dotenv = require('dotenv');
const fs = require("fs");
dotenv.config();

console.log('port' + process.env.PORT);

var key = fs.readFileSync('./certs/key.key');
var cert = fs.readFileSync('./certs/cert.crt');

var options = {
    key: key,
    cert: cert
};

const cors = require('cors');
const app = express();
app.use(cors());

try {
    let server = https.createServer(options, app);
    server.listen(process.env.PORT, () => {
        console.log('Started https server on port ' + process.env.PORT);
    });
} catch (err) {
    console.log(err);
}

app.get('/test', cors(), function (req, res, next) {
  res.json({msg: "This is CORS-enabled for all origins!"})
})

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({limit: '50mb', extended: false}));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/router/one', routerOne);
app.use('/router/two', routerTwo);

// catch 404 and forward to error handler
app.use(function (req, res, next) {
    next(createError(404));
});

// error handler
app.use(function (err, req, res, next) {
    console.log(err);
    // set locals, only providing error in development
    res.locals.message = err.message;
    res.locals.error = req.app.get('env') === 'development' ? err : {};

    // render the error page
    res.status(err.status || 500);
    res.render('error');
});

module.exports = app;

Unlike android when running web version(Chrome or Edge), I have been unable to get the response from the newly added '/test' on the server side. I'm hoping for some suggestion for how I can get the cors policy to work.

Client side I've tried using Uri.https instead of Uri.parse and I added headers as well. On the server I tried to follow instructions on how to add cors policy to node.js/express.

Error message from flutter:

Error: XMLHttpRequest error.
    C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart 963:28                get current
packages/http/src/browser_client.dart 69:22                                                                                    <fn>
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/zone.dart 1685:54                                              runUnary
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/future_impl.dart 147:18                                        handleValue
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/future_impl.dart 766:44                                        handleValueCallback
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/future_impl.dart 795:13                                        _propagateToListeners
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/future_impl.dart 557:7                                         [_complete]
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/stream_pipe.dart 61:11                                         _cancelAndValue
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/stream.dart 1530:7                                             <fn>
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 334:14  _checkAndCall
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 339:39  dcall
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/html/dart2js/html_dart2js.dart 37309:58                              <fn>


    at Object.createErrorWithStack (http://localhost:59072/dart_sdk.js:5093:12)
    at Error._throw (http://localhost:59072/dart_sdk.js:20399:18)
    at Error.throwWithStackTrace (http://localhost:59072/dart_sdk.js:20396:18)
    at async._AsyncCallbackEntry.new.callback (http://localhost:59072/dart_sdk.js:40921:18)
    at Object._microtaskLoop (http://localhost:59072/dart_sdk.js:40778:13)
    at _startMicrotaskLoop (http://localhost:59072/dart_sdk.js:40784:13)
    at http://localhost:59072/dart_sdk.js:36261:9

Image of browser: image of browser with network tab


Update Solution

The answer from Ber is correct. This is a problem with certificate. Self signed certificate was being used on our server and by getting a new certificate using Let's encrypt the problem got solved. If anyone else runs into the "XMLHttpRequest error" they may also want to check out the error output in the browser as the "net::ERR_CERT_AUTHORITY_INVALID" was not shown in flutter.


Solution

  • The error code in your screen shot is net::ERR_CERT_AUTHORITY_INVALID meaning the server's SSL certificate is expired, invalid for the domain or not accepted by the root certificates in your app.