Line data Source code
1 : import 'dart:convert';
2 :
3 : import 'package:http/http.dart' as http;
4 : import 'package:http/http.dart';
5 : import 'package:http_parser/http_parser.dart';
6 : import 'package:pal/src/services/http_client/adapters/error_adapter.dart';
7 :
8 : abstract class BaseHttpClient {}
9 :
10 : /// use this Http client for every request on the app to be authenticated
11 : /// intercept request and add user token if present
12 : /// if token is expired calls refresh token endpoint and save new token
13 : class HttpClient extends http.BaseClient implements BaseHttpClient {
14 : final http.Client _client = new http.Client();
15 : final String _baseUrl;
16 : final String _token;
17 :
18 7 : factory HttpClient.create(final String url, final String token) =>
19 7 : HttpClient._private(url, token);
20 :
21 7 : HttpClient._private(final String url, final String token)
22 7 : : assert(url != null && url != ""),
23 7 : assert(token != null && token != ""),
24 : this._baseUrl = url,
25 : this._token = token;
26 :
27 : @override
28 0 : Future<http.StreamedResponse> send(final http.BaseRequest request) async {
29 0 : request.headers['Authorization'] = 'Bearer ${this._token}';
30 0 : return this._client.send(request);
31 : }
32 :
33 0 : Future<Response> _checkResponse(final Response response) async {
34 0 : if (response.statusCode >= 200 && response.statusCode < 300)
35 : return response;
36 0 : else if (response.statusCode >= 400 && response.statusCode < 500) {
37 0 : final String errorCode = ErrorAdapter().parse(response.body);
38 :
39 0 : throw UnreachableHttpError('Http ${response.statusCode} error, network or bad gateway : ${response.request.url}',
40 : code: errorCode);
41 0 : } else if (response.statusCode >= 500 && response.statusCode < 600) {
42 0 : print("... ==> 500 error ");
43 0 : throw InternalHttpError(
44 0 : 'Http 500 error, internal error ${response.toString()}');
45 : } else {
46 0 : throw UnknownHttpError('e');
47 : }
48 : }
49 :
50 : @override
51 0 : Future<Response> post(final url,
52 : {Map<String, String> headers,
53 : final body,
54 : final Encoding encoding}) async {
55 0 : headers = _initHeader(headers);
56 :
57 0 : return this._checkResponse(
58 0 : await super.post(
59 0 : '${this._baseUrl}/$url',
60 : headers: headers,
61 : body: body,
62 : encoding: encoding,
63 : ),
64 : );
65 : }
66 :
67 : @override
68 0 : Future<Response> delete(final url,
69 : {final Map<String, String> headers}) async {
70 0 : return this._checkResponse(
71 0 : await super.delete('${this._baseUrl}/$url', headers: headers));
72 : }
73 :
74 : @override
75 0 : Future<Response> put(final url,
76 : {Map<String, String> headers,
77 : final body,
78 : final Encoding encoding}) async {
79 0 : headers = _initHeader(headers);
80 :
81 0 : return this._checkResponse(await super.put('${this._baseUrl}/$url',
82 : headers: headers, body: body, encoding: encoding));
83 : }
84 :
85 : @override
86 0 : Future<Response> patch(final url,
87 : {Map<String, String> headers,
88 : final body,
89 : final Encoding encoding}) async {
90 0 : headers = _initHeader(headers);
91 :
92 0 : return this._checkResponse(await super.patch('${this._baseUrl}/$url',
93 : headers: headers, body: body, encoding: encoding));
94 : }
95 :
96 0 : Map<String, String> _initHeader(Map<String, String> headers) {
97 : if (headers == null) {
98 0 : headers = new Map();
99 : }
100 0 : headers..putIfAbsent('Content-Type', () => 'application/json');
101 :
102 : return headers;
103 : }
104 :
105 : @override
106 0 : Future<Response> get(final url, {final Map<String, String> headers}) async {
107 0 : return this._checkResponse(
108 0 : await super.get('${this._baseUrl}/$url', headers: headers));
109 : }
110 :
111 0 : Future<http.StreamedResponse> multipartImage(url,
112 : {Map<String, String> fields,
113 : Map<String, String> headers,
114 : List<int> fileData,
115 : String imageType,
116 : String filename,
117 : String fileFieldName,
118 : String httpMethod = "POST"}) async {
119 0 : var request = new http.MultipartRequest(
120 0 : httpMethod, Uri.parse('${this._baseUrl}/$url'));
121 : if (fields != null) {
122 0 : request.fields.addAll(fields);
123 : }
124 : if (headers != null) {
125 0 : request.headers.addAll(headers);
126 : }
127 0 : var multipartFile = http.MultipartFile.fromBytes(
128 : fileFieldName,
129 : fileData,
130 : filename: filename,
131 0 : contentType: MediaType.parse("image/$imageType"),
132 : );
133 0 : request.files.add(multipartFile);
134 0 : request.headers['Authorization'] = 'Bearer ${this._token}';
135 0 : return request.send();
136 : }
137 : }
138 :
139 : class InternalHttpError implements Exception {
140 : String message;
141 :
142 0 : InternalHttpError(this.message);
143 :
144 0 : String toString() {
145 0 : if (message == null) return "InternalHttpError";
146 0 : return "Exception: $message";
147 : }
148 : }
149 :
150 : class UnreachableHttpError implements Exception {
151 : String message;
152 :
153 : String code;
154 :
155 0 : UnreachableHttpError(this.message, {this.code});
156 :
157 0 : String toString() {
158 0 : if (message == null) return "UnreacheableHttpError";
159 0 : return "Exception: $message";
160 : }
161 : }
162 :
163 : class UnknownHttpError implements Exception {
164 : String message;
165 :
166 0 : UnknownHttpError(this.message);
167 :
168 0 : String toString() {
169 0 : if (message == null) return "UnknownHttpError";
170 0 : return "Exception: $message";
171 : }
172 : }
|