CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-hishel

Persistent cache implementation for httpx and httpcore following RFC 9111 specification

74

1.48x
Overview
Eval results
Files

http-headers.mddocs/

HTTP Headers

Cache-Control and Vary header parsing and representation with RFC 9111 compliant validation and directive handling. These classes provide structured access to HTTP caching headers.

Capabilities

Cache-Control Header

Class representing Cache-Control header directives with validation and parsing functionality.

class CacheControl:
    def __init__(self, *, immutable=False, max_age=None, max_stale=None,
                 min_fresh=None, must_revalidate=False, must_understand=False,
                 no_cache=False, no_store=False, no_transform=False,
                 only_if_cached=False, private=False, proxy_revalidate=False,
                 public=False, s_maxage=None):
        """
        Represent Cache-Control header directives.
        
        Parameters:
        - immutable: Response will not change over time (RFC 8246)
        - max_age: Maximum age in seconds for cached response
        - max_stale: Client will accept stale response up to specified seconds
        - min_fresh: Client wants response fresh for at least specified seconds
        - must_revalidate: Must revalidate stale responses
        - must_understand: Override no-store under certain circumstances
        - no_cache: Must revalidate before using cached response
        - no_store: Must not store request or response
        - no_transform: Must not transform response content
        - only_if_cached: Only use cached response, don't contact server
        - private: Response is private to single user
        - proxy_revalidate: Shared caches must revalidate
        - public: Response may be cached by any cache
        - s_maxage: Maximum age for shared caches
        """

Usage Examples:

import hishel

# Create Cache-Control directives
cache_control = hishel.CacheControl(
    max_age=3600,        # 1 hour
    public=True,         # Can be cached by any cache
    must_revalidate=True # Must revalidate when stale
)

# Access individual directives
print(cache_control.max_age)      # 3600
print(cache_control.public)       # True
print(cache_control.no_cache)     # False

# Private cache directives
private_cache = hishel.CacheControl(
    max_age=1800,       # 30 minutes
    private=True,       # Private to single user
    no_store=False      # Can be stored
)

Cache-Control Validation

Class method for validating and normalizing Cache-Control directives from parsed headers.

@classmethod
def validate(cls, directives: dict[str, Any]) -> dict[str, Any]:
    """
    Validate and normalize Cache-Control directives.
    
    Parameters:
    - directives: Dictionary of directive names to values
    
    Returns:
    - Validated and normalized directives dictionary
    
    Raises:
    - ValidationError: If directive values are invalid
    """

Cache-Control Parsing

Function to parse Cache-Control header values into a CacheControl object.

def parse_cache_control(cache_control_values: list[str]) -> CacheControl:
    """
    Parse Cache-Control header values into structured representation.
    
    Parameters:
    - cache_control_values: List of Cache-Control header value strings
    
    Returns:
    - CacheControl object with parsed directives
    
    Raises:
    - ParseError: If header values cannot be parsed
    """

Usage Examples:

import hishel

# Parse Cache-Control header
header_values = ["max-age=3600, public", "must-revalidate"]
cache_control = hishel.parse_cache_control(header_values)

print(cache_control.max_age)           # 3600
print(cache_control.public)            # True
print(cache_control.must_revalidate)   # True

# Parse complex directives
complex_header = ['no-cache="Set-Cookie, Authorization", max-age=0']
cache_control = hishel.parse_cache_control([complex_header])
print(cache_control.no_cache)  # ['Set-Cookie', 'Authorization']

# Handle quoted values
quoted_header = ['private="user-info", s-maxage=7200']
cache_control = hishel.parse_cache_control([quoted_header])
print(cache_control.private)   # ['user-info']
print(cache_control.s_maxage)  # 7200

Vary Header

Class representing HTTP Vary header for content negotiation caching.

class Vary:
    def __init__(self, values: list[str]):
        """
        Represent Vary header field names.
        
        Parameters:
        - values: List of header field names that affect response content
        """
    
    @classmethod
    def from_value(cls, vary_values: list[str]) -> "Vary":
        """
        Create Vary object from header value strings.
        
        Parameters:
        - vary_values: List of Vary header value strings
        
        Returns:
        - Vary object with parsed field names
        """

Usage Examples:

import hishel

# Create Vary header from field names
vary = hishel.Vary(values=["Accept", "Accept-Encoding", "User-Agent"])

# Parse from header values
vary_headers = ["Accept, Accept-Encoding", "User-Agent"]
vary = hishel.Vary.from_value(vary_headers)

# Access field names
print(vary._values)  # ['Accept', 'Accept-Encoding', 'User-Agent']

# Handle wildcard
wildcard_vary = hishel.Vary.from_value(["*"])
print(wildcard_vary._values)  # ['*']

Header Directive Reference

Time-based Directives

Time values are specified in seconds:

  • max-age: Maximum time response is considered fresh
  • s-maxage: Maximum time for shared caches (overrides max-age)
  • max-stale: Client accepts stale response up to specified time
  • min-fresh: Client wants response fresh for at least specified time

Boolean Directives

Directives that are either present (True) or absent (False):

  • immutable: Response content will never change
  • must-revalidate: Must revalidate stale responses with origin server
  • must-understand: Special handling for must-understand responses
  • no-store: Must not store request or any response
  • no-transform: Must not modify response content
  • only-if-cached: Only return cached response, don't contact server
  • proxy-revalidate: Shared caches must revalidate
  • public: Response may be cached by any cache

List Directives

Directives that can have optional field name lists:

  • no-cache: Must revalidate (optionally only specified headers)
  • private: Response is private (optionally only specified headers)

Error Handling

Header parsing can raise specific exceptions:

class CacheControlError(Exception):
    """Base exception for Cache-Control processing"""

class ParseError(CacheControlError):
    """Exception raised when parsing Cache-Control header fails"""

class ValidationError(CacheControlError):
    """Exception raised when validating Cache-Control directives fails"""

Usage Examples:

import hishel

try:
    # Invalid directive value
    cache_control = hishel.parse_cache_control(["max-age=invalid"])
except hishel.ValidationError as e:
    print(f"Validation error: {e}")

try:
    # Malformed header
    cache_control = hishel.parse_cache_control(['max-age="unclosed quote'])
except hishel.ParseError as e:
    print(f"Parse error: {e}")

Advanced Usage

Custom Directive Handling

import hishel

# Parse headers and inspect all directives
cache_control = hishel.parse_cache_control([
    "max-age=3600, public, custom-directive=value"
])

# Access standard directives
print(cache_control.max_age)  # 3600
print(cache_control.public)   # True

# Custom directives are not directly accessible
# but are preserved in the parsing process

Integration with HTTP Libraries

import httpx
import hishel

# Extract Cache-Control from response
response = httpx.get("https://api.example.com/data")
cache_control_headers = [
    value.decode() for key, value in response.headers.raw
    if key.lower() == b'cache-control'
]

if cache_control_headers:
    cache_control = hishel.parse_cache_control(cache_control_headers)
    print(f"Max age: {cache_control.max_age}")
    print(f"Public: {cache_control.public}")

Content Negotiation with Vary

import hishel

# Handle content negotiation caching
vary = hishel.Vary.from_value(["Accept", "Accept-Language"])

# In cache key generation, these headers would be considered:
# - Accept: application/json vs text/html
# - Accept-Language: en-US vs fr-FR
# Each combination gets its own cache entry

Install with Tessl CLI

npx tessl i tessl/pypi-hishel

docs

cache-clients.md

cache-controller.md

cache-transports.md

http-headers.md

index.md

serializers.md

storage-backends.md

testing-utilities.md

tile.json