Search code examples
jsonflutterdartxmlhttprequest

How to fix XMLHttpRequest (CORS) exceptions on Flutter web projects


My problem

Finally, I found the errors in my project and not related to null variables and were related to XMLHttpRequest (CORS) on Flutter web projects that I thought related to null variables. however, I decided to change my title topic and say what problem exists

My Json :

{
    "success": true,
    "status_code": 200,
    "error": null,
    "data": {
        "message": "sussecc!",
        "has_paginate": 0,
        "results": {
            "user": {
                "id": 1,
                "full_name": "emin",
                "phone_number": "+1125585",
                "admin_role": "0",
                "national_id": "21",
                "address": null,
                "is_active": "1",
                "email": null,
                "email_verified_at": "2023-12-04 20:41:41",
                "created_at": "2023-12-04T17:11:42.000000Z",
                "updated_at": "2023-12-04T17:11:42.000000Z"
            },
            "token": "31|ssasdsdfsdgeedewfsdvfdbdfve3svxfb"
        }
    }
}

My Model Class :

class ModelLoginService {
  ModelLoginService({
    required this.success,
    required this.statusCode,
    required this.error,
    required this.data,
  });
  late final bool success;
  late final int statusCode;
  late final dynamic? error;
  late final Data? data;

  ModelLoginService.fromJson(Map<String, dynamic> json) {
    success = json['success'];
    statusCode = json['status_code'];
    error = Error.fromJson(json['error']);
    data = Data.fromJson(json['data']);
  }

  Map<String, dynamic> toJson() {
    final _data = <String, dynamic>{};
    _data['success'] = success;
    _data['status_code'] = statusCode;
    _data['error'] = error!.toJson() == null ? null : error.toJson();
    _data['data'] = data!.toJson() == null ? null : error.toJson();
    return _data;
  }
}

class Error {
  Error({
    required this.message,
    required this.errors,
  });
  late final String? message;
  late final Errors? errors;

  Error.fromJson(Map<String, dynamic> json) {
    message = json['message'];
    errors = Errors.fromJson(json['errors']);
  }

  Map<String, dynamic> toJson() {
    final _data = <String, dynamic>{};
    _data['message'] = message!;
    _data['errors'] = errors!.toJson().isEmpty;
    return _data;
  }
}

class Errors {
  Errors({
    required this.reason,
    required this.message,
  });
  late final String reason;
  late final String message;

  Errors.fromJson(Map<String, dynamic> json) {
    reason = json['reason'];
    message = json['message'];
  }

  Map<String, dynamic> toJson() {
    final _data = <String, dynamic>{};
    _data['reason'] = reason;
    _data['message'] = message;
    return _data;
  }
}

class Data {
  Data({
    required this.message,
    required this.hasPaginate,
    required this.results,
  });
  late final String message;
  late final int hasPaginate;
  late final Results results;

  Data.fromJson(Map<String, dynamic> json) {
    message = json['message'];
    hasPaginate = json['has_paginate'];
    results = Results.fromJson(json['results']);
  }

  Map<String, dynamic> toJson() {
    final _data = <String, dynamic>{};
    _data['message'] = message;
    _data['has_paginate'] = hasPaginate;
    _data['results'] = results.toJson();
    return _data;
  }
}

class Results {
  Results({
    required this.user,
    required this.token,
  });
  late final User user;
  late final String token;

  Results.fromJson(Map<String, dynamic> json) {
    user = User.fromJson(json['user']);
    token = json['token'];
  }

  Map<String, dynamic> toJson() {
    final _data = <String, dynamic>{};
    _data['user'] = user.toJson();
    _data['token'] = token;
    return _data;
  }
}

class User {
  User({
    required this.id,
    required this.fullName,
    required this.phoneNumber,
    required this.adminRole,
    required this.nationalId,
    required this.address,
    required this.isActive,
    required this.email,
    required this.emailVerifiedAt,
    required this.createdAt,
    required this.updatedAt,
  });
  late final int id;
  late final String fullName;
  late final String phoneNumber;
  late final String adminRole;
  late final String nationalId;
  late final String? address;
  late final String isActive;
  late final String? email;
  late final String emailVerifiedAt;
  late final String createdAt;
  late final String updatedAt;

