Skip to content

anthochamp/dart-httpx-client

Repository files navigation

Yet Another HTTP client

HTTP1/2 client in the style of Dart's HttpClient with an integrated RFC-compliant private cache.

This package exists to support the ac_fetch package. You might want to check it, it allows easier data management.

Features

What it implements:

  • HTTP/1 client using dart:io's HttpClient;
  • HTTP/2 client using http2 package with automatic fallback to HTTP/1 without severing the TCP connection;
  • HTTP headers (parsing, folding, sensitive-data-aware formatting, etc.);
  • HTTP credentials;
  • RFC-7231 and RFC-5861 compliant HTTP private cache (with limitations, see below).

What it does NOT implement yet:

HTTP cache limitations:

  • Content negociation fields are not supported for cache entry selection of Vary-ing response (meaning that if multiple cached entries are available for a given resource, cache will make a conditional request to the server to disambiguate which one should be returned),
  • Caching of responses with partial content is not supported.
  • Caching of POST responses is disabled.

Usage

Simple request

const client = HttpxClient();

final request = client.createRequest(
    method: 'POST',
    uri: Uri.parse('https://www.example.com'),
    headers: HttpxHeaders.fromMap({
        'Content-Type': 'application/json; charset=utf-8',
        'Accept': 'application/json',
    }),
);

await request.write('{"data": "hello world!"}'.codeUnits);

final response = await request.dispose();

final data = await response.fold(<int>[], (previous, element) => previous..addAll(element));

await response.dispose();

print(data);

Cache store

import 'package:path_provider/path_provider.dart' as path_provider;
import 'package:hive/hive.dart';

final supportDir =
    await path_provider.getApplicationSupportDirectory();

// Always use an encrypted store for protecting your user data !
// (and use appropriate means to protect its key)
final encryptionCipher =
    HiveAesCipher('01234567890123456789012345678901'.codeUnits);

HttpxCacheHiveStore store = HttpxCacheHiveStore(
    boxPath: supportDir.path,
    encryptionCipher: encryptionCipher,
);

try {
    await store.open();
} catch (_) {
    // if the store fail to open, delete it from disk
    await Hive.deleteBoxFromDisk(
      HttpxCacheHiveStore.defaultBoxName,
      path: supportDir.path,
    );

    // and try to re-open
    await store.open();
}

final client = HttpxClient();

client.cacheStores.add(store);

// do request...

Cache Policy

When making a request, you can policy the cache to act in a different way that it is supposed to using the cachePolicy property argument of the HttpxClient.createRequest method.

const client = HttpxClient();
final request = client.createRequest(
    method: 'GET',
    uri: Uri.parse('https://www.example.com'),
    cachePolicy: HttpxCachePolicy.standard,
);

Policies

CachePolicy Description
standard (default) Standard behaviour.
straightToNetwork Behaves as if there is no HTTP cache for the request. It will still update the cache with the response.
ignoreDirectives Uses any response in the HTTP cache matching the request, not paying attention to Pragma / Cache Control directives in both the request and the cached response(s).
staleWhileRevalidate Enable stale-while-revalidate even for cached responses which do not have the directive (or if it's past its lifetime). It does not bypass Pragma / Cache-Control directives (no-cache and/or min-fresh directives may prevent revalidation in background).

Cache directives

You can also control the cache using the Pragma / Cache-Control directives in the request :