http_client_cache 1.0.0 copy "http_client_cache: ^1.0.0" to clipboard
http_client_cache: ^1.0.0 copied to clipboard

A Dart package for HTTP request caching and network optimization. Provides flexible caching mechanisms to improve performance and reduce network load in Dart and Flutter applications.

example/example.dart

import 'dart:async';
import 'dart:io';

import 'package:http/http.dart' as http;
import 'package:http_client_cache/http_client_cache.dart';
import 'package:http_client_interceptor/http_client_interceptor.dart';
import 'package:http_client_logger/http_client_logger.dart';
import 'package:logging/logging.dart' hide Level;
import 'package:mime/mime.dart';

Future<void> main() async {
  // HttpOverrides.global = _HttpOverrides();

  Logger.root.onRecord.listen((record) {
    print(record.message);
  });

  final cache = HttpCache();

  // create a cache instance which persists the cache entries on disk
  // final dir = Directory('cache');
  // await cache.initLocal(dir);

  // create a cache instance which persists the cache entries in memory
  await cache.initInMemory();

  await http.runWithClient(
    _myDartApp,
    () => _createHttpClient(cache),
  );
}

/// Simulates a Dart application making an HTTP GET request to a public API
/// endpoint.
///
/// This function performs a GET request to 'https://jsonplaceholder.typicode.com/posts/1'.
///
/// The HTTP client is created and closed again once the request has been
/// completed. This is important to free up system resources and avoid possible
/// memory leaks. Reusing the same client keeps the HTTP connection open.
/// In addition, `_createHttpClient` is not called again for every HTTP request.
Future<void> _myDartApp() async {
  // Instantiate a new HTTP client. This client will be configured to use
  // the interceptors defined in `http.runWithClient` if any are set up.
  final client = http.Client();

  try {
    await client.get(Uri.parse('https://jsonplaceholder.typicode.com/posts/1'));
    await client.get(Uri.parse('https://jsonplaceholder.typicode.com/posts/2'));
    await client.get(Uri.parse('https://jsonplaceholder.typicode.com/posts/1'));
    await client.get(Uri.parse('https://jsonplaceholder.typicode.com/posts/3'));
  } finally {
    // Always close the client after use to free up system resources
    // and avoid potential memory leaks.
    client.close();
  }
}

http.Client _createHttpClient(HttpCache cache) => HttpClientProxy(
      interceptors: [
        // The order of interceptors is important.
        // This logging interceptor logs the original request and response.
        HttpLogger(/* level: Level.headers */),
        _CacheControlInterceptor(),
        // This logging interceptor logs the modified request and response
        // after the [_CacheControlInterceptor] has modified the cache control
        // header.
        // HttpLogger(/* level: Level.headers */),
        cache,
      ],
    );

/// This interceptor modifies the cache control header of the response
/// depending on the request url and the response mime type.
class _CacheControlInterceptor extends HttpInterceptorWrapper {
  @override
  Future<OnResponse> onResponse(http.StreamedResponse response) async {
    late final CacheControl cacheControl;

    if (response.request?.url.pathSegments.last == '/login') {
      // This is a login request, so we don't want to cache the response.
      cacheControl = CacheControl.sensitiveContent();
    } else if (extensionFromMime(response.headers[HttpHeaders.cacheControlHeader]!) == 'jpg') {
      // This is a jpg image, so we want to cache the response for a long time
      // and for all users (shared content).
      //
      // Note: in production, you should test if there is a cache control header
      // and don't force it with the postfix null assertion "bang" operator (!)
      cacheControl = CacheControl.sharedContent(
        maxAge: const Duration(days: 1),
        staleWhileRevalidate: const Duration(hours: 12),
        staleIfError: const Duration(days: 2),
      );
    } else {
      // This is a regular request, so we want to cache the response for a short
      // time and only for the current user (private content).
      // You should prune the cache with [HttpCache.deletePrivateContent()]
      // after the user has logged out.
      cacheControl = CacheControl.privateContent(
        maxAge: const Duration(seconds: 60),
        staleWhileRevalidate: const Duration(seconds: 30),
        staleIfError: const Duration(seconds: 300),
      );
    }

    // Create new headers map with the updated cache control
    final newHeaders = Map<String, String>.from(response.headers);
    newHeaders[HttpHeaders.cacheControlHeader] = cacheControl.toString();

    return OnResponse.next(response.copyWith(headers: newHeaders));
  }
}

// HttpOverrides to see the http(s) traffic in debug proxies like Charles Proxy
// ignore: unused_element
class _HttpOverrides extends HttpOverrides {
  @override
  HttpClient createHttpClient(SecurityContext? context) =>
      super.createHttpClient(context)
        ..badCertificateCallback = (_, __, ___) => true;

  @override
  String findProxyFromEnvironment(_, __) => 'PROXY 10.0.1.1:8888;';
}
copied to clipboard
0
likes
140
points
67
downloads

Publisher

verified publisherdasralph.de

Weekly Downloads

2024.09.08 - 2025.03.23

A Dart package for HTTP request caching and network optimization. Provides flexible caching mechanisms to improve performance and reduce network load in Dart and Flutter applications.

Repository (GitHub)
View/report issues

Topics

#http #network #cache

Documentation

API reference

License

MIT (license)

Dependencies

async, collection, file, fixnum, http, http_client_interceptor, http_client_logger, logging, meta, protobuf, uuid

More

Packages that depend on http_client_cache