Line data Source code
1 : import 'dart:async'; 2 : import 'dart:convert'; 3 : 4 : import 'package:contentstack/contentstack.dart'; 5 : import 'package:contentstack/src/stack.dart'; 6 : import 'package:http/http.dart' as http; 7 : 8 : class HttpClient extends http.BaseClient { 9 : final http.Client _client; 10 : final Stack stack; 11 : final Map<String, String> stackHeaders; 12 : 13 : factory HttpClient(Map<String, String> headers, 14 6 : {http.Client client, Stack stack}) { 15 : final stackClient = client ?? http.Client(); 16 6 : return HttpClient._internal(stackClient, headers, stack); 17 6 : } 18 : 19 : /// This is used for the _internal constructure 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 : /// 31 10 : /// Makes `GET` Request based on uri request 32 10 : Future<T> sendRequest<T, K>(Uri uri) async { 33 15 : stackHeaders['Content-Type'] = 'application/json'; 34 : stackHeaders['X-User-Agent'] = 'contentstack-dart/0.1.1'; 35 : final response = await http.get(uri, headers: stackHeaders); 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 : final Map bodyJson = jsonDecode(response.body); 49 6 : if (T == EntryModel && bodyJson.containsKey('entry')) { 50 2 : return fromJson<T, K>(bodyJson['entry']); 51 6 : } else if (K == EntryModel && bodyJson.containsKey('entries')) { 52 2 : return fromJson<T, K>(bodyJson['entries']); 53 6 : } else if (T == AssetModel && bodyJson.containsKey('asset')) { 54 2 : return fromJson<T, K>(bodyJson['asset']); 55 6 : } else if (K == AssetModel && bodyJson.containsKey('assets')) { 56 1 : return fromJson<T, K>(bodyJson['assets']); 57 : } else if (T == SyncResult && bodyJson.containsKey('items')) { 58 5 : return fromJson<T, K>(bodyJson); 59 : } else { 60 : return fromJson<T, K>(bodyJson); 61 : } 62 : } else { 63 : return bodyJson; 64 : } 65 0 : } 66 0 : 67 : /// generic objects as well as List of generic objects 68 : /// (from a JSON list response). 69 : /// First, you need to have a function that checks the type of the 70 : /// generic object and returns the result of the corresponding fromJson call 71 : /// code taken from: 72 : /// https://stackoverflow.com/questions/56271651/how-to-pass-a-generic-type-as-a-parameter-to-a-future-in-flutter 73 : static T fromJson<T, K>(dynamic json) { 74 5 : if (json is Iterable) { 75 5 : return _fromJsonList<K>(json) as T; 76 2 : } else if (T == AssetModel) { 77 5 : return AssetModel.fromJson(json) as T; 78 1 : } else if (T == EntryModel) { 79 5 : return EntryModel.fromJson(json) as T; 80 2 : } else if (T == SyncResult) { 81 5 : return SyncResult.fromJson(json) as T; 82 1 : } else { 83 : return json; 84 : } 85 : } 86 : 87 : static List<K> _fromJsonList<K>(List jsonList) { 88 2 : if (jsonList == null) { 89 : return null; 90 : } 91 : 92 : final output = <K>[]; 93 2 : // ignore: prefer_final_in_for_each 94 : for (Map<String, dynamic> json in jsonList) { 95 4 : output.add(fromJson(json)); 96 4 : } 97 : return output; 98 : } 99 : }