hishel 1.0.0.dev2__tar.gz → 1.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. {hishel-1.0.0.dev2 → hishel-1.1.0}/CHANGELOG.md +52 -0
  2. {hishel-1.0.0.dev2 → hishel-1.1.0}/PKG-INFO +225 -18
  3. {hishel-1.0.0.dev2 → hishel-1.1.0}/README.md +170 -17
  4. {hishel-1.0.0.dev2 → hishel-1.1.0}/hishel/__init__.py +26 -17
  5. hishel-1.1.0/hishel/_async_cache.py +213 -0
  6. hishel-1.1.0/hishel/_async_httpx.py +236 -0
  7. {hishel-1.0.0.dev2 → hishel-1.1.0}/hishel/_core/_headers.py +11 -1
  8. {hishel-1.0.0.dev2 → hishel-1.1.0}/hishel/_core/_spec.py +101 -120
  9. hishel-1.1.0/hishel/_core/_storages/_async_base.py +71 -0
  10. hishel-1.0.0.dev2/hishel/_core/_async/_storages/_sqlite.py → hishel-1.1.0/hishel/_core/_storages/_async_sqlite.py +100 -134
  11. hishel-1.1.0/hishel/_core/_storages/_packing.py +144 -0
  12. hishel-1.1.0/hishel/_core/_storages/_sync_base.py +71 -0
  13. hishel-1.0.0.dev2/hishel/_core/_sync/_storages/_sqlite.py → hishel-1.1.0/hishel/_core/_storages/_sync_sqlite.py +100 -134
  14. {hishel-1.0.0.dev2 → hishel-1.1.0}/hishel/_core/models.py +93 -33
  15. hishel-1.1.0/hishel/_policies.py +49 -0
  16. hishel-1.1.0/hishel/_sync_cache.py +213 -0
  17. hishel-1.1.0/hishel/_sync_httpx.py +236 -0
  18. {hishel-1.0.0.dev2 → hishel-1.1.0}/hishel/_utils.py +49 -2
  19. hishel-1.1.0/hishel/asgi.py +400 -0
  20. hishel-1.1.0/hishel/fastapi.py +263 -0
  21. hishel-1.1.0/hishel/httpx.py +12 -0
  22. {hishel-1.0.0.dev2 → hishel-1.1.0}/hishel/requests.py +28 -22
  23. {hishel-1.0.0.dev2 → hishel-1.1.0}/pyproject.toml +13 -2
  24. hishel-1.0.0.dev2/hishel/_async_cache.py +0 -174
  25. hishel-1.0.0.dev2/hishel/_core/__init__.py +0 -59
  26. hishel-1.0.0.dev2/hishel/_core/_base/_storages/_base.py +0 -272
  27. hishel-1.0.0.dev2/hishel/_core/_base/_storages/_packing.py +0 -165
  28. hishel-1.0.0.dev2/hishel/_sync_cache.py +0 -174
  29. hishel-1.0.0.dev2/hishel/httpx.py +0 -335
  30. {hishel-1.0.0.dev2 → hishel-1.1.0}/.gitignore +0 -0
  31. {hishel-1.0.0.dev2 → hishel-1.1.0}/LICENSE +0 -0
  32. {hishel-1.0.0.dev2 → hishel-1.1.0}/hishel/py.typed +0 -0
