Skip to content

Commit

Permalink
feat(#16): Allow POST methods to be cached
Browse files Browse the repository at this point in the history
  • Loading branch information
llfbandit committed May 3, 2021
1 parent 88ed14c commit 2ae5510
Show file tree
Hide file tree
Showing 9 changed files with 60 additions and 17 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
## 2.3.0
- feat: `allowPostMethod` added to `CacheOptions`.

## 2.2.0
- feat: Cache-Control: max-age as cache trigger added.
- core: update README.md.
Expand Down
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import 'package:dio_cache_interceptor/dio_cache_interceptor.dart';
// Global options
final options = const CacheOptions(
// A default store is required for interceptor.
store: DbCacheStore(databasePath: 'a_path'),
store: MemCacheStore(),
// Default.
policy: CachePolicy.request,
// Optional. Returns a cached response on error but for statuses 401 & 403.
Expand All @@ -43,6 +43,13 @@ final options = const CacheOptions(
maxStale: const Duration(days: 7),
// Default. Allows 3 cache sets and ease cleanup.
priority: CachePriority.normal,
// Default. Body and headers encryption with your own algorithm.
cipher: null,
// Default. Key builder to retrieve requests.
keyBuilder: CacheOptions.defaultCacheKeyBuilder,
// Default. Allows to cache POST requests.
// Overriding [keyBuilder] is strongly recommended.
allowPostMethod: false,
);
// Add cache interceptor with global/default options
Expand Down
2 changes: 1 addition & 1 deletion example/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ buildscript {
}

dependencies {
classpath 'com.android.tools.build:gradle:3.5.0'
classpath 'com.android.tools.build:gradle:4.1.3'
}
}

Expand Down
4 changes: 2 additions & 2 deletions example/android/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#Sat Jun 27 10:47:21 CEST 2020
#Sat Apr 24 18:07:04 CEST 2021
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip
33 changes: 23 additions & 10 deletions lib/src/dio_cache_interceptor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import 'util/response_extension.dart';
/// Cache interceptor
class DioCacheInterceptor extends Interceptor {
static const String _getMethodName = 'GET';
static const String _postMethodName = 'POST';

final CacheOptions _options;
final CacheStore _store;
Expand All @@ -28,13 +29,13 @@ class DioCacheInterceptor extends Interceptor {
RequestOptions request,
RequestInterceptorHandler handler,
) async {
if (_shouldSkipRequest(request)) {
final options = _getCacheOptions(request);

if (_shouldSkipRequest(request, options: options)) {
handler.next(request);
return;
}

final options = _getCacheOptions(request);

if (options.policy != CachePolicy.refresh &&
options.policy != CachePolicy.refreshForceCache) {
final cacheResp = await _getCacheResponse(request);
Expand All @@ -57,13 +58,14 @@ class DioCacheInterceptor extends Interceptor {
Response response,
ResponseInterceptorHandler handler,
) async {
if (_shouldSkipRequest(response.requestOptions) ||
final options = _getCacheOptions(response.requestOptions);

if (_shouldSkipRequest(response.requestOptions, options: options) ||
response.statusCode != 200) {
handler.next(response);
return;
}

final options = _getCacheOptions(response.requestOptions);
final policy = options.policy;

if (policy == CachePolicy.noCache) {
Expand Down Expand Up @@ -93,7 +95,9 @@ class DioCacheInterceptor extends Interceptor {
DioError err,
ErrorInterceptorHandler handler,
) async {
if (_shouldSkipRequest(err.requestOptions, error: err)) {
final options = _getCacheOptions(err.requestOptions);

if (_shouldSkipRequest(err.requestOptions, options: options, error: err)) {
handler.next(err);
return;
}
Expand All @@ -105,7 +109,6 @@ class DioCacheInterceptor extends Interceptor {
returnResponse = true;
} else {
// Check if we can return cache
final options = _getCacheOptions(err.requestOptions);
final hcoeExcept = options.hitCacheOnErrorExcept;

if (hcoeExcept != null) {
Expand Down Expand Up @@ -184,9 +187,19 @@ class DioCacheInterceptor extends Interceptor {
return options.store ?? _store;
}

bool _shouldSkipRequest(RequestOptions? request, {DioError? error}) {
var result = error?.type == DioErrorType.cancel;
result |= (request?.method.toUpperCase() != _getMethodName);
bool _shouldSkipRequest(
RequestOptions? request, {
required CacheOptions options,
DioError? error,
}) {
if (error?.type == DioErrorType.cancel) {
return true;
}

final rqMethod = request?.method.toUpperCase();
var result = (rqMethod != _getMethodName);
result &= (!options.allowPostMethod || rqMethod != _postMethodName);

return result;
}

Expand Down
6 changes: 6 additions & 0 deletions lib/src/model/cache_options.dart
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ class CacheOptions {
/// Optional method to decrypt/encrypt cache content
final CacheCipher? cipher;

/// allow POST method request to be cached.
final bool allowPostMethod;

// Key to retrieve options from request
static const _extraKey = '@cache_options@';

Expand All @@ -84,6 +87,7 @@ class CacheOptions {
this.maxStale,
this.priority = CachePriority.normal,
this.cipher,
this.allowPostMethod = false,
required this.store,
});

Expand Down Expand Up @@ -111,6 +115,7 @@ class CacheOptions {
CachePriority? priority,
CacheStore? store,
CacheCipher? cipher,
bool? allowPostMethod,
}) {
return CacheOptions(
policy: policy ?? this.policy,
Expand All @@ -121,6 +126,7 @@ class CacheOptions {
priority: priority ?? this.priority,
store: store ?? this.store,
cipher: cipher ?? this.cipher,
allowPostMethod: allowPostMethod ?? this.allowPostMethod,
);
}
}
4 changes: 2 additions & 2 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ description: Dio HTTP cache interceptor with multiple stores respecting HTTP dir
repository: https://github.com/llfbandit/dio_cache_interceptor
issue_tracker: https://github.com/llfbandit/dio_cache_interceptor/issues

version: 2.2.0
version: 2.3.0

environment:
sdk: ">=2.12.0 <3.0.0"
Expand All @@ -24,7 +24,7 @@ dev_dependencies:
# https://pub.dev/packages/moor_generator
moor_generator: ^4.2.1
# https://pub.dev/packages/build_runner
build_runner: ^1.12.2
build_runner: ^2.0.1
# https://pub.dev/packages/pedantic
pedantic: ^1.11.0
# https://pub.dev/packages/sqlite3
Expand Down
13 changes: 13 additions & 0 deletions test/cache_interceptor_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,19 @@ void main() {
expect(resp.extra[CacheResponse.cacheKey], isNull);
});

test('Fetch post doesn\'t skip request', () async {
final resp = await _dio.post(
'${MockHttpClientAdapter.mockBase}/post',
options: Options(
extra: options.copyWith(allowPostMethod: true).toExtra(),
),
);

expect(resp.statusCode, equals(200));
expect(resp.data['path'], equals('/post'));
expect(resp.extra[CacheResponse.cacheKey], isNotNull);
});

test('Fetch hitCacheOnErrorExcept 500', () async {
final resp = await _dio.get('${MockHttpClientAdapter.mockBase}/ok');
final cacheKey = resp.extra[CacheResponse.cacheKey];
Expand Down
3 changes: 2 additions & 1 deletion test/mock_httpclient_adapter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ class MockHttpClientAdapter extends HttpClientAdapter {
jsonEncode({'path': uri.path}),
200,
headers: {
Headers.contentTypeHeader: [Headers.jsonContentType]
Headers.contentTypeHeader: [Headers.jsonContentType],
'etag': ['1234'],
},
);
case '/exception':
Expand Down

0 comments on commit 2ae5510

Please sign in to comment.