admin 管理员组文章数量: 1086019
I am exploring the dio_cache_interceptor package in Flutter. This package provides logic for implementing caching and handling the HTTP Status Code 304.
While testing this package I tested a particular scenario. My configuration is-
Future<Dio> createDioInstance() async {
final dio = Dio();
dio.options.validateStatus = (status) {
return status != null && (status >= 200 && status < 300 || status == 304);
};
final directory = await getApplicationDocumentsDirectory();
final cacheOptions = CacheOptions(
store: HiveCacheStore(directory.path),
policy: CachePolicy.request,
maxStale: Duration(seconds: 30,)
hitCacheOnErrorExcept: [500, 404]);
dio.interceptors.add(CustomDioCacheInterceptor(options: cacheOptions));
return dio;
}
class CustomDioCacheInterceptor extends DioCacheInterceptor {
CustomDioCacheInterceptor({
required super.options,
}) : _cacheOptions = options;
late final CacheOptions _cacheOptions;
}
The CustomDioCacheInterceptor
is a sub class of the DioCacheInterceptor
class. It just overrides the onRequest()
and onResponse()
method and just call the corresponding super()
methods. No custom logic.
Now, the logic for loading the cached response (in the package) is-
Future<CacheResponse?> _loadCacheResponse(RequestOptions request) async {
final options = _getCacheOptions(request);
final cacheKey = options.keyBuilder(request);
final cacheStore = _getCacheStore(options);
final response = await cacheStore.get(cacheKey);
if (response != null) {
// Purge entry if staled
final maxStale = CacheOptions.fromExtra(request)?.maxStale;
if ((maxStale == null || maxStale == const Duration(microseconds: 0)) &&
response.isStaled()) {
await cacheStore.delete(cacheKey);
return null;
}
return response.readContent(options);
}
return null;
}
bool isStaled() {
return maxStale?.isBefore(DateTime.now()) ?? false;
}
Based on the maxStale
, the cached response is either deleted (if stale) or returned (if not stale).
This _loadCacheResponse()
is called in onRequest()
when the request comes in and in onResponse()
when the response has a status code of 304. This is the exact logic in the package.
Potential Issue-
- Suppose we set a
maxStale
duration of 30 seconds. This would mean that the cached response has a maxStale of 30 seconds. - Next, we make 3 consecutive requests to the same cached api with different delays.
- Request 1 --> Response 1 (status code 200), therefore data is cached with max-stale of 30 seconds. (expected)
- Request 2 (after a delay of 20 seconds) --> Response 2 (status code 304 because of etag sent in the request), therefore data is fetched from the cache, max-stale is updated with 30 seconds and data is saved to cache. (expected)
- Request 3 (after a delay of 29 seconds) --> Response 3 (status code 304 because of etag sent in the request), therefore data is fetched from the cache. Now here is the issue! As per the logic the data is fetched from the cache and then a staleness check is performed. If it passes, the cached data is deleted and empty response is returned! As a result, in the onResponse() we have status code 304 with empty response body (since the cached data got deleted).
This breaks on the upper layers (api-calling layer) because we got an empty response body. This happened because in onRequest(), the cached data was not stale but in onResponse() the data got stale.
本文标签: cachingdiocacheinterceptor package returns empty response body with maxStaleFlutterStack Overflow
版权声明:本文标题:caching - dio_cache_interceptor package returns empty response body with maxStale : Flutter - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.roclinux.cn/p/1744070544a2528403.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论