Skip to content

Commit

Permalink
Merge pull request #29 from Zazo032/master
Browse files Browse the repository at this point in the history
Add MultipartFileRecreatable.fromBytes + plugin improvements
  • Loading branch information
rodion-m authored Oct 26, 2023
2 parents a13117e + 9d7767b commit 810d213
Show file tree
Hide file tree
Showing 10 changed files with 108 additions and 40 deletions.
1 change: 0 additions & 1 deletion .idea/dio_smart_retry.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
## 6.0.0
- Updated internal libraries.
- Bumped minimum Dart SDK to 3.0.
- Added `MultipartFileRecreatable` documentation.
- Refactors static constructors to factories.
- Adds a new `MultipartFileRecreatable.fromBytes` factory compatible with web.
- Added a new `headers` parameter.
- You can now read the file's content with `MultipartFileRecreatable.data`.
- **Breaking:** `MultipartFileRecreatable.filename` is now a named parameter to match `dio`.
- **Breaking:** Removed `MultipartFileRecreatable.filePath` since it was not being used internally.

## 5.0.0
- Add supporting of the new dio 5.+

Expand Down
28 changes: 27 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,4 +129,30 @@ final formData =
data: formData,
);
```
See the full example in the test: https://github.com/rodion-m/dio_smart_retry/blob/63a3bddae8b5a0581c35c4ae5e973996561d9100/test/multipart_retry_tests.dart#L32-L61
See the full example in the test: https://github.com/rodion-m/dio_smart_retry/blob/63a3bddae8b5a0581c35c4ae5e973996561d9100/test/multipart_retry_tests.dart#L32-L61

## Migrating to 6.0

Version 6.0 introduces 2 breaking changes:
- `MultipartFileRecreatable.filename` is now a named parameter
- `MultipartFileRecreatable.filePath` is now removed

To update to the latest version, if you were using the `MultipartFileRecreatable` constructor, remove the `filePath` parameter and change `filename` to a named parameter:

Old:
```dart
return MultipartFileRecreatable(
stream,
length,
filename,
filePath,
);
```
New:
```dart
return MultipartFileRecreatable(
stream,
length,
filename: filename,
);
```
8 changes: 4 additions & 4 deletions lib/src/default_retry_evaluator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,18 @@ class DefaultRetryEvaluator {
/// Returns true only if the response hasn't been cancelled
/// or got a bad status code.
// ignore: avoid-unused-parameters
FutureOr<bool> evaluate(DioError error, int attempt) {
FutureOr<bool> evaluate(DioException error, int attempt) {
bool shouldRetry;
if (error.type == DioErrorType.badResponse) {
if (error.type == DioExceptionType.badResponse) {
final statusCode = error.response?.statusCode;
if (statusCode != null) {
shouldRetry = isRetryable(statusCode);
} else {
shouldRetry = true;
}
} else {
shouldRetry =
error.type != DioErrorType.cancel && error.error is! FormatException;
shouldRetry = error.type != DioExceptionType.cancel &&
error.error is! FormatException;
}
currentAttempt = attempt;
return shouldRetry;
Expand Down
54 changes: 40 additions & 14 deletions lib/src/multipart_file_recreatable.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,39 @@ import 'package:dio/dio.dart';
import 'package:http_parser/http_parser.dart';
import 'package:path/path.dart' as p;

/// Creates an instance of [MultipartFile] that can be recreated and reused.
class MultipartFileRecreatable extends MultipartFile {
/// Default constructor.
MultipartFileRecreatable(
Stream<List<int>> stream,
int length,
super.stream,
super.length, {
super.filename,
super.contentType,
super.headers,
}) : data = stream;

/// Creates a [MultipartFileRecreatable] object with [bytes].
factory MultipartFileRecreatable.fromBytes(
List<int> bytes, {
String? filename,
this.filePath, {
MediaType? contentType,
}) : super(stream, length, filename: filename, contentType: contentType);
final String filePath;
Map<String, List<String>>? headers,
}) {
return MultipartFileRecreatable(
Stream.fromIterable(<List<int>>[bytes]),
bytes.length,
filename: filename,
contentType: contentType,
headers: headers,
);
}

// ignore: prefer_constructors_over_static_methods
static MultipartFileRecreatable fromFileSync(
/// Creates a [MultipartFileRecreatable] object from a [File] in [filePath].
factory MultipartFileRecreatable.fromFileSync(
String filePath, {
String? filename,
MediaType? contentType,
Map<String, List<String>>? headers,
}) {
filename ??= p.basename(filePath);
final file = File(filePath);
Expand All @@ -27,15 +45,23 @@ class MultipartFileRecreatable extends MultipartFile {
return MultipartFileRecreatable(
stream,
length,
filename,
filePath,
filename: filename,
contentType: contentType,
headers: headers,
);
}

MultipartFileRecreatable recreate() => fromFileSync(
filePath,
filename: filename,
contentType: contentType,
);
/// The stream that will emit the file's contents.
final Stream<List<int>> data;

/// Recreates the [MultipartFileRecreatable] object.
MultipartFileRecreatable recreate() {
return MultipartFileRecreatable(
data,
length,
filename: filename,
contentType: contentType,
headers: headers,
);
}
}
21 changes: 14 additions & 7 deletions lib/src/retry_interceptor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ import 'package:dio_smart_retry/src/http_status_codes.dart';
import 'package:dio_smart_retry/src/multipart_file_recreatable.dart';
import 'package:dio_smart_retry/src/retry_not_supported_exception.dart';

typedef RetryEvaluator = FutureOr<bool> Function(DioError error, int attempt);
typedef RetryEvaluator = FutureOr<bool> Function(
DioException error,
int attempt,
);

/// An interceptor that will try to send failed request again
class RetryInterceptor extends Interceptor {
Expand Down Expand Up @@ -35,7 +38,7 @@ class RetryInterceptor extends Interceptor {
'retryableExtraStatuses',
);
}
if(retries < 0) {
if (retries < 0) {
throw ArgumentError(
'[retries] cannot be less than 0',
'retries',
Expand Down Expand Up @@ -82,11 +85,11 @@ class RetryInterceptor extends Interceptor {

/// Redirects to [DefaultRetryEvaluator.evaluate]
/// with [defaultRetryableStatuses]
static final FutureOr<bool> Function(DioError error, int attempt)
static final FutureOr<bool> Function(DioException error, int attempt)
defaultRetryEvaluator =
DefaultRetryEvaluator(defaultRetryableStatuses).evaluate;

Future<bool> _shouldRetry(DioError error, int attempt) async {
Future<bool> _shouldRetry(DioException error, int attempt) async {
try {
return await _retryEvaluator(error, attempt);
} catch (e) {
Expand All @@ -105,7 +108,10 @@ class RetryInterceptor extends Interceptor {
}

@override
Future<dynamic> onError(DioError err, ErrorInterceptorHandler handler) async {
Future<dynamic> onError(
DioException err,
ErrorInterceptorHandler handler,
) async {
if (err.requestOptions.disableRetry) {
return super.onError(err, handler);
}
Expand Down Expand Up @@ -135,7 +141,7 @@ class RetryInterceptor extends Interceptor {
requestOptions = _recreateOptions(err.requestOptions);
} on RetryNotSupportedException catch (e) {
return super.onError(
DioError(requestOptions: requestOptions, error: e),
DioException(requestOptions: requestOptions, error: e),
handler,
);
}
Expand All @@ -153,7 +159,7 @@ class RetryInterceptor extends Interceptor {
await dio
.fetch<void>(requestOptions)
.then((value) => handler.resolve(value));
} on DioError catch (e) {
} on DioException catch (e) {
super.onError(e, handler);
}
}
Expand Down Expand Up @@ -191,6 +197,7 @@ class RetryInterceptor extends Interceptor {
}

var _multipartFileChecked = false;

void _printErrorIfRequestHasMultipartFile(RequestOptions options) {
if (_multipartFileChecked) return;
if (options.data is FormData) {
Expand Down
14 changes: 7 additions & 7 deletions pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
name: dio_smart_retry
description: Retry library for Dio and Dio package made with love. By default, the request will be retried only for appropriate retryable http statuses.
version: 5.0.0
version: 6.0.0
repository: https://github.com/rodion-m/dio_smart_retry
issue_tracker: https://github.com/rodion-m/dio_smart_retry/issues
homepage: https://github.com/rodion-m/dio_smart_retry
documentation: https://github.com/rodion-m/dio_smart_retry#contents

environment:
sdk: '>=2.12.0 <3.0.0'
sdk: '>=3.0.0 <4.0.0'

dependencies:
dio: ^5.0.0
dio: ^5.3.3
http_parser: ^4.0.2
path: ^1.8.2
path: ^1.8.3

dev_dependencies:
dart_code_metrics: ^5.6.0
test: ^1.23.1
very_good_analysis: ^4.0.0+1
dart_code_metrics: ^5.7.6
test: ^1.24.9
very_good_analysis: ^5.1.0
6 changes: 3 additions & 3 deletions test/multipart_retry_tests.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ void main() {
'https://rodion-m.ru/mock/post500.php',
data: formData,
);
} on DioError catch (error) {
} on DioException catch (error) {
exception = error.error;
}

Expand Down Expand Up @@ -51,8 +51,8 @@ void main() {
'https://rodion-m.ru/mock/post500.php',
data: formData,
);
} on DioError catch (error) {
if (error.type != DioErrorType.badResponse) {
} on DioException catch (error) {
if (error.type != DioExceptionType.badResponse) {
rethrow;
}
}
Expand Down
4 changes: 2 additions & 2 deletions test/override_retryable_statuses_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ void main() {

try {
await dio.get<dynamic>('https://mock.codes/400');
} on DioError catch (error) {
if (error.type != DioErrorType.badResponse ||
} on DioException catch (error) {
if (error.type != DioExceptionType.badResponse ||
error.response?.statusCode != 400) {
rethrow;
}
Expand Down

0 comments on commit 810d213

Please sign in to comment.