@@ -2,10 +2,62 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## 1.1.0 - 2025-10-31
6
+ ### ⚙️ Miscellaneous Tasks
7
+ - Add in memory example
8
+
9
+ ### 🐛 Bug Fixes
10
+ - Pass any response with non-expected status code on revalidation to client
11
+
12
+ ### 🚀 Features
13
+ - Allow setting storage base with via `database_path` for sqlite storage
14
+
15
+ ## 1.0.0 - 2025-10-28
16
+ ### ⚙️ Miscellaneous Tasks
17
+ - Add examples, improve docs
18
+
19
+ ## 1.0.0b1 - 2025-10-28
20
+ ### ♻️ Refactoring
21
+ - Add policies
22
+
23
+ ### ⚙️ Miscellaneous Tasks
24
+ - Improve sans-io diagram colors
25
+ - Add graphql docs
26
+
27
+ ### 🐛 Bug Fixes
28
+ - Body-sensitive responses caching
29
+ - Filter out `Transfer-Encoding` header for asgi responses
30
+
31
+ ### 🚀 Features
32
+ - Add global `use_body_key` setting
33
+
34
+ ## 1.0.0.dev3 - 2025-10-26
35
+ ### ♻️ Refactoring
36
+ - Replace pairs with entries, simplify storage API
37
+ - Automatically generate httpx sync integration from async
38
+
39
+ ### ⚙️ Miscellaneous Tasks
40
+ - Simplify metadata docs
41
+ - Add custom integrations docs
42
+ - More robust compressed response caching
43
+
44
+ ### 🐛 Bug Fixes
45
+ - Add missing permissions into `publish.yml`
46
+ - Raise on consumed httpx streams, which we can't store as is (it's already decoded)
47
+ - Fix compressed data caching for requests
48
+ - Handle httpx iterable usage instead of iterator correctly
49
+ - Add date header for proper age calculation
50
+
51
+ ### 🚀 Features
52
+ - Add integrations with fastapi and asgi
53
+ - Add blacksheep integration examples
54
+ - Add logging for asgi
55
+
5
56
  ## 1.0.0.dev2 - 2025-10-21
6
57
  ### ⚙️ Miscellaneous Tasks
7
58
  - Remove redundant utils and tests
8
59
  - Add import without extras check in ci
60
+ - Fix time travel date, explicitly specify the timezone
9
61
 
10
62
  ### 🐛 Bug Fixes
11
63
  - Fix check for storing auth requests
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hishel
3
- Version: 1.0.0.dev2
3
+ Version: 1.1.0
4
4
  Summary: Elegant HTTP Caching for Python
5
5
  Project-URL: Homepage, https://hishel.com
6
6
  Project-URL: Source, https://github.com/karpetrosyan/hishel
@@ -29,6 +29,8 @@ Requires-Dist: typing-extensions>=4.14.1
29
29
  Provides-Extra: async
30
30
  Requires-Dist: anyio>=4.9.0; extra == 'async'
31
31
  Requires-Dist: anysqlite>=0.0.5; extra == 'async'
32
+ Provides-Extra: fastapi
33
+ Requires-Dist: fastapi>=0.119.1; extra == 'fastapi'
32
34
  Provides-Extra: httpx
33
35
  Requires-Dist: anyio>=4.9.0; extra == 'httpx'
34
36
  Requires-Dist: anysqlite>=0.0.5; extra == 'httpx'
@@ -37,6 +39,7 @@ Provides-Extra: requests
37
39
  Requires-Dist: requests>=2.32.5; extra == 'requests'
38
40
  Description-Content-Type: text/markdown
39
41
 
42
+
40
43
  <p align="center">
41
44
  <img alt="Hishel Logo" width="350" src="https://raw.githubusercontent.com/karpetrosyan/hishel/master/docs/static/Shelkopryad_350x250_yellow.png#gh-dark-mode-only">
42
45
  <img alt="Hishel Logo" width="350" src="https://raw.githubusercontent.com/karpetrosyan/hishel/master/docs/static/Shelkopryad_350x250_black.png#gh-light-mode-only">
@@ -73,14 +76,16 @@ Description-Content-Type: text/markdown
73
76
  ## ✨ Features
74
77
 
75
78
  - 🎯 **RFC 9111 Compliant** - Fully compliant with the latest HTTP caching specification
76
- - 🔌 **Easy Integration** - Drop-in support for HTTPX and Requests
79
+ - 🔌 **Easy Integration** - Drop-in support for HTTPX, Requests, ASGI, FastAPI, and BlackSheep
77
80
  - 💾 **Flexible Storage** - SQLite backend with more coming soon
78
81
  - ⚡ **High Performance** - Efficient caching with minimal overhead