  User.fromJson(Map<String, dynamic> json) {
    id = json['id'];
    fullName = json['full_name'];
    phoneNumber = json['phone_number'];
    adminRole = json['admin_role'];
    nationalId = json['national_id'];
    address = json['address'] == null ? null : json['address'];
    isActive = json['is_active'];
    email = json['email'] == null ? null : json['email'];
    emailVerifiedAt = json['email_verified_at'];
    createdAt = json['created_at'];
    updatedAt = json['updated_at'];
  }

  Map<String, dynamic> toJson() {
    final _data = <String, dynamic>{};
    _data['id'] = id;
    _data['full_name'] = fullName;
    _data['phone_number'] = phoneNumber;
    _data['admin_role'] = adminRole;
    _data['national_id'] = nationalId;
    _data['address'] = address;
    _data['is_active'] = isActive;
    _data['email'] = email;
    _data['email_verified_at'] = emailVerifiedAt;
    _data['created_at'] = createdAt;
    _data['updated_at'] = updatedAt;
    return _data;
  }
}

My service for get JSON

class ServiceLogin extends GetConnect implements GetxService {
  Map<String, String> authorizationh = {};
  Map<String, dynamic> bodyMap = {};
  String username = "", password = "";

  Future<ModelLoginService> postData() async {
    bodyMap = {
      'full_name': 'admin',
      'password': 'c1992885',
    };

    var response = await post('http://test.com/admin/api/login', bodyMap);

    print('response.body ${response.body}');
    return ModelLoginService.fromJson(response.body);
  }
}

Error Log

Performing hot restart...
Waiting for connection from debug service on Edge...
Restarted application in 743ms.
[GETX] Instance "GetMaterialController" has been created
[GETX] Instance "GetMaterialController" has been initialized
[GETX] Instance "ApiController" has been created
[GETX] Instance "ApiController" has been initialized
response.body null
Error: Expected a value of type 'Map<String, dynamic>', but got one of type 'Null'
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 294:3       throw_
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 127:3       castError
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 818:12  cast
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/classes.dart 652:14     as_C
packages/shndz_panel/services/service_login.dart 21:30                            postData
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 45:50                <fn>
dart-sdk/lib/async/zone.dart 1661:54                                              runUnary
dart-sdk/lib/async/future_impl.dart 162:18                                        handleValue
dart-sdk/lib/async/future_impl.dart 846:44                                        handleValueCallback
dart-sdk/lib/async/future_impl.dart 875:13                                        _propagateToListeners
dart-sdk/lib/async/future_impl.dart 655:5                                         [_completeError]
dart-sdk/lib/async/future_impl.dart 745:7                                         callback
dart-sdk/lib/async/schedule_microtask.dart 40:11                                  _microtaskLoop
dart-sdk/lib/async/schedule_microtask.dart 49:5                                   _startMicrotaskLoop
dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 181:7                <fn>

I used nullable type in flutter in my model and expected this problem not to occur and i can't find the best way to solve it


Solution

  • This is the main problem that was preventing API calls in Web Flutter. so I finally found on search and set an answer in my topic

    XMLHttpRequest (CORS) exception on every flutter web

    I've spent time on it and did research. The issue is there and needs highlighting. A lot of people are facing this issue it can be verified upon doing a single search on Google and there's no solution to it directly within Flutter.

    The CORS problem can be resolved only if I am the developer of the API. I can add CORS configuration to it or the server and it'll work fine in Flutter Web but upon using 3rd party API it keeps on giving errors that can't be resolved. I've tried multiple publicly available APIs.

    The only way I found out is to make middleware API of the 3rd party API, add CORS configuration to it, and then use it in Flutter Web but instead of all this process shouldn't Flutter Web directly able to manage all of these hassles?