Skip to content

Commit fb0d4f1

Browse files
authored
Merge pull request #32 from CodingAleCR/release/0.3.1
Release 0.3.1
2 parents ab64835 + d61cfa5 commit fb0d4f1

File tree

9 files changed

+146
-52
lines changed

9 files changed

+146
-52
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# Changelog
22

3+
## 0.3.1
4+
5+
* Fixed: Retry Policy's `shouldAttemptRetryOnResponse` was synchronous which would not allow async token updates.
6+
* Fixed: Retry Policy would only trigger once when using `HttpClientWithInterceptor`.
7+
* Fixed: Retry Policy would use the `http` Response class, which would force plugin users to add http plugin separately.
8+
* Experimental: `badCertificateCallback` allows you to use self-signing certificates.
9+
310
## 0.3.0
411

512
* Added: RetryPolicy. It allows to attempt retries on a request when an exception occurs or when a condition from the response is met.

README.md

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ This is a plugin that lets you intercept the different requests and responses fr
1515
- [Building your own interceptor](#building-your-own-interceptor)
1616
- [Using your interceptor](#using-your-interceptor)
1717
- [Retrying requests](#retrying-requests)
18+
- [Using self-signed certificates](#using-self-signed-certificates)
1819
- [Having trouble? Fill an issue](#troubleshooting)
1920

2021
## Installation
@@ -147,7 +148,7 @@ class WeatherRepository {
147148
```dart
148149
class ExpiredTokenRetryPolicy extends RetryPolicy {
149150
@override
150-
bool shouldAttemptRetryOnResponse(Response response) {
151+
Future<bool> shouldAttemptRetryOnResponse(ResponseData response) async {
151152
if (response.statusCode == 401) {
152153
// Perform your token refresh here.
153154
@@ -161,6 +162,34 @@ class ExpiredTokenRetryPolicy extends RetryPolicy {
161162

162163
You can also set the maximum amount of retry attempts with `maxRetryAttempts` property or override the `shouldAttemptRetryOnException` if you want to retry the request after it failed with an exception.
163164

165+
### Using self signed certificates
166+
167+
**(EXPERIMENTAL ⚗️)** This plugin allows you to override the default `badCertificateCallback` provided by Dart's `io` package, this is really useful when working with self-signed certificates in your server. This can be done by sending a the callback to the HttpInterceptor builder functions. This feature is marked as experimental and **might be subject to change before release 1.0.0 comes**.
168+
169+
```dart
170+
class WeatherRepository {
171+
172+
Future<Map<String, dynamic>> fetchCityWeather(int id) async {
173+
var parsedWeather;
174+
try {
175+
var response = await HttpWithInterceptor.build(
176+
interceptors: [WeatherApiInterceptor()],
177+
badCertificateCallback: (certificate, host, port) => true)
178+
.get("$baseUrl/weather", params: {'id': "$id"});
179+
if (response.statusCode == 200) {
180+
parsedWeather = json.decode(response.body);
181+
} else {
182+
throw Exception("Error while fetching. \n ${response.body}");
183+
}
184+
} catch (e) {
185+
print(e);
186+
}
187+
return parsedWeather;
188+
}
189+
190+
}
191+
```
192+
164193
## Troubleshooting
165194

166195
Open an issue and tell me, I will be happy to help you out as soon as I can.

example/pubspec.lock

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,42 +7,42 @@ packages:
77
name: archive
88
url: "https://pub.dartlang.org"
99
source: hosted
10-
version: "2.0.11"
10+
version: "2.0.13"
1111
args:
1212
dependency: transitive
1313
description:
1414
name: args
1515
url: "https://pub.dartlang.org"
1616
source: hosted
17-
version: "1.5.2"
17+
version: "1.6.0"
1818
async:
1919
dependency: transitive
2020
description:
2121
name: async
2222
url: "https://pub.dartlang.org"
2323
source: hosted
24-
version: "2.4.0"
24+
version: "2.4.1"
2525
boolean_selector:
2626
dependency: transitive
2727
description:
2828
name: boolean_selector
2929
url: "https://pub.dartlang.org"
3030
source: hosted
31-
version: "1.0.5"
31+
version: "2.0.0"
3232
charcode:
3333
dependency: transitive
3434
description:
3535
name: charcode
3636
url: "https://pub.dartlang.org"
3737
source: hosted
38-
version: "1.1.2"
38+
version: "1.1.3"
3939
collection:
4040
dependency: transitive
4141
description:
4242
name: collection
4343
url: "https://pub.dartlang.org"
4444
source: hosted
45-
version: "1.14.11"
45+
version: "1.14.12"
4646
convert:
4747
dependency: transitive
4848
description:
@@ -56,7 +56,7 @@ packages:
5656
name: crypto
5757
url: "https://pub.dartlang.org"
5858
source: hosted
59-
version: "2.1.3"
59+
version: "2.1.4"
6060
cupertino_icons:
6161
dependency: "direct main"
6262
description:
@@ -87,7 +87,7 @@ packages:
8787
path: ".."
8888
relative: true
8989
source: path
90-
version: "0.3.0"
90+
version: "0.3.1"
9191
http_parser:
9292
dependency: transitive
9393
description:
@@ -101,7 +101,7 @@ packages:
101101
name: image
102102
url: "https://pub.dartlang.org"
103103
source: hosted
104-
version: "2.1.4"
104+
version: "2.1.12"
105105
matcher:
106106
dependency: transitive
107107
description:
@@ -143,7 +143,7 @@ packages:
143143
name: quiver
144144
url: "https://pub.dartlang.org"
145145
source: hosted
146-
version: "2.0.5"
146+
version: "2.1.3"
147147
sky_engine:
148148
dependency: transitive
149149
description: flutter
@@ -155,7 +155,7 @@ packages:
155155
name: source_span
156156
url: "https://pub.dartlang.org"
157157
source: hosted
158-
version: "1.5.5"
158+
version: "1.7.0"
159159
stack_trace:
160160
dependency: transitive
161161
description:
@@ -190,7 +190,7 @@ packages:
190190
name: test_api
191191
url: "https://pub.dartlang.org"
192192
source: hosted
193-
version: "0.2.11"
193+
version: "0.2.15"
194194
typed_data:
195195
dependency: transitive
196196
description:
@@ -211,6 +211,6 @@ packages:
211211
name: xml
212212
url: "https://pub.dartlang.org"
213213
source: hosted
214-
version: "3.5.0"
214+
version: "3.6.1"
215215
sdks:
216-
dart: ">=2.4.0 <3.0.0"
216+
dart: ">=2.6.0 <3.0.0"

lib/http_client_with_interceptor.dart

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import 'dart:async';
22
import 'dart:convert';
3+
import 'dart:io';
34
import 'dart:typed_data';
5+
46
import 'package:flutter/foundation.dart';
5-
import 'package:http/http.dart' as http;
67
import 'package:http/http.dart';
7-
import 'package:http_interceptor/models/models.dart';
8+
import 'package:http/io_client.dart';
89
import 'package:http_interceptor/interceptor_contract.dart';
10+
import 'package:http_interceptor/models/models.dart';
911
import 'package:http_interceptor/utils.dart';
1012

1113
import 'http_methods.dart';
@@ -34,34 +36,43 @@ import 'http_methods.dart';
3436
///```
3537
///Don't forget to close the client once you are done, as a client keeps
3638
///the connection alive with the server.
37-
class HttpClientWithInterceptor extends http.BaseClient {
39+
class HttpClientWithInterceptor extends BaseClient {
3840
List<InterceptorContract> interceptors;
3941
Duration requestTimeout;
4042
RetryPolicy retryPolicy;
43+
bool Function(X509Certificate, String, int) badCertificateCallback;
4144

42-
final Client _client = Client();
4345
int _retryCount = 0;
46+
Client _client;
47+
48+
void _initializeClient() {
49+
var ioClient = new HttpClient()
50+
..badCertificateCallback = badCertificateCallback;
51+
_client = IOClient(ioClient);
52+
}
4453

4554
HttpClientWithInterceptor._internal({
4655
this.interceptors,
4756
this.requestTimeout,
4857
this.retryPolicy,
58+
this.badCertificateCallback,
4959
});
5060

5161
factory HttpClientWithInterceptor.build({
5262
@required List<InterceptorContract> interceptors,
5363
Duration requestTimeout,
5464
RetryPolicy retryPolicy,
65+
bool Function(X509Certificate, String, int) badCertificateCallback,
5566
}) {
5667
assert(interceptors != null);
5768

5869
//Remove any value that is null.
5970
interceptors.removeWhere((interceptor) => interceptor == null);
6071
return HttpClientWithInterceptor._internal(
61-
interceptors: interceptors,
62-
requestTimeout: requestTimeout,
63-
retryPolicy: retryPolicy,
64-
);
72+
interceptors: interceptors,
73+
requestTimeout: requestTimeout,
74+
retryPolicy: retryPolicy,
75+
badCertificateCallback: badCertificateCallback);
6576
}
6677

6778
Future<Response> head(url, {Map<String, String> headers}) => _sendUnstreamed(
@@ -130,7 +141,12 @@ class HttpClientWithInterceptor extends http.BaseClient {
130141
});
131142
}
132143

133-
Future<StreamedResponse> send(BaseRequest request) => _client.send(request);
144+
Future<StreamedResponse> send(BaseRequest request) {
145+
if (_client == null) {
146+
_initializeClient();
147+
}
148+
return _client.send(request);
149+
}
134150

135151
Future<Response> _sendUnstreamed({
136152
@required Method method,
@@ -193,23 +209,25 @@ class HttpClientWithInterceptor extends http.BaseClient {
193209
: await send(request).timeout(requestTimeout);
194210

195211
response = await Response.fromStream(stream);
196-
if (retryPolicy != null
197-
&& retryPolicy.maxRetryAttempts > _retryCount
198-
&& retryPolicy.shouldAttemptRetryOnResponse(response)) {
212+
if (retryPolicy != null &&
213+
retryPolicy.maxRetryAttempts > _retryCount &&
214+
await retryPolicy.shouldAttemptRetryOnResponse(
215+
ResponseData.fromHttpResponse(response))) {
199216
_retryCount += 1;
200217
return _attemptRequest(request);
201218
}
202219
} catch (error) {
203-
if (retryPolicy != null
204-
&& retryPolicy.maxRetryAttempts > _retryCount
205-
&& retryPolicy.shouldAttemptRetryOnException(error)) {
220+
if (retryPolicy != null &&
221+
retryPolicy.maxRetryAttempts > _retryCount &&
222+
retryPolicy.shouldAttemptRetryOnException(error)) {
206223
_retryCount += 1;
207224
return _attemptRequest(request);
208225
} else {
209226
throw HttpInterceptorException(error.toString());
210227
}
211228
}
212229

230+
_retryCount = 0;
213231
return response;
214232
}
215233

@@ -238,6 +256,9 @@ class HttpClientWithInterceptor extends http.BaseClient {
238256
}
239257

240258
void close() {
259+
if (_client == null) {
260+
_initializeClient();
261+
}
241262
_client.close();
242263
}
243264
}

lib/http_with_interceptor.dart

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import 'dart:async';
22
import 'dart:convert';
3+
import 'dart:io';
34
import 'dart:typed_data';
45
import 'package:flutter/foundation.dart';
56
import 'package:http/http.dart';
@@ -29,27 +30,30 @@ class HttpWithInterceptor {
2930
List<InterceptorContract> interceptors;
3031
Duration requestTimeout;
3132
RetryPolicy retryPolicy;
33+
bool Function(X509Certificate, String, int) badCertificateCallback;
3234

3335
HttpWithInterceptor._internal({
3436
this.interceptors,
3537
this.requestTimeout,
3638
this.retryPolicy,
39+
this.badCertificateCallback,
3740
});
3841

3942
factory HttpWithInterceptor.build({
4043
@required List<InterceptorContract> interceptors,
4144
Duration requestTimeout,
4245
RetryPolicy retryPolicy,
46+
bool Function(X509Certificate, String, int) badCertificateCallback,
4347
}) {
4448
assert(interceptors != null);
4549

4650
//Remove any value that is null.
4751
interceptors?.removeWhere((interceptor) => interceptor == null);
4852
return new HttpWithInterceptor._internal(
49-
interceptors: interceptors,
50-
requestTimeout: requestTimeout,
51-
retryPolicy: retryPolicy,
52-
);
53+
interceptors: interceptors,
54+
requestTimeout: requestTimeout,
55+
retryPolicy: retryPolicy,
56+
badCertificateCallback: badCertificateCallback);
5357
}
5458

5559
Future<Response> head(url, {Map<String, String> headers}) async {
@@ -58,7 +62,8 @@ class HttpWithInterceptor {
5862

5963
Future<Response> get(url,
6064
{Map<String, String> headers, Map<String, String> params}) async {
61-
return _withClient((client) => client.get(url, headers: headers, params: params));
65+
return _withClient(
66+
(client) => client.get(url, headers: headers, params: params));
6267
}
6368

6469
Future<Response> post(url,
@@ -96,6 +101,7 @@ class HttpWithInterceptor {
96101
interceptors: interceptors,
97102
requestTimeout: requestTimeout,
98103
retryPolicy: retryPolicy,
104+
badCertificateCallback: badCertificateCallback,
99105
);
100106
try {
101107
return await fn(client);

lib/models/retry_policy.dart

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
import 'package:http/http.dart';
1+
import 'package:http_interceptor/models/models.dart';
22

33
abstract class RetryPolicy {
44
bool shouldAttemptRetryOnException(Exception reason) => false;
5-
bool shouldAttemptRetryOnResponse(Response response) => false;
5+
Future<bool> shouldAttemptRetryOnResponse(ResponseData response) async =>
6+
false;
67
final int maxRetryAttempts = 1;
7-
}
8+
}

0 commit comments

Comments
 (0)