req method

Future req(
  1. String path, {
  2. String method = "GET",
  3. dynamic body,
  4. Map<String, String>? headers,
  5. Map<String, String>? context,
  6. bool skipDecode = false,
})

Implementation

Future<dynamic> req(String path,
    {String method = "GET",
    dynamic body,
    Map<String, String>? headers,
    Map<String, String>? context,
    bool skipDecode = false}) async {
  print("Running $method $path");

  http.Response res;

  var _ctx = <String, String?>{};
  headers ??= {};

  _ctx["_ctx[l]"] = Intl.defaultLocale;
  _ctx["_ctx[t]"] = DateTime.now().timeZoneName; // grab timezone name...?

  if (context != null) {
    context.forEach((k, v) => _ctx["_ctx[" + k + "]"] = v);
  }
  if ((method == "GET") && (body != null)) {
    _ctx["_"] = json.encode(body);
  }

  if (cookies.isNotEmpty) {
    headers['cookie'] = _generateCookieHeader();
  }
  headers["Sec-ClientId"] = appId;

  Uri urlPath = Uri.parse(prefix + path);
  urlPath = Uri(
      scheme: urlPath.scheme,
      host: urlPath.host,
      path: urlPath.path,
      queryParameters: _ctx);

  switch (method) {
    case "GET":
      print("API GET request: $urlPath");
      try {
        res = await http.get(urlPath, headers: headers);
      } on http.ClientException catch(e) {
        if (e.message == "Failed to parse header value") {
          // [ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: Failed to parse header value
          // See: https://github.com/dart-lang/sdk/issues/46442
          // Flutter does not handle properly Bearer auth failure and will return a crap error. Our token is shit.
          if (!headers.containsKey("Authorization")) {
            throw e;
          }
          expiresV = 0; // mark token as expired.
          // retry
          headers["Authorization"] = "Bearer " + await token();
          res = await http.get(urlPath, headers: headers);
        }
        throw e; // no idea
      }
      break;
    case "POST":
      if (body != null) {
        headers["Content-Type"] = "application/json";
        body = json.encode(body);
      }

      try {
        res = await http.post(urlPath, body: body, headers: headers);
      } on http.ClientException catch(e) {
        if (e.message == "Failed to parse header value") {
          // [ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: Failed to parse header value
          // See: https://github.com/dart-lang/sdk/issues/46442
          // Flutter does not handle properly Bearer auth failure and will return a crap error. Our token is shit.
          if (!headers.containsKey("Authorization")) {
            throw e;
          }
          expiresV = 0; // mark token as expired.
          // retry
          headers["Authorization"] = "Bearer " + await token();
          res = await http.post(urlPath, body: body, headers: headers);
        }
        throw e; // no idea
      }
      break;
    default:
      var req = http.Request(method, urlPath);
      headers.forEach((String k, String v) {
        req.headers[k] = v;
      });
      if (body != null) {
        req.body = json.encode(body);
        req.headers["Content-Type"] = "application/json";
      }

      try {
        var stream = await http.Client().send(req);
        res = await http.Response.fromStream(stream);
      } on http.ClientException catch(e) {
        if (e.message == "Failed to parse header value") {
          // [ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: Failed to parse header value
          // See: https://github.com/dart-lang/sdk/issues/46442
          // Flutter does not handle properly Bearer auth failure and will return a crap error. Our token is shit.
          if (!req.headers.containsKey("Authorization")) {
            throw e;
          }
          expiresV = 0; // mark token as expired.
          // retry
          req.headers["Authorization"] = "Bearer " + await token();
          var stream = await http.Client().send(req);
          res = await http.Response.fromStream(stream);
        }
        throw e; // no idea
      }
  }

  _updateCookie(res);

  if (res.statusCode >= 300) {
    // something is wrong

    // check if response is json
    String ct = res.headers["content-type"]!;
    int idx = ct.indexOf(';');
    if (idx > 0) {
      ct = ct.substring(0, idx);
    }
    if (ct == "application/json") {
      // this is a platform error
      var d = json.decode(res.body);
      print("Got error: ${res.body}");
      if (d.containsKey("token")) {
        switch (d["token"]) {
          case "error_invalid_oauth_refresh_token":
            // this is actually a login exception, the refresh token is not valid, void it
          print("got invalid token error, voiding token");
            await voidToken();
            throw new AtOnlineLoginException(d.error);
        }
      }
      throw new AtOnlinePlatformException(d);
    }
    print("Error from API: ${res.body}");
    throw new AtOnlineNetworkException(
        "invalid response from api ${res.statusCode} ${res.body}");
  }

  var d = json.decode(res.body);

  if (skipDecode) {
    return d;
  }

  if (d["result"] != "success") {
    print("Got error: $d");
    throw AtOnlinePlatformException(d);
  }

  return AtOnlineApiResult(d);
}