Baseflow / Baseflow/flutter_cached_network_image
The libarary is not respecting the cache-control headers
- Dominant language
- Dart
- Stars
- 2.6k
- Forks
- 731
- Avg merge
- 3d 9h
- Merged PRs (30d)
- 1
Description
## 🐛 Bug Report
### Expected behavior
on the server side I'm sending these headers along with the image file:
```
{
'cache-control': 'no-cache,max-age=1',
'etag': hash,
'age': '1',
'content-type': 'image/jpeg'
}
```
so what I expect is that each time I call `CachedNetworkImageProvider` the app would send a get request with an `if-none-match` to check if the ETag of the cached file was changed, but I'm not seeing this request on the server side, note that if I use the `flutter_cache_manager` package directly(through `getSingleFile`) with `Image.memory` then it works as expected, somehow it just breaks when using the `flutter_cached_network_image` package.
### Reproduction steps
- Start a backend server that sends the following cache control HTTP header with '[no-cache](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control)' which should force the cache manager to validate the cached file each time it is requested:
```
import 'dart:io';
import 'dart:typed_data';
import "package:path/path.dart" show dirname, join;
import 'package:shelf/shelf.dart' as shelf;
import 'package:shelf/shelf_io.dart' as io;
import 'package:crypto/crypto.dart' as crypto;
import 'package:shelf_router/shelf_router.dart' as shelf_router;
shelf_router.Router router = shelf_router.Router();
late HttpServer server;
String generateMd5(Uint8List data) {
crypto.Hash md5 = crypto.md5;
crypto.Digest digest = md5.convert(data);
return digest.toString();
}
void main(List args) async {
server = await io.serve(router, InternetAddress.anyIPv4, 8081);
router.get('/avatar/', avatarCallback);
}
avatarCallback(shelf.Request request, String key) async {
print("A request was made");
print(request.headers);
Uint8List avatar =
File(join(dirname(Platform.script.path), 'avatar.png')).readAsBytesSync();
String hash = generateMd5(avatar);
Map responseHeaders = {
'cache-control': 'no-cache,max-age=1',
'etag': hash,
'age': '1',
'content-type': 'image/png'
};
if (request.headers.containsKey('if-none-match')) {
print('found if-none-match');
print('request hash: ${request.headers['if-none-match']}');
print("local hash: ${hash}");
if (request.headers['if-none-match'] == hash) {
return shelf.Response(304, headers: responseHeaders);
}
}
return shelf.Response.ok(avatar, headers: responseHeaders);
}
```
I have added a print statement in a place where it is called each time a request is made to the file .
- below is a an example flutter app to show the problem:
```
import 'package:flutter/material.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
BaseCacheManager def = DefaultCacheManager();
void main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark(),
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
HomePage({
Key? key,
}) : super(key: key);
@override
State createState() => _HomePageState();
}
class _HomePageState extends State {
String imageUrl = 'http://192.168.88.32:8081/avatar/0';
List imagesChildren = [];
@override
void initState() {
// TODO: implement initState
super.initState();
}
@override
void dispose() {
// TODO: implement dispose
super.dispose();
}
@override
Widget build(BuildContext context) {
print('rebuilding');
print(imagesChildren.length);
return Scaffold(
body: SafeArea(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
TextButton(
onPressed: (() async {
Widget wid;
wid = Image.memory(
await def
.getSingleFile(imageUrl)
.then((value) => value.readAsBytesSync()),
width: 50,
height: 50,
);
setState(() {
imagesChildren.add(wid);
});
}),
child: Text('add using cache manager'),
),
TextButton(
onPressed: (() {
Widget wid;
wid = Image(
width: 50,
height: 50,
image: CachedNetworkImageProvider(imageUrl),
);
setState(() {
imagesChildren.add(wid);
});
}),
child: const Text('add using CachedNetworkImageProvider'),
),
ListView(
scrollDirection: Axis.vertical,
shrinkWrap: true,
children: [...imagesChildren],
),
],
),
),
),
);
}
}
```
- start the server and the flutter app, notice that when you click ' add using cache manager' multiple times, it works as expected(the app sends a request with the cached file's hash to check if the resource was updated, while if you click on the 'add using CachedNetworkImageProvider' multiple times, it only request the file in the first time, then it always shows the cached file and doesn't check the server for updates.
### Configuration
**Version:** 1.x
**Platform:**
- [ x] :iphone: iOS
- [x ] :robot: Android
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.