79
82
  - 🔄 **Async & Sync** - Full support for both synchronous and asynchronous workflows
80
83
  - 🎨 **Type Safe** - Fully typed with comprehensive type hints
81
84
  - 🧪 **Well Tested** - Extensive test coverage and battle-tested
82
- - 🎛️ **Configurable** - Fine-grained control over caching behavior
83
- - 🌐 **Future Ready** - Designed for easy integration with any HTTP client/server
85
+ - 🎛️ **Configurable** - Fine-grained control over caching behavior with flexible policies
86
+ - 💨 **Memory Efficient** - Streaming support prevents loading large payloads into memory
87
+ - 🌐 **Universal** - Works with any ASGI application (Starlette, Litestar, BlackSheep, etc.)
88
+ - 🎯 **GraphQL Support** - Cache GraphQL queries with body-sensitive content caching
84
89
 
85
90
  ## 📦 Installation
86
91
 
@@ -90,19 +95,23 @@ pip install hishel
90
95
 
91
96
  ### Optional Dependencies
92
97
 
93
- Install with specific HTTP client support:
98
+ Install with specific integration support:
94
99
 
95
100
  ```bash
96
101
  pip install hishel[httpx] # For HTTPX support
97
102
  pip install hishel[requests] # For Requests support
103
+ pip install hishel[fastapi] # For FastAPI support (includes ASGI)
98
104
  ```
99
105
 
100
- Or install both:
106
+ Or install multiple:
101
107
 
102
108
  ```bash
103
- pip install hishel[httpx,requests]
109
+ pip install hishel[httpx,requests,fastapi]
104
110
  ```
105
111
 
112
+ > [!NOTE]
113
+ > ASGI middleware has no extra dependencies - it's included in the base installation.
114
+
106
115
  ## 🚀 Quick Start
107
116
 
108
117
  ### With HTTPX
@@ -156,23 +165,112 @@ response = session.get("https://api.example.com/data")
156
165
  print(response.headers.get("X-Hishel-From-Cache")) # "True"
157
166
  ```
158
167
 
168
+ ### With ASGI Applications
169
+
170
+ Add caching middleware to any ASGI application:
171
+
172
+ ```python
173
+ from hishel.asgi import ASGICacheMiddleware
174
+
175
+ # Wrap your ASGI app
176
+ app = ASGICacheMiddleware(app)
177
+
178
+ # Or configure with options
179
+ from hishel import AsyncSqliteStorage, CacheOptions, SpecificationPolicy
180
+
181
+ app = ASGICacheMiddleware(
182
+ app,
183
+ storage=AsyncSqliteStorage(),
184
+ policy=SpecificationPolicy(
185
+ cache_options=CacheOptions(shared=True)
186
+ ),
187
+ )
188
+ ```
189
+
190
+ ### With FastAPI
191
+
192
+ Add Cache-Control headers using the `cache()` dependency:
193
+
194
+ ```python
195
+ from fastapi import FastAPI
196
+ from hishel.fastapi import cache
197
+
198
+ app = FastAPI()
199
+
200
+ @app.get("/api/data", dependencies=[cache(max_age=300, public=True)])
201
+ async def get_data():
202
+ # Cache-Control: public, max-age=300
203
+ return {"data": "cached for 5 minutes"}
204
+
205
+ # Optionally wrap with ASGI middleware for local caching according to specified rules
206
+ from hishel.asgi import ASGICacheMiddleware
207
+ from hishel import AsyncSqliteStorage
208
+
209
+ app = ASGICacheMiddleware(app, storage=AsyncSqliteStorage())
210
+ ```
211
+
212
+ ### With BlackSheep
213
+
214
+ Use BlackSheep's native `cache_control` decorator with Hishel's ASGI middleware:
215
+
216
+ ```python
217
+ from blacksheep import Application, get
218
+ from blacksheep.server.headers.cache import cache_control
219
+
220
+ app = Application()
221
+
222
+ @get("/api/data")
223
+ @cache_control(max_age=300, public=True)
224
+ async def get_data():
225
+ # Cache-Control: public, max-age=300
226
+ return {"data": "cached for 5 minutes"}
227
+ ```
228
+
159
229
  ## 🎛️ Advanced Configuration
160
230
 
161
- ### Custom Cache Options
231
+ ### Caching Policies
232
+
233
+ Hishel supports two types of caching policies:
234
+
235
+ **SpecificationPolicy** - RFC 9111 compliant HTTP caching (default):
162
236
 
163
237
  ```python
