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-transports.mddocs/

0

# Cache Transports

1

2

HTTPX transport implementations that add a caching layer on top of existing transports. These transports handle cache lookups, storage, validation, and seamlessly integrate with HTTPX's transport architecture.

3

4

## Capabilities

5

6

### Synchronous Cache Transport

7

8

HTTP transport that wraps existing synchronous transports to add caching capabilities.

9

10

```python { .api }

11

class CacheTransport(httpx.BaseTransport):

12

def __init__(self, *, transport: httpx.BaseTransport, storage=None, controller=None):

13

"""

14

Synchronous HTTP transport with caching.

15

16

Parameters:

17

- transport: Underlying HTTPX transport to wrap

18

- storage: Storage backend for cached responses (defaults to FileStorage)

19

- controller: Cache controller for caching logic (defaults to Controller())

20

"""

21

22

def handle_request(self, request: httpx.Request) -> httpx.Response:

23

"""Handle HTTP request with caching logic"""

24

25

def close(self) -> None:

26

"""Close transport and storage resources"""

27

28

def __enter__(self) -> "CacheTransport": ...

29

def __exit__(self, *args) -> None: ...

30

```

31

32

**Usage Examples:**

33

34

```python

35

import httpx

36

import hishel

37

38

# Wrap existing transport with caching

39

base_transport = httpx.HTTPTransport()

40

cache_transport = hishel.CacheTransport(

41

transport=base_transport,

42

storage=hishel.FileStorage(),

43

controller=hishel.Controller()

44

)

45

46

# Use directly with httpx

47

with httpx.Client(transport=cache_transport) as client:

48

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

49

50

# Custom transport configuration

51

import ssl

52

context = ssl.create_default_context()

53

base_transport = httpx.HTTPTransport(

54

verify=context,

55

cert=('client.crt', 'client.key'),

56

timeout=30.0

57

)

58

cache_transport = hishel.CacheTransport(transport=base_transport)

59

60

with httpx.Client(transport=cache_transport) as client:

61

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

62

```

63

64

### Asynchronous Cache Transport

65

66

HTTP transport that wraps existing asynchronous transports to add caching capabilities.

67

68

```python { .api }

69

class AsyncCacheTransport(httpx.AsyncBaseTransport):

70

def __init__(self, *, transport: httpx.AsyncBaseTransport, storage=None, controller=None):

71

"""

72

Asynchronous HTTP transport with caching.

73

74

Parameters:

75

- transport: Underlying async HTTPX transport to wrap

76

- storage: Async storage backend for cached responses (defaults to AsyncFileStorage)

77

- controller: Cache controller for caching logic (defaults to Controller())

78

"""

79

80

async def handle_async_request(self, request: httpx.Request) -> httpx.Response:

81

"""Handle HTTP request with caching logic asynchronously"""

82

83

async def aclose(self) -> None:

84

"""Close transport and storage resources asynchronously"""

85

86

async def __aenter__(self) -> "AsyncCacheTransport": ...

87

async def __aexit__(self, *args) -> None: ...

88

```

89

90

**Usage Examples:**

91

92

```python

93

import httpx

94

import hishel

95

import asyncio

96

97

async def main():

98

# Wrap existing async transport with caching

99

base_transport = httpx.AsyncHTTPTransport()

100

cache_transport = hishel.AsyncCacheTransport(

101

transport=base_transport,

102

storage=hishel.AsyncRedisStorage(),

103

controller=hishel.Controller(allow_heuristics=True)

104

)

105

106

# Use directly with async httpx

107

async with httpx.AsyncClient(transport=cache_transport) as client:

108

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

109

110

# Custom async transport configuration

111

import ssl

112

context = ssl.create_default_context()

113

base_transport = httpx.AsyncHTTPTransport(

114

verify=context,

115

http2=True,

116

limits=httpx.Limits(max_connections=100)

117

)

118

cache_transport = hishel.AsyncCacheTransport(transport=base_transport)

119

120

async with httpx.AsyncClient(transport=cache_transport) as client:

121

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

122

123

asyncio.run(main())

124

```

125

126

### Cache Streams

127

128

Stream implementations for serving cached response content efficiently.

129

130

