Search code examples
flutterhttpdarthttp-headersdio

Dio error, disappears when web security is disabled


So I need ASAP to do a request to the Google Places API using Dart for a flutter web app. I am using Dio I found some answers, which said that XMLHttpRequest Error would disappear if I added headers. I added the headers and the problem persists. I received some help from a Software Engineer (I'm a newbie), and although he was unfamiliar with Dio, he edited a file in the flutter SDK which disabled security with the flag --disable---web-security

path: C:\flutter\packages\flutter_tools\lib\src\web file: chrome.dart
(Here I only added the code block changed from the file)

final int port = debugPort ?? await _operatingSystemUtils.findFreePort();
final List<String> args = <String>[
  chromeExecutable,
  // Using a tmp directory ensures that a new instance of chrome launches
  // allowing for the remote debug port to be enabled.
  '--user-data-dir=${userDataDir.path}',
  '--remote-debugging-port=$port',
  // When the DevTools has focus we don't want to slow down the application.
  '--disable-background-timer-throttling',
  // Since we are using a temp profile, disable features that slow the
  // Chrome launch.
  '--disable-extensions',
  '--disable-popup-blocking',
  '--bwsi',
  '--no-first-run',
  '--no-default-browser-check',
  '--disable-default-apps',
  '--disable-translate',
  '--disable-web-security', //the line added
  if (headless) ...<String>[
    '--headless',
    '--disable-gpu',
    '--no-sandbox',
    '--window-size=2400,1800',
  ],
  url,
];

Once web security was disabled, Dio worked fine, with the API. The request is executed and returns with a 200 according to the DevTools console but then security blocks it off. So my question is what header am I missing, or what should I add to the Dio() object in order to re-activate web security and be able to make requests.

Dio request to Places API

try {
  var dio = Dio();
  dio.options.headers["Access-Control-Allow-Credentials"] = "true";
  dio.options.headers["Access-Control-Allow-Headers"] =
      "Origin,Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,locale";
  dio.options.headers["Access-Control-Allow-Origin"] = "*";
  dio.options.headers["Access-Control-Allow-Methods"] =
      "GET, HEAD, POST, OPTIONS";

  dio.options.responseType = ResponseType.json;
  String url =
      autocompleteUrl(search, sessionToken, locale, components, placeType);
  //print(url);
  var response = await dio.get(url);

  var json = convert.jsonDecode(response.data);

  var jsonResults = json[_f.predictions] as List;

  return jsonResults.map((p) => PlaceSearch.fromMap(p)).toList(); //modeling the response
} on DioError catch (e) {
  return null;
}

Thank you for taking the time to help.

EDIT:

When I would print the error data this would show up

request : null
message : XMLHttpRequest error.
DioError [DioErrorType.RESPONSE]: XMLHttpRequest error.

Error in DevTools:
Access to XMLHttpRequest at 'https://maps.googleapis.com/maps/api/place/autocomplete/json?input=a&key=keyg&sessionToken=e1f7496d-a62e-437d-877d-d93e5045e22d&language=null&components=country:us&types=address' from origin 'http://localhost:49234' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.


Solution

  • The same-origin policy causing the error only happens when the request is from client to server not from server to server. So I created a cloud function that makes the request and returns the response. Below is the function in typescript

    import axios from "axios";
    
    export const serverRequest = functions.https.onCall(async (url, context)=> {
      isAuthenticatedAdmin(context);
      const response = await axios.get(url as string).then(({data})=> data);
      return response;
    });