164
- from hishel import CacheOptions
238
+ from hishel import CacheOptions, SpecificationPolicy
165
239
  from hishel.httpx import SyncCacheClient
166
240
 
167
241
  client = SyncCacheClient(
168
- cache_options=CacheOptions(
169
- shared=False, # Use as private cache (browser-like)
170
- supported_methods=["GET", "HEAD", "POST"], # Cache GET, HEAD, and POST
171
- allow_stale=True # Allow serving stale responses
242
+ policy=SpecificationPolicy(
243
+ cache_options=CacheOptions(
244
+ shared=False, # Use as private cache (browser-like)
245
+ supported_methods=["GET", "HEAD", "POST"], # Cache GET, HEAD, and POST
246
+ allow_stale=True # Allow serving stale responses
247
+ )
248
+ )
249
+ )
250
+ ```
251
+
252
+ **FilterPolicy** - Custom filtering logic for fine-grained control:
253
+
254
+ ```python
255
+ from hishel import FilterPolicy, BaseFilter, Request
256
+ from hishel.httpx import AsyncCacheClient
257
+
258
+ class CacheOnlyAPIRequests(BaseFilter[Request]):
259
+ def needs_body(self) -> bool:
260
+ return False
261
+
262
+ def apply(self, item: Request, body: bytes | None) -> bool:
263
+ return "/api/" in str(item.url)
264
+
265
+ client = AsyncCacheClient(
266
+ policy=FilterPolicy(
267
+ request_filters=[CacheOnlyAPIRequests()]
172
268
  )
173
269
  )
174
270
  ```
175
271
 
272
+ [Learn more about policies →](https://hishel.com/dev/policies/)
273
+
176
274
  ### Custom Storage Backend
177
275
 
178
276
  ```python
@@ -188,6 +286,60 @@ storage = SyncSqliteStorage(
188
286
  client = SyncCacheClient(storage=storage)
189
287
  ```
190
288
 
289
+ ### GraphQL and Body-Sensitive Caching
290
+
291
+ Cache GraphQL queries and other POST requests by including the request body in the cache key.
292
+
293
+ **Using per-request header:**
294
+
295
+ ```python
296
+ from hishel import FilterPolicy
297
+ from hishel.httpx import SyncCacheClient
298
+
299
+ client = SyncCacheClient(
300
+ policy=FilterPolicy()
301
+ )
302
+
303
+ # Cache GraphQL queries - different queries get different cache entries
304
+ graphql_query = """
305
+ query GetUser($id: ID!) {
306
+ user(id: $id) {
307
+ name
308
+ email
309
+ }
310
+ }
311
+ """
312
+
313
+ response = client.post(
314
+ "https://api.example.com/graphql",
315
+ json={"query": graphql_query, "variables": {"id": "123"}},
316
+ headers={"X-Hishel-Body-Key": "true"} # Enable body-based caching
317
+ )
318
+
319
+ # Different query will be cached separately
320
+ response = client.post(
321
+ "https://api.example.com/graphql",
322
+ json={"query": graphql_query, "variables": {"id": "456"}},
323
+ headers={"X-Hishel-Body-Key": "true"}
324
+ )
325
+ ```
326
+
327
+ **Using global configuration:**
328
+
329
+ ```python
330
+ from hishel.httpx import SyncCacheClient
331
+ from hishel import FilterPolicy
332
+
333
+ # Enable body-based caching for all requests
334
+ client = SyncCacheClient(policy=FilterPolicy(use_body_key=True))
335
+
336
+ # All POST requests automatically include body in cache key
337
+ response = client.post(
338
+ "https://api.example.com/graphql",
339
+ json={"query": graphql_query, "variables": {"id": "123"}}
340
+ )
341
+ ```
342
+
191
343
  ## 🏗️ Architecture
192
344
 
193
345
  Hishel uses a **sans-I/O state machine** architecture that separates HTTP caching logic from I/O operations:
@@ -199,13 +351,11 @@ Hishel uses a **sans-I/O state machine** architecture that separates HTTP cachin
199
351
 
200
352
  ## 🔮 Roadmap
201
353
 
202
- While Hishel currently supports HTTPX and Requests, we're actively working on:
354
+ We're actively working on:
203
355
 
204
- - 🎯 Additional HTTP client integrations
205
- - 🎯 Server-side caching support
206
- - 🎯 More storage backends
207
- - 🎯 Advanced caching strategies
208
356
  - 🎯 Performance optimizations
357
+ - 🎯 More integrations
358
+ - 🎯 Partial responses support
209
359
 
210
360
  ## 📚 Documentation
211
361
 
@@ -214,7 +364,12 @@ Comprehensive documentation is available at [https://hishel.com/dev](https://his
214
364
  - [Getting Started](https://hishel.com)
215
365
  - [HTTPX Integration](https://hishel.com/dev/integrations/httpx)
216
366
  - [Requests Integration](https://hishel.com/dev/integrations/requests)
367
+ - [ASGI Integration](https://hishel.com/dev/asgi)
368
+ - [FastAPI Integration](https://hishel.com/dev/fastapi)
369
+ - [BlackSheep Integration](https://hishel.com/dev/integrations/blacksheep)
370
+ - [GraphQL Integration](https://hishel.com/dev/integrations/graphql)
217
371
  - [Storage Backends](https://hishel.com/dev/storages)
372
+ - [Request/Response Metadata](https://hishel.com/dev/metadata)
218
373
  - [RFC 9111 Specification](https://hishel.com/dev/specification)
219
374
 
220
375
  ## 🤝 Contributing
@@ -255,10 +410,62 @@ Hishel is inspired by and builds upon the excellent work in the Python HTTP ecos
255
410
 
256
411
  All notable changes to this project will be documented in this file.
257
412
 
413
+ ## 1.1.0 - 2025-10-31
414
+ ### ⚙️ Miscellaneous Tasks
415
+ - Add in memory example
416
+
417
+ ### 🐛 Bug Fixes
418
+ - Pass any response with non-expected status code on revalidation to client
419
+
420
+ ### 🚀 Features
421
+ - Allow setting storage base with via `database_path` for sqlite storage
422
+
423
+ ## 1.0.0 - 2025-10-28
424
+ ### ⚙️ Miscellaneous Tasks
425
+ - Add examples, improve docs
426
+
427
+ ## 1.0.0b1 - 2025-10-28
428
+ ### ♻️ Refactoring
429
+ - Add policies
430
+
431
+ ### ⚙️ Miscellaneous Tasks
432
+ - Improve sans-io diagram colors
433
+ - Add graphql docs
434
+
435
+ ### 🐛 Bug Fixes
436
+ - Body-sensitive responses caching
437
+ - Filter out `Transfer-Encoding` header for asgi responses
438
+
439
+ ### 🚀 Features
440
+ - Add global `use_body_key` setting
441
+
442
+ ## 1.0.0.dev3 - 2025-10-26
443
+ ### ♻️ Refactoring
444
+ - Replace pairs with entries, simplify storage API
445
+ - Automatically generate httpx sync integration from async
446
+
447
+ ### ⚙️ Miscellaneous Tasks
448
+ - Simplify metadata docs
449
+ - Add custom integrations docs
450
+ - More robust compressed response caching
451
+
452
+ ### 🐛 Bug Fixes
453
+ - Add missing permissions into `publish.yml`
454
+ - Raise on consumed httpx streams, which we can't store as is (it's already decoded)
455
+ - Fix compressed data caching for requests
456
+ - Handle httpx iterable usage instead of iterator correctly
457
+ - Add date header for proper age calculation
458
+
459
+ ### 🚀 Features
460
+ - Add integrations with fastapi and asgi
461
+ - Add blacksheep integration examples
462
+ - Add logging for asgi
463
+
258
464
  ## 1.0.0.dev2 - 2025-10-21
259
465
  ### ⚙️ Miscellaneous Tasks
260
466
  - Remove redundant utils and tests
261
467
  - Add import without extras check in ci
468
+ - Fix time travel date, explicitly specify the timezone
262
469
 
263
470
  ### 🐛 Bug Fixes
264
471
  - Fix check for storing auth requests
@@ -1,3 +1,4 @@
1
+
1
2
  <p align="center">
2
3
  <img alt="Hishel Logo" width="350" src="https://raw.githubusercontent.com/karpetrosyan/hishel/master/docs/static/Shelkopryad_350x250_yellow.png#gh-dark-mode-only">
3
4
  <img alt="Hishel Logo" width="350" src="https://raw.githubusercontent.com/karpetrosyan/hishel/master/docs/static/Shelkopryad_350x250_black.png#gh-light-mode-only">
@@ -34,14 +35,16 @@
34
35
  ## ✨ Features
35
36
 
36
37
  - 🎯 **RFC 9111 Compliant** - Fully compliant with the latest HTTP caching specification
37
- - 🔌 **Easy Integration** - Drop-in support for HTTPX and Requests
38
+ - 🔌 **Easy Integration** - Drop-in support for HTTPX, Requests, ASGI, FastAPI, and BlackSheep
38
39
  - 💾 **Flexible Storage** - SQLite backend with more coming soon
39
40
  - ⚡ **High Performance** - Efficient caching with minimal overhead
40
41
  - 🔄 **Async & Sync** - Full support for both synchronous and asynchronous workflows
41
42
  - 🎨 **Type Safe** - Fully typed with comprehensive type hints
42
43
  - 🧪 **Well Tested** - Extensive test coverage and battle-tested
43
- - 🎛️ **Configurable** - Fine-grained control over caching behavior
44
- - 🌐 **Future Ready** - Designed for easy integration with any HTTP client/server
44
+ - 🎛️ **Configurable** - Fine-grained control over caching behavior with flexible policies
45
+ - 💨 **Memory Efficient** - Streaming support prevents loading large payloads into memory
46
+ - 🌐 **Universal** - Works with any ASGI application (Starlette, Litestar, BlackSheep, etc.)
47
+ - 🎯 **GraphQL Support** - Cache GraphQL queries with body-sensitive content caching
45
48
 
46
49
  ## 📦 Installation
47
50
 
@@ -51,19 +54,23 @@ pip install hishel
51
54
 
52
55
  ### Optional Dependencies
53
56
 
54
- Install with specific HTTP client support:
57
+ Install with specific integration support:
55
58
 
56
59
  ```bash
57
60
  pip install hishel[httpx] # For HTTPX support
58
61
  pip install hishel[requests] # For Requests support
62
+ pip install hishel[fastapi] # For FastAPI support (includes ASGI)
59
63
  ```
60
64
 
61
- Or install both:
65
+ Or install multiple:
62
66
 
63
67
  ```bash
64
- pip install hishel[httpx,requests]
68
+ pip install hishel[httpx,requests,fastapi]
65
69
  ```
66
70
 
71
+ > [!NOTE]
72
+ > ASGI middleware has no extra dependencies - it's included in the base installation.
73
+
67
74
  ## 🚀 Quick Start
68
75
 
69
76
  ### With HTTPX
@@ -117,23 +124,112 @@ response = session.get("https://api.example.com/data")
117
124
  print(response.headers.get("X-Hishel-From-Cache")) # "True"
118
125
  ```
119
126
 
127
+ ### With ASGI Applications
128
+
129
+ Add caching middleware to any ASGI application:
130
+
131
+ ```python
132
+ from hishel.asgi import ASGICacheMiddleware
133
+
134
+ # Wrap your ASGI app
135
+ app = ASGICacheMiddleware(app)
136
+
137
+ # Or configure with options
138
+ from hishel import AsyncSqliteStorage, CacheOptions, SpecificationPolicy
139
+
140
+ app = ASGICacheMiddleware(
141
+ app,
142
+ storage=AsyncSqliteStorage(),
143
+ policy=SpecificationPolicy(
144
+ cache_options=CacheOptions(shared=True)
145
+ ),
146
+ )
147
+ ```
148
+
149
+ ### With FastAPI
150
+
151
+ Add Cache-Control headers using the `cache()` dependency:
152
+
153
+ ```python
154
+ from fastapi import FastAPI
155
+ from hishel.fastapi import cache
156
+
157
+ app = FastAPI()
158
+
159
+ @app.get("/api/data", dependencies=[cache(max_age=300, public=True)])
160
+ async def get_data():
161
+ # Cache-Control: public, max-age=300
162
+ return {"data": "cached for 5 minutes"}
163
+
164
+ # Optionally wrap with ASGI middleware for local caching according to specified rules
165
+ from hishel.asgi import ASGICacheMiddleware
166
+ from hishel import AsyncSqliteStorage
167
+
168
+ app = ASGICacheMiddleware(app, storage=AsyncSqliteStorage())
169
+ ```
170
+
171
+ ### With BlackSheep
172
+
173
+ Use BlackSheep's native `cache_control` decorator with Hishel's ASGI middleware:
174
+
175
+ ```python
176
+ from blacksheep import Application, get
177
+ from blacksheep.server.headers.cache import cache_control
178
+
179
+ app = Application()
180
+
181
+ @get("/api/data")
182
+ @cache_control(max_age=300, public=True)
183
+ async def get_data():
184
+ # Cache-Control: public, max-age=300
185
+ return {"data": "cached for 5 minutes"}
186
+ ```
187
+
120
188
  ## 🎛️ Advanced Configuration
121
189
 
122
- ### Custom Cache Options
190
+ ### Caching Policies
191
+
192
+ Hishel supports two types of caching policies:
193
+
194
+ **SpecificationPolicy** - RFC 9111 compliant HTTP caching (default):
123
195
 
124
196
  ```python
125
- from hishel import CacheOptions
197
+ from hishel import CacheOptions, SpecificationPolicy
126
198
  from hishel.httpx import SyncCacheClient
127
199
 
128
200
  client = SyncCacheClient(
129
- cache_options=CacheOptions(
130
- shared=False, # Use as private cache (browser-like)
131
- supported_methods=["GET", "HEAD", "POST"], # Cache GET, HEAD, and POST
132
- allow_stale=True # Allow serving stale responses
201
+ policy=SpecificationPolicy(
202
+ cache_options=CacheOptions(
203
+ shared=False, # Use as private cache (browser-like)
204
+ supported_methods=["GET", "HEAD", "POST"], # Cache GET, HEAD, and POST
205
+ allow_stale=True # Allow serving stale responses
206
+ )
207
+ )
208
+ )
209
+ ```
210
+
211
+ **FilterPolicy** - Custom filtering logic for fine-grained control:
212
+
213
+ ```python
214
+ from hishel import FilterPolicy, BaseFilter, Request
215
+ from hishel.httpx import AsyncCacheClient
216
+
217
+ class CacheOnlyAPIRequests(BaseFilter[Request]):
218
+ def needs_body(self) -> bool:
219
+ return False
220
+
221
+ def apply(self, item: Request, body: bytes | None) -> bool:
222
+ return "/api/" in str(item.url)
223
+
224
+ client = AsyncCacheClient(
225
+ policy=FilterPolicy(
226
+ request_filters=[CacheOnlyAPIRequests()]
133
227
  )
134
228
  )
135
229
  ```
136
230
 
231
+ [Learn more about policies →](https://hishel.com/dev/policies/)
232
+
137
233
  ### Custom Storage Backend
138
234
 
139
235
  ```python
@@ -149,6 +245,60 @@ storage = SyncSqliteStorage(
149
245
  client = SyncCacheClient(storage=storage)
150
246
  ```
151
247
 
248
+ ### GraphQL and Body-Sensitive Caching
249
+
250
+ Cache GraphQL queries and other POST requests by including the request body in the cache key.
251
+
252
+ **Using per-request header:**
253
+
254
+ ```python
255
+ from hishel import FilterPolicy
256
+ from hishel.httpx import SyncCacheClient
257
+
258
+ client = SyncCacheClient(
259
+ policy=FilterPolicy()
260
+ )
261
+
262
+ # Cache GraphQL queries - different queries get different cache entries
263
+ graphql_query = """
264
+ query GetUser($id: ID!) {
265
+ user(id: $id) {
266
+ name
267
+ email
268
+ }
269
+ }
270
+ """
271
+
272
+ response = client.post(
273
+ "https://api.example.com/graphql",
274
+ json={"query": graphql_query, "variables": {"id": "123"}},
275
+ headers={"X-Hishel-Body-Key": "true"} # Enable body-based caching
276
+ )
277
+
278
+ # Different query will be cached separately
279
+ response = client.post(
280
+ "https://api.example.com/graphql",
281
+ json={"query": graphql_query, "variables": {"id": "456"}},
282
+ headers={"X-Hishel-Body-Key": "true"}
283
+ )
284
+ ```
285
+
286
+ **Using global configuration:**
287
+
288
+ ```python
289
+ from hishel.httpx import SyncCacheClient
290
+ from hishel import FilterPolicy
291
+
292
+ # Enable body-based caching for all requests
293
+ client = SyncCacheClient(policy=FilterPolicy(use_body_key=True))
294
+
295
+ # All POST requests automatically include body in cache key
296
+ response = client.post(
297
+ "https://api.example.com/graphql",
298
+ json={"query": graphql_query, "variables": {"id": "123"}}
299
+ )
300
+ ```
301
+
152
302
  ## 🏗️ Architecture
153
303
 
154
304
  Hishel uses a **sans-I/O state machine** architecture that separates HTTP caching logic from I/O operations:
@@ -160,13 +310,11 @@ Hishel uses a **sans-I/O state machine** architecture that separates HTTP cachin
160
310
 
161
311
  ## 🔮 Roadmap
162
312
 
163
- While Hishel currently supports HTTPX and Requests, we're actively working on:
313
+ We're actively working on:
164
314
 
165
- - 🎯 Additional HTTP client integrations
166
- - 🎯 Server-side caching support
167
- - 🎯 More storage backends
168
- - 🎯 Advanced caching strategies
169
315
  - 🎯 Performance optimizations
316
+ - 🎯 More integrations
317
+ - 🎯 Partial responses support
170
318
 
171
319
  ## 📚 Documentation
172
320
 
@@ -175,7 +323,12 @@ Comprehensive documentation is available at [https://hishel.com/dev](https://his
175
323
  - [Getting Started](https://hishel.com)
176
324
  - [HTTPX Integration](https://hishel.com/dev/integrations/httpx)
177
325
  - [Requests Integration](https://hishel.com/dev/integrations/requests)
326
+ - [ASGI Integration](https://hishel.com/dev/asgi)
327
+ - [FastAPI Integration](https://hishel.com/dev/fastapi)
328
+ - [BlackSheep Integration](https://hishel.com/dev/integrations/blacksheep)
329
+ - [GraphQL Integration](https://hishel.com/dev/integrations/graphql)
178
330
  - [Storage Backends](https://hishel.com/dev/storages)
331
+ - [Request/Response Metadata](https://hishel.com/dev/metadata)
179
332
  - [RFC 9111 Specification](https://hishel.com/dev/specification)
180
333
 
181
334
  ## 🤝 Contributing