CacheControlHeader.parse constructor

CacheControlHeader.parse(
  1. Iterable<String> values
)

Parses the Cache-Control header value and returns a CacheControlHeader instance.

This method splits the header value by commas, trims each directive, and processes common cache directives like no-cache, no-store, max-age, etc.

Implementation

factory CacheControlHeader.parse(final Iterable<String> values) {
  final directives = values.splitTrimAndFilterUnique();

  if (directives.isEmpty) {
    throw const FormatException('Directives cannot be empty');
  }

  // Check if at least one directive is valid
  final foundOneDirective = directives.any(
    (final directive) => _validDirectives.any(
      (final validDirective) => directive.startsWith(validDirective),
    ),
  );

  // Check for invalid directives
  final invalidDirectives = directives.where(
    (final directive) => !_validDirectives.any(
      (final validDirective) => directive.startsWith(validDirective),
    ),
  );

  if (!foundOneDirective || invalidDirectives.isNotEmpty) {
    throw const FormatException('Invalid directive');
  }

  final bool noCache = directives.contains(_noCacheDirective);
  final bool noStore = directives.contains(_noStoreDirective);
  final bool mustRevalidate = directives.contains(_mustRevalidateDirective);
  final bool proxyRevalidate = directives.contains(_proxyRevalidateDirective);
  final bool noTransform = directives.contains(_noTransformDirective);
  final bool onlyIfCached = directives.contains(_onlyIfCachedDirective);
  final bool immutable = directives.contains(_immutableDirective);
  final bool mustUnderstand = directives.contains(_mustUnderstandDirective);
  int? maxAge;
  int? staleWhileRevalidate;
  int? sMaxAge;
  int? staleIfError;
  int? maxStale;
  int? minFresh;
  final bool publicCache = directives.contains(_publicDirective);
  final bool privateCache = directives.contains(_privateDirective);

  for (final directive in directives) {
    if (directive.startsWith('$_maxAgeDirective=')) {
      maxAge = int.tryParse(directive.substring(_maxAgeDirective.length + 1));
    } else if (directive.startsWith('$_staleWhileRevalidateDirective=')) {
      staleWhileRevalidate = int.tryParse(
        directive.substring(_staleWhileRevalidateDirective.length + 1),
      );
    } else if (directive.startsWith('$_sMaxAgeDirective=')) {
      sMaxAge = int.tryParse(
        directive.substring(_sMaxAgeDirective.length + 1),
      );
    } else if (directive.startsWith('$_staleIfErrorDirective=')) {
      staleIfError = int.tryParse(
        directive.substring(_staleIfErrorDirective.length + 1),
      );
    } else if (directive.startsWith('$_maxStaleDirective=')) {
      maxStale = int.tryParse(
        directive.substring(_maxStaleDirective.length + 1),
      );
    } else if (directive.startsWith('$_minFreshDirective=')) {
      minFresh = int.tryParse(
        directive.substring(_minFreshDirective.length + 1),
      );
    }
  }

  if (publicCache == true && privateCache == true) {
    throw const FormatException('Cannot be both public and private');
  }

  if (maxAge != null && staleWhileRevalidate != null) {
    throw const FormatException(
      'Cannot have both max-age and stale-while-revalidate directives',
    );
  }

  return CacheControlHeader(
    noCache: noCache,
    noStore: noStore,
    mustRevalidate: mustRevalidate,
    proxyRevalidate: proxyRevalidate,
    noTransform: noTransform,
    onlyIfCached: onlyIfCached,
    maxAge: maxAge,
    staleWhileRevalidate: staleWhileRevalidate,
    sMaxAge: sMaxAge,
    publicCache: publicCache,
    privateCache: privateCache,
    staleIfError: staleIfError,
    maxStale: maxStale,
    minFresh: minFresh,
    immutable: immutable,
    mustUnderstand: mustUnderstand,
  );
}