-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathhttp-cache-semantics.node.txt
113 lines (101 loc) · 8.06 KB
/
http-cache-semantics.node.txt
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
┏━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ HTTP-CACHE-SEMANTICS ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━┛
VERSION ==> #4.1.1
new HttpCacheSemantics #HTTP caching logic for servers to know whether to cache responses and whether to serve them.
(REQ], RES[, OPTS]) #OPTS:
# - shared BOOL (def: true): if server cache is shared by other clients
# - cacheHeuristic NUM (def: 0.1): fallback TTL to percentage of response's age
# - immutableMinTimeToLive NUM (def: 1 day, in ms): minimum TTL if Cache-Control: immutable [C]
SEMANTICS #Cache information for a specific resource (method + URL)
SEMANTICS.toObject(SEMANTICS)->OBJ#Serialize to JSON-serializable OBJ
fromObject(OBJ)->SEMANTICS #Parse from such OBJ
SEMANTICS.storable()->BOOL #Whether resource|SEMANTICS can be cached for later requests.
#false if either:
# - Cache-Control: no-store [C|S]
# - Cache-Control: private [S] and OPTS.shared true
# - not GET|HEAD|POST
# - POST and:
# - no Expires [S]
# - no Cache-Control: maxage [S]
# - no Cache-Control: s-maxage [S] or OPTS.shared false
# - not 200|203|204|300|301|302|303|307|308|404|405|410|414|501
# - 302|303|307|308 and no Expires [S] nor Cache-Control: public|[s-]maxage [C]
# - Authorization [C] and OPTS.shared true and no Cache-Control: must-revalidate|public|s-maxage [C]
SEMANTICS.date()->'TIMESTAMP' #Resource's timestamp using Date [S]
SEMANTICS.age()->NUM #Resource's age using max of Age [S] or age using Date [S], in secs
SEMANTICS.maxAge()->NUM #Resource's max age.
#0 if either:
# - storable() false
# - Cache-Control: no-cache [C]
# - OPTS.shared true and either:
# - Cache-Control: proxy-revalidate [C]
# - Set-Cookie [S] and no Cache-Control: public|immutable [C]
# - Vary: * [S]
#Otherwise returns (in secs):
# - Cache-Control: s-maxage [C] (if OPTS.shared true)
# - Cache-Control: maxage [C]
# - Expires [S]
# - OPTS.cacheHeuristic * age using Last-Modified [S]
#The last two return at least OPTS.immutableMinTimeToLive if Cache-Control: immutable [C]
SEMANTICS.timeToLive()->NUM #Max of age() or maxAge() (in ms)
#Also take into account State-If-Error|Stale-If-Revalidate [S]
SEMANTICS.stale()->BOOL #Whether age() > maxAge()
SEMANTICS. #Whether REQ can use previously cached resource|SEMANTICS.
satisfiesWithoutRevalidation #Return false if either:
(REQ)->BOOL # - different method, URL, Host [C] and (if Vary [S]) headers
# - age() > Cache-Control: max-age [C]
# - age() > maxAge() unless:
# - Cache-Control: max-stale [C] matches
# - no Cache-Control: must-revalidate [C]
# - timeToLive() < Cache-Control: min-fresh [C]
# - Cache-Control|Pragma: no-cache [C]
SEMANTICS.responseHeaders()->OBJ #Response headers to set on a RES that use a cached resource.
#Return same response headers as cached resource but:
# - without Date|Connection|Keep-Alive|Proxy-Authenticate|Proxy-Authorization|TE|Trailer|Transfer-Encoding|Upgrade [S]
# - with Date [S] using current time
# - with Age [S] using age()
SEMANTICS.revalidatedPolicy #When !satisfiesWithoutRevalidation() and server is a proxy, we need to make a REQ to origin server (which responds with RES).
(REQ, RES)->OBJ #Returns new resource|SEMANTICS to cache.
#OBJ:
# - policy SEMANTICS
# - matches BOOL:
# - true if 304 and same ETag|Last-Modified [S]
# - if true, SEMANTICS is cloned
# - modified BOOL:
# - false if 304, i.e. can re-use previously cached RES
#Take into account State-If-Error [S]
SEMANTICS.revalidationHeaders(REQ)#Request headers to set on a REQ when making such request to origin server.
->OBJ #Return same request headers as cached resource but:
# - without Date|Connection|Keep-Alive|Proxy-Authenticate|Proxy-Authorization|TE|Trailer|Transfer-Encoding|Upgrade [C]
# - without If-Range [C]
# - if ETag [S], If-None-Match: ETAG [S]
# - if Last-Modified [S], If-Modified-Since: DATE [S]
# - both If-Non-Match|If-Modified-Since [S] are removed if not storable() or different method, URL, Host [C] or (if Vary [S]) headers:
┌───────────────────────┐
│ CACHEABLE-REQUEST │
└───────────────────────┘
VERSION ==> #12.0.1 (2024-08-12)
new CacheableRequest #Wrap HTTP.request() to cache HTTP responses:
(HTTP.request, 'URI'|STORE|KEYV) # - if not cached yet and cacheable, cache response
CACHEABLE_REQUEST.request() # - if cached and can be used (satisfiesWithoutRevalidation() or revalidatedPolicy().modified false),
->HTTP.request # re-use cached response
# - set correct responseHeaders|revalidationHeader()
# - otherwise remove from cache
#Built on top of http-cache-semantics
#Persist responses URL|status|body with keyv (see its doc)
# - URI|STORE is keyv OPTS.uri|store
#Adds OPTS:
# - cache BOOL (def: true): if false, disables
# - maxTtl NUM (in ms): response TTL using specific NUM
# - strictTtl BOOL (def: false): if true, disable revalidation (revalidatedPolicy())
# - forceRefresh BOOL (def: false): never re-use cached responses
# - automaticFailover BOOL (def: false): retry if cache error (not if network|HTTP error)
# - any options from new HttpCacheSemantics()
#Adds RES:
# - cachePolicy SEMANTICS
# - fromCache BOOL: if re-used cached response
REQ.addHook('onResponse',
FUNC(CACHED_VAL, RES)
->PROMISE_CACHED_VAL) #Process RES before saving to cache
REQ.removeHook('onResponse') #