File: controllers.md

package info (click to toggle)
hishel 0.1.3-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,548 kB
  • sloc: python: 6,387; sh: 13; makefile: 4
file content (189 lines) | stat: -rw-r--r-- 5,744 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
---
icon: material/brain
---

`Hishel` provides the `Controllers`, which allow you to fully customize how the cache works at the specification level.

You can choose which parts of [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111.html) to ignore. For example, this is useful when you want to ensure that your client does **not use stale responses** even if they are **acceptable from the server.**

### Force caching

If you only need to cache responses without validating the headers and following RFC9111 rules, simply set the `force_cache` property to true.

Example:

```python
import hishel

controller = hishel.Controller(force_cache=True)
client = hishel.CacheClient(controller=controller)
```

!!! note
    [force_cache](extensions.md#force_cache) extension will always overwrite the controller's force_cache property.

### Cachable HTTP methods

You can specify which HTTP methods `Hishel` should cache.

Example:

```python
import hishel

controller = hishel.Controller(cacheable_methods=["GET", "POST"])
client = hishel.CacheClient(controller=controller)
```

!!! note
    `Hishel` will only cache `GET` methods if the cachable methods are not explicitly specified.

### Cachable status codes

If you only want to cache specific status codes, do so.

Example:

```python
import hishel

controller = hishel.Controller(cacheable_status_codes=[301, 308])
client = hishel.CacheClient(controller=controller)
```

!!! note
    If the cachable status codes are not explicitly specified, `Hishel` will only cache status codes **200, 301, and 308**.


### Allowing heuristics

You can enable heuristics calculations, which are disabled by default.

Example:

```python
import hishel

controller = hishel.Controller(allow_heuristics=True)
client = hishel.CacheClient(controller=controller)

```

`Hishel` is very conservative about what status codes are permitted
to be heuristically cacheable. When `allow_heuristics` is enabled,
`Hishel` will only cache responses having status codes 200, 301, and 308. In contrast, RFC 9111 specifies that many more responses can be heuristically cacheable, specifically 200, 203, 204, 206, 300, 301, 308, 404, 405, 410, 414, and 501.

If you would prefer heuristic caching to the fullest extent permitted by
RFC 9111, then pass `HEURISTICALLY_CACHEABLE_STATUS_CODES` to `cacheable_status_codes`:

```python
import hishel

controller = hishel.Controller(
    allow_heuristics=True,
    cacheable_status_codes=hishel.HEURISTICALLY_CACHEABLE_STATUS_CODES
    )
client = hishel.CacheClient(controller=controller)

```

!!! tip
    If you're not familiar with `Heuristics Caching`, you can [read about it in the specification](https://www.rfc-editor.org/rfc/rfc9111.html#name-calculating-heuristic-fresh).

### Preventing caching of private responses

If you want `Hishel` to act as a _shared_ cache, you need to prevent it from caching responses with the `private` directive.

Example:

```python
import hishel

controller = hishel.Controller(cache_private=False)
client = hishel.CacheClient(controller=controller)
```

!!! note
    Servers may prohibit only some headers from being stored in a shared cache by sending a header such as `Cache-Control: private=set-cookie`. However, `Hishel` with `cache_private=False` will still not cache the response, at all.

### Allowing stale responses

Some servers allow the use of stale responses if they cannot be re-validated or the client is disconnected from the server. Clients MAY use stale responses in such cases, but this behavior is disabled by default in `Hishel`.

Example:

```python
import hishel

controller = hishel.Controller(allow_stale=True)
client = hishel.CacheClient(controller=controller)
```

!!! tip
    `Hishel` will attempt to use stale response only if the client is unable to connect to the server to make a request. You can enable stale responses to receive responses even if your internet connection is lost.

### Specifying revalidation behavior

Responses are revalidated by default when they become stale; however, you can always revalidate the responses if you wish.

Example:

```python
import hishel

controller = hishel.Controller(always_revalidate=True)
client = hishel.CacheClient(controller=controller)
```

!!! note
    Because we already have the response body in our cache, revalidation is very quick.

### Custom cache keys

By default, `Hishel` generates cache keys as a hash of the request method and url.
However, you can customize cache key creation by writing a function with the signature `Callable[[httpcore.Request], str]` and passing it to the controller.

Example:

```python
import hishel
import httpcore
from hishel._utils import generate_key

def custom_key_generator(request: httpcore.Request, body: bytes):
    key = generate_key(request, body)
    method = request.method.decode()
    host = request.url.host.decode()
    return f"{method}|{host}|{key}"

controller = hishel.Controller(key_generator=custom_key_generator)
client = hishel.CacheClient(controller=controller)

client.get("https://hishel.com")
```

Instead of just the `hashed_value`, the key now has the format `method|host|hashed_value`.

!!! note
    Cache keys are used to store responses in storages, such as filesystem storage, which will use the cache key to create a file with that value.
    You can write your own cache key implementation to have more meaningful file names and simplify cache monitoring.

=== "Before"

    ```
    📁 root
    └─╴📁 .cache
       └─╴📁 hishel
          └─╴📄 41ebb4dd16761e94e2ee36b71e0d916e
    ```

=== "After"

    ```
    📁 root
    └─╴📁 .cache
       └─╴📁 hishel
          └─╴📄 GET|hishel.com|41ebb4dd16761e94e2ee36b71e0d916e
    ```