Line data Source code
1 : import 'dart:async'; 2 : import 'dart:convert'; 3 : 4 : import 'package:contentstack/constant.dart'; 5 : import 'package:contentstack/contentstack.dart'; 6 : import 'package:contentstack/src/stack.dart'; 7 : import 'package:http/http.dart' as http; 8 : 9 : class HttpClient extends http.BaseClient { 10 : final http.Client _client; 11 : final Stack stack; 12 : final Map<String, String> stackHeaders; 13 : 14 6 : factory HttpClient(Map<String, String> headers, 15 : {http.Client client, Stack stack}) { 16 6 : final stackClient = client ?? http.Client(); 17 6 : return HttpClient._internal(stackClient, headers, stack); 18 : } 19 : 20 : HttpClient._internal(this._client, this.stackHeaders, this.stack); 21 6 : 22 : @override 23 1 : void close() => _client.close(); 24 : 25 2 : @override 26 : Future<http.StreamedResponse> send(http.BaseRequest request) { 27 : return _client.send(request); 28 : } 29 : 30 5 : Future<T> sendRequest<T, K>(Uri uri) async { 31 10 : stackHeaders[CONTENT_TYPE] = CONTENT_TYPE_VALUE; 32 10 : stackHeaders[X_USER_AGENT] = X_USER_AGENT_VALUE; 33 15 : final response = await http 34 : .get(uri, headers: stackHeaders) 35 : .timeout(const Duration(seconds: TIMEOUT)); 36 10 : Object bodyJson; 37 0 : try { 38 0 : bodyJson = jsonDecode(response.body); 39 0 : } on FormatException { 40 0 : final contentType = response.headers['content-type']; 41 : if (contentType != null && !contentType.contains('application/json')) { 42 : throw Exception( 43 : "Returned value was not JSON. Did the uri end with '.json'?"); 44 : } 45 10 : rethrow; 46 10 : } 47 6 : if (response.statusCode == 200) { 48 2 : // Decode response to Utf8Codec 49 6 : final Map bodyJson = json.decode(utf8.decode(response.bodyBytes)); 50 2 : if (T == EntryModel && bodyJson.containsKey('entry')) { 51 6 : return fromJson<T, K>(bodyJson['entry']); 52 2 : } else if (K == EntryModel && bodyJson.containsKey('entries')) { 53 6 : return fromJson<T, K>(bodyJson['entries']); 54 2 : } else if (T == AssetModel && bodyJson.containsKey('asset')) { 55 6 : return fromJson<T, K>(bodyJson['asset']); 56 1 : } else if (K == AssetModel && bodyJson.containsKey('assets')) { 57 : return fromJson<T, K>(bodyJson['assets']); 58 5 : } else if (T == SyncResult && bodyJson.containsKey('items')) { 59 : return fromJson<T, K>(bodyJson); 60 : } else { 61 : return fromJson<T, K>(bodyJson); 62 : } 63 : } else { 64 : // Response code other than 200 65 0 : return bodyJson; 66 0 : } 67 : } 68 : 69 : /// generic objects as well as List of generic objects 70 : /// (from a JSON list response). 71 : /// First, you need to have a function that checks the type of the 72 : /// generic object and returns the result of the corresponding fromJson call 73 : /// code taken from: 74 5 : /// https://stackoverflow.com/questions/56271651/how-to-pass-a-generic-type-as-a-parameter-to-a-future-in-flutter 75 5 : static T fromJson<T, K>(dynamic json) { 76 2 : if (json is Iterable) { 77 5 : return _fromJsonList<K>(json) as T; 78 1 : } else if (T == AssetModel) { 79 5 : return AssetModel.fromJson(json) as T; 80 2 : } else if (T == EntryModel) { 81 5 : return EntryModel.fromJson(json) as T; 82 1 : } else if (T == SyncResult) { 83 : return SyncResult.fromJson(json) as T; 84 : } else { 85 : return json; 86 : } 87 : } 88 2 : 89 : static List<K> _fromJsonList<K>(List jsonList) { 90 : if (jsonList == null) { 91 : return null; 92 : } 93 2 : 94 : final output = <K>[]; 95 4 : // ignore: prefer_final_in_for_each 96 4 : for (Map<String, dynamic> json in jsonList) { 97 : output.add(fromJson(json)); 98 : } 99 : return output; 100 : } 101 : }