Noldy Nayoan
Noldy Nayoan

Reputation: 127

Flutter Web Firebase Hosting XMLHttpRequest error (no error using local chrome browser (debug), or using Firefox)

I wrote a Flutter web application that connects via http to Firebase Cloud Functions api. I runs with no error in debug mode (run using flutter -d chrome). However when I deployed the web application to Firebase Hosting and open the result homepage in Chrome, I get the following error when requesting http.get method :

Exception : XMLHttpRequest error

But i I open the homepage in Firefox there is no error and the cloud function returns data. I know from several sources that we can disable Chrome security to get rid of this error, but this is not accepted because ordinary users may just think that the web site is not working.

In my serverside code I use Express and have enable CORS (as I found several tips about the error is related to CORS) :

const app = require("express")();
const cors = require("cors")({ origin: true});

In my firebase project \Authentication\Sign-in method\Authorized domain, I see the generated flutter web app domain myproject.firebaseapp.com is listed, so it is whitelisted.

I have spent hours looking for solutions, but no luck so far. Anyone can help?

Upvotes: 3

Views: 2256

Answers (1)

Noldy Nayoan
Noldy Nayoan

Reputation: 127

Well, never mind no answer from the experts. I have found a working solution.

  1. First I don't use 'cors' package anymore.
  2. I created a function middleware to handle CORS. So my server side index.ts file is like this :
const app = require("express")()
const whitelist = ['https://mysite1.com', 
                   'https://mysite2.web.app', 
                   'http://localhost', 
                   'https://us-central1-mysite2.cloudfunctions.net'] // replace with your domain whitelist

// MIDDLEWARE IF NOT USING cors package 
app.use(function (req, res, next) {
  const origin : string = req.headers.origin?? ""

  if (whitelist.indexOf(origin) !== -1) {
    res.setHeader('Access-Control-Allow-Origin', origin);
  } else {
    res.setHeader('Access-Control-Allow-Origin', '*') // Allow all origin, may be removed if all request must be from whitelisted domain
  }

  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
  res.setHeader('Access-Control-Allow-Headers', 'Access-Control-Allow-Origin, Access-Control-Allow-Methods, Access-Control-Request-Method, Access-Control-Request-Headers, Access-Control-Allow-Headers,Origin, X-Requested-With, Content-Type, Accept, Authorization')

  res.setHeader('Access-Control-Allow-Credentials', true)
  if (req.method === "OPTIONS") {
    return res.status(200).json({})
  }
  next()
})

// api
app.get("/login", playerAuth.login)

That's it. Now my api can be called from Chrome/Firefox/Postman and from my Flutter app. I was a little bit frustated, but with some patience and help from some articles I finally find the solution.

I hope this solution will help somebody who is also struggling with the CORS problem.

Upvotes: 2

Related Questions