or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cache-clients.mdcache-controller.mdcache-transports.mdhttp-headers.mdindex.mdserializers.mdstorage-backends.mdtesting-utilities.md

cache-controller.mddocs/

0

# Cache Controller

1

2

RFC 9111 compliant cache controller that implements HTTP caching logic, determines response cacheability, validates cached responses, and handles cache directives from HTTP headers.

3

4

## Capabilities

5

6

### Cache Controller

7

8

The main controller class that implements HTTP caching specification logic for determining what to cache and when to serve cached responses.

9

10

```python { .api }

11

class Controller:

12

def __init__(self, *, cacheable_methods=None, cacheable_status_codes=None,

13

cache_private=True, allow_heuristics=False, clock=None,

14

allow_stale=False, always_revalidate=False, force_cache=False,

15

key_generator=None):

16

"""

17

Initialize cache controller with caching policies.

18

19

Parameters:

20

- cacheable_methods: HTTP methods to cache (defaults to ["GET"])

21

- cacheable_status_codes: Status codes to cache (defaults to [200, 301, 308])

22

- cache_private: Whether to cache responses with private directives

23

- allow_heuristics: Enable heuristic caching for responses without explicit cache headers

24

- clock: Custom clock implementation for time-based operations

25

- allow_stale: Whether to serve stale responses when allowed

26

- always_revalidate: Always revalidate cached responses

27

- force_cache: Force caching regardless of cache headers

28

- key_generator: Custom function for generating cache keys

29

"""

30

```

31

32

**Usage Examples:**

33

34

```python

35

import hishel

36

37

# Default controller (GET requests, status codes 200/301/308)

38

controller = hishel.Controller()

39

40

# Conservative caching (only explicitly cacheable responses)

41

controller = hishel.Controller(

42

cacheable_methods=["GET", "HEAD"],

43

cacheable_status_codes=[200],

44

cache_private=False,

45

allow_heuristics=False

46

)

47

48

# Aggressive caching with heuristics

49

controller = hishel.Controller(

50

cacheable_methods=["GET", "HEAD", "POST"],

51

cacheable_status_codes=[200, 201, 204, 301, 308, 404],

52

allow_heuristics=True,

53

allow_stale=True

54

)

55

56

# Always revalidate for critical applications

57

controller = hishel.Controller(

58

always_revalidate=True,

59

force_cache=False

60

)

61

62

# Use with cache client

63

with hishel.CacheClient(controller=controller) as client:

64

response = client.get("https://api.example.com/data")

65

```

66

67

### Cacheability Determination

68

69

Method to determine if a response can be cached based on request/response headers and controller configuration.

70

71

```python { .api }

72

def is_cachable(self, request: Request, response: Response) -> bool:

73

"""

74

Determine whether the response may be cached.

75

76

Parameters:

77

- request: HTTP request object

78

- response: HTTP response object

79

80

Returns:

81

- bool: True if response can be cached, False otherwise

82

83

Implements RFC 9111 Section 3 logic for storing responses in caches.

84

"""

85

```

86

87

**Usage Examples:**

88

89

```python

90

from httpcore import Request, Response

91

import hishel

92

93

controller = hishel.Controller()

94

95

# Check if response is cacheable

96

request = Request(b"GET", b"https://api.example.com/data")

97

response = Response(200, [(b"cache-control", b"max-age=3600")])

98

99

if controller.is_cachable(request, response):

100

print("Response can be cached")

101

else:

102

print("Response should not be cached")

103

```

104

105

### Cache Response Construction

106

107

Method to construct responses from cache, handling validation, freshness checks, and conditional requests.

108

109

```python { .api }

110

def construct_response_from_cache(self, request: Request, response: Response,

111

original_request: Request) -> Request | Response | None:

112

"""

113

Determine how to use a cached response for the current request.

114

115

Parameters:

116

- request: Current HTTP request

117

- response: Cached HTTP response

118

- original_request: Original request that created the cached response

119

120

Returns:

121

- Response: Cached response is valid and can be used

122

- Request: Cached response needs revalidation (returns conditional request)

123

- None: Cached response cannot be used

124

125

Implements RFC 9111 Section 4 logic for constructing responses from caches.

126

"""

127

```

128

129

### Validation Response Handling

130

131

Method to handle validation responses, particularly 304 Not Modified responses.

132

133

```python { .api }

134

def handle_validation_response(self, old_response: Response, new_response: Response) -> Response:

135

"""

136

Handle incoming validation response from server.

137

138

Parameters:

139

- old_response: Previously cached response

140

- new_response: Validation response from server

141

142

Returns:

143

- Response: Updated response (old response with new headers for 304,

144

or new response for other status codes)

145

146

Implements RFC 9111 Section 4.3.4 logic for handling validation responses.

147

"""

148

```

149

150

**Usage Examples:**

151

152

```python

153

# Handle 304 Not Modified response

154

cached_response = Response(200, [(b"etag", b'"abc123"')])

155

validation_response = Response(304, [(b"cache-control", b"max-age=7200")])

156

157

updated_response = controller.handle_validation_response(

158

cached_response,

159

validation_response

160

)

161

# Returns cached_response with updated headers from validation_response

162

```

163

164

## Cache Key Generation

165

166

The controller uses a default key generation strategy but supports custom key generators:

167

168

```python

169

import hashlib

170

from httpcore import Request

171

172

def custom_key_generator(request: Request, body: bytes = b"") -> str:

173

"""

174

Generate cache key from request and body.

175

176

Parameters:

177

- request: HTTP request object

178

- body: Request body bytes

179

180

Returns:

181

- str: Cache key for the request

182

"""

183

# Custom logic here

184

url = request.url

185

method = request.method

186

return hashlib.sha256(method + url + body).hexdigest()

187

188

controller = hishel.Controller(key_generator=custom_key_generator)

189

```

190

191

## Caching Constants

192

193

```python { .api }

194

HEURISTICALLY_CACHEABLE_STATUS_CODES: tuple[int, ...] = (

195

200, 203, 204, 206, 300, 301, 308, 404, 405, 410, 414, 501

196

)

197

```

198

199

Status codes that are considered cacheable when heuristic caching is enabled and no explicit cache headers are present.

200

201

## Clock Implementations

202

203

Custom clock implementations for testing and time manipulation:

204

205

```python { .api }

206

class BaseClock:

207

def now(self) -> int:

208

"""Return current timestamp as integer seconds"""

209

210

class Clock(BaseClock):

211

def now(self) -> int:

212

"""Return current Unix timestamp"""

213

```

214

215

**Usage Examples:**

216

217

```python

218

import time

219

220

class TestClock(hishel.BaseClock):

221

def __init__(self, fixed_time=None):

222

self.fixed_time = fixed_time or time.time()

223

224

def now(self):

225

return int(self.fixed_time)

226

227

# Use custom clock for testing

228

test_clock = TestClock(fixed_time=1609459200) # 2021-01-01

229

controller = hishel.Controller(clock=test_clock)

230

```

231

232

## Cache Behavior Control

233

234

The controller provides fine-grained control over caching behavior:

235

236

- **Method-based caching**: Control which HTTP methods are cached

237

- **Status code filtering**: Specify which response status codes to cache

238

- **Private response handling**: Control caching of responses with Cache-Control: private

239

- **Heuristic caching**: Enable caching based on heuristics when no explicit cache headers

240

- **Stale response serving**: Allow serving stale responses when permitted

241

- **Forced revalidation**: Always revalidate cached responses

242

- **Forced caching**: Cache responses regardless of cache headers

243

- **Custom key generation**: Use custom logic for generating cache keys