Skip to content

Commit ac15ac7

Browse files
committed
Docs
1 parent e9d0fda commit ac15ac7

File tree

2 files changed

+30
-21
lines changed

2 files changed

+30
-21
lines changed

README.md

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
# Can I cache this? [![Build Status](https://travis-ci.org/kornelski/http-cache-semantics.svg?branch=master)](https://travis-ci.org/kornelski/http-cache-semantics)
22

3-
`CachePolicy` tells when responses can be reused from a cache, taking into account [HTTP RFC 7234](http://httpwg.org/specs/rfc7234.html) rules for user agents and shared caches.
4-
It also implements [RFC 5861](https://tools.ietf.org/html/rfc5861), implementing `stale-if-error` and `stale-while-revalidate`.
3+
This library tells when responses can be reused from a cache, taking into account [HTTP RFC 7234/9111](http://httpwg.org/specs/rfc9111.html) rules for user agents and shared caches.
4+
It also implements `stale-if-error` and `stale-while-revalidate` from [RFC 5861](https://tools.ietf.org/html/rfc5861).
55
It's aware of many tricky details such as the `Vary` header, proxy revalidation, and authenticated responses.
66

7-
## Usage
7+
## Basic Usage
8+
9+
`CachePolicy` is a metadata object that is meant to be stored in the cache, and it will keep track of cacheability of the response.
810

911
Cacheability of an HTTP response depends on how it was requested, so both `request` and `response` are required to create the policy.
1012

@@ -20,22 +22,26 @@ if (!policy.storable()) {
2022
// (this is pseudocode, roll your own cache (lru-cache package works))
2123
letsPretendThisIsSomeCache.set(
2224
request.url,
23-
{ policy, response },
25+
{ policy, body: response.body }, // you only need to store the response body. CachePolicy holds the headers.
2426
policy.timeToLive()
2527
);
2628
```
2729

2830
```js
2931
// And later, when you receive a new request:
30-
const { policy, response } = letsPretendThisIsSomeCache.get(newRequest.url);
32+
const { policy, body } = letsPretendThisIsSomeCache.get(newRequest.url);
3133

3234
// It's not enough that it exists in the cache, it has to match the new request, too:
3335
if (policy && policy.satisfiesWithoutRevalidation(newRequest)) {
3436
// OK, the previous response can be used to respond to the `newRequest`.
3537
// Response headers have to be updated, e.g. to add Age and remove uncacheable headers.
36-
response.headers = policy.responseHeaders();
37-
return response;
38+
return {
39+
headers: policy.responseHeaders(),
40+
body,
41+
}
3842
}
43+
44+
// Cache miss. See revalidationHeaders() and revalidatedPolicy() for advanced usage.
3945
```
4046

4147
It may be surprising, but it's not enough for an HTTP response to be [fresh](#yo-fresh) to satisfy a request. It may need to match request headers specified in `Vary`. Even a matching fresh response may still not be usable if the new request restricted cacheability, etc.
@@ -95,15 +101,14 @@ If it returns `false`, then the response may not be matching at all (e.g. it's f
95101
Returns updated, filtered set of response headers to return to clients receiving the cached response. This function is necessary, because proxies MUST always remove hop-by-hop headers (such as `TE` and `Connection`) and update response's `Age` to avoid doubling cache time.
96102

97103
```js
98-
cachedResponse.headers = cachePolicy.responseHeaders(cachedResponse);
104+
cachedResponse.headers = cachePolicy.responseHeaders();
99105
```
100106

101107
### `timeToLive()`
102108

103-
Returns approximate time in _milliseconds_ until the response becomes stale (i.e. not fresh).
109+
Suggests a time in _milliseconds_ for how long this cache entry may be useful. This is not freshness, so always check with `satisfiesWithoutRevalidation()`. This time may be longer than response's `max-age` to allow for `stale-if-error` and `stale-while-revalidate`.
104110

105-
After that time (when `timeToLive() <= 0`) the response might not be usable without revalidation. However, there are exceptions, e.g. a client can explicitly allow stale responses, so always check with `satisfiesWithoutRevalidation()`.
106-
`stale-if-error` and `stale-while-revalidate` extend the time to live of the cache, that can still be used if stale.
111+
After that time (when `timeToLive() <= 0`) the response may still be usable in certain cases, e.g. if client can explicitly allows stale responses.
107112

108113
### `toObject()`/`fromObject(json)`
109114

@@ -133,37 +138,40 @@ Use this method to update the cache after receiving a new response from the orig
133138
- `modified` — Boolean indicating whether the response body has changed.
134139
- If `false`, then a valid 304 Not Modified response has been received, and you can reuse the old cached response body. This is also affected by `stale-if-error`.
135140
- If `true`, you should use new response's body (if present), or make another request to the origin server without any conditional headers (i.e. don't use `revalidationHeaders()` this time) to get the new resource.
141+
- `headers` — updated response headers to use when returning the response to the client.
136142

137143
```js
138144
// When serving requests from cache:
139-
const { oldPolicy, oldResponse } = letsPretendThisIsSomeCache.get(
145+
const { cachedPolicy, cachedBody } = letsPretendThisIsSomeCache.get(
140146
newRequest.url
141147
);
142148

143-
if (!oldPolicy.satisfiesWithoutRevalidation(newRequest)) {
149+
if (!cachedPolicy.satisfiesWithoutRevalidation(newRequest)) {
144150
// Change the request to ask the origin server if the cached response can be used
145-
newRequest.headers = oldPolicy.revalidationHeaders(newRequest);
151+
newRequest.headers = cachedPolicy.revalidationHeaders(newRequest);
146152

147153
// Send request to the origin server. The server may respond with status 304
148154
const newResponse = await makeRequest(newRequest);
149155

150156
// Create updated policy and combined response from the old and new data
151-
const { policy, modified } = oldPolicy.revalidatedPolicy(
157+
const { policy, modified } = cachedPolicy.revalidatedPolicy(
152158
newRequest,
153159
newResponse
154160
);
155-
const response = modified ? newResponse : oldResponse;
161+
const body = modified ? newResponse.body : oldBody;
156162

157163
// Update the cache with the newer/fresher response
158164
letsPretendThisIsSomeCache.set(
159165
newRequest.url,
160-
{ policy, response },
166+
{ policy, body },
161167
policy.timeToLive()
162168
);
163169

164-
// And proceed returning cached response as usual
165-
response.headers = policy.responseHeaders();
166-
return response;
170+
// Make a new response from the cached or revalidated data
171+
return {
172+
headers: policy.responseHeaders()
173+
body,
174+
}
167175
}
168176
```
169177

index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -454,8 +454,9 @@ module.exports = class CachePolicy {
454454

455455
/**
456456
* Remaining time this cache entry may be useful for, in *milliseconds*.
457+
* You can use this as an expiration time for your cache storage.
457458
*
458-
* Prefer this method over `maxAge()`, because it includes other factors.
459+
* Prefer this method over `maxAge()`, because it includes other factors like `age` and `stale-while-revalidate`.
459460
*/
460461
timeToLive() {
461462
const age = this.maxAge() - this.age();

0 commit comments

Comments
 (0)