```python { .api }

131

class CacheStream(httpx.SyncByteStream):

132

def __init__(self, httpcore_stream: Iterable[bytes]):

133

"""

134

Synchronous byte stream for cached responses.

135

136

Parameters:

137

- httpcore_stream: Iterable of bytes for response content

138

"""

139

140

def __iter__(self) -> Iterator[bytes]:

141

"""Iterate over response content bytes"""

142

143

def close(self) -> None:

144

"""Close the stream"""

145

146

class AsyncCacheStream(httpx.AsyncByteStream):

147

def __init__(self, httpcore_stream: AsyncIterable[bytes]):

148

"""

149

Asynchronous byte stream for cached responses.

150

151

Parameters:

152

- httpcore_stream: Async iterable of bytes for response content

153

"""

154

155

async def __aiter__(self) -> AsyncIterator[bytes]:

156

"""Async iterate over response content bytes"""

157

158

async def aclose(self) -> None:

159

"""Close the stream asynchronously"""

160

```

161

162

## Transport Integration

163

164

Cache transports seamlessly integrate with HTTPX's transport system:

165

166

### With Connection Pooling

167

168

```python

169

import httpx

170

import hishel

171

172

# HTTP/1.1 with connection pooling

173

base_transport = httpx.HTTPTransport(

174

limits=httpx.Limits(

175

max_keepalive_connections=20,

176

max_connections=100,

177

keepalive_expiry=30.0

178

)

179

)

180

cache_transport = hishel.CacheTransport(transport=base_transport)

181

182

with httpx.Client(transport=cache_transport) as client:

183

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

184

```

185

186

### With HTTP/2 Support

187

188

```python

189

import httpx

190

import hishel

191

192

# HTTP/2 with caching

193

base_transport = httpx.AsyncHTTPTransport(http2=True)

194

cache_transport = hishel.AsyncCacheTransport(transport=base_transport)

195

196

async with httpx.AsyncClient(transport=cache_transport) as client:

197

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

198

```

199

200

### With Custom Authentication

201

202

```python

203

import httpx

204

import hishel

205

206

# Custom auth with caching

207

auth = httpx.DigestAuth("username", "password")

208

base_transport = httpx.HTTPTransport()

209

cache_transport = hishel.CacheTransport(transport=base_transport)

210

211

with httpx.Client(transport=cache_transport, auth=auth) as client:

212

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

213

```

214

215

### With Proxy Support

216

217

```python

218

import httpx

219

import hishel

220

221

# Proxy transport with caching

222

proxy_transport = httpx.HTTPTransport(proxy="http://proxy.example.com:8080")

223

cache_transport = hishel.CacheTransport(transport=proxy_transport)

224

225

with httpx.Client(transport=cache_transport) as client:

226

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

227

```

228

229

## Cache Transport Behavior

230

231

### Request Flow

232

233

1. **Cache Lookup**: Check if request has a valid cached response

234

2. **Freshness Check**: Validate cached response freshness using Controller

235

3. **Conditional Request**: Send validation request if needed (ETag, Last-Modified)

236

4. **Response Handling**: Store new responses or update cached responses

237

5. **Response Serving**: Return cached or fresh response to client

238

239

### Error Handling

240

241

Cache transports gracefully handle errors:

242

243

- **Storage Errors**: Fall back to network requests if cache storage fails

244

- **Network Errors**: Serve stale responses when allowed and available

245

- **Serialization Errors**: Skip caching and serve fresh responses

246

- **Validation Errors**: Treat as cache miss and fetch fresh response

247

248

### 504 Gateway Timeout

249

250

When network fails and no cached response is available:

251

252

```python

253

# Returns 504 status code when network is unavailable

254

# and no cached response exists

255

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

256

assert response.status_code == 504

257

```

258

259

## Advanced Usage

260

261

### Custom Transport Chains

262

263

```python

264

import httpx

265

import hishel

266

267

# Chain multiple transports

268

retry_transport = httpx.HTTPTransport(retries=3)

269

cache_transport = hishel.CacheTransport(transport=retry_transport)

270

271

# Custom middleware transport

272

class LoggingTransport(httpx.BaseTransport):

273

def __init__(self, transport):

274

self.transport = transport

275

276

def handle_request(self, request):

277

print(f"Requesting: {request.url}")

278

response = self.transport.handle_request(request)

279

print(f"Response: {response.status_code}")

280

return response

281

282

logging_transport = LoggingTransport(cache_transport)

283

284

with httpx.Client(transport=logging_transport) as client:

285

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

286

```

287

288

### Manual Transport Usage

289

290

```python

291

import httpx

292

import hishel

293

294

# Use transport directly without client

295

transport = hishel.CacheTransport(

296

transport=httpx.HTTPTransport(),

297

storage=hishel.InMemoryStorage(),

298

controller=hishel.Controller()

299

)

300

301

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

302

response = transport.handle_request(request)

303

304

transport.close()

305

```