src/cache.bend
emerging-ezhttp@0.21.0.0 · 174 lines · 25 definitions
1
2
3
4import Base
5import emerging-ezhttp@0.21.0.0/src/http.bend as Http
6
7
8type Cc is Data:
9 Cc{
10 no_store: Bool
11 no_cache: Bool
12 public: Bool
13 private: Bool
14 max_age: String
15 expires: String
16 }
17
18
19def cache.empty() -> Cc:
20 Cc{False{}, False{}, False{}, False{}, "", ""}
21
22
23def cache.store(c: Cc) -> Cc:
24 match c:
25 case Cc{no_store, no_cache, public, private, max_age, expires}:
26 Cc{True{}, no_cache, public, private, max_age, expires}
27
28
29def cache.revalidate(c: Cc) -> Cc:
30 match c:
31 case Cc{no_store, no_cache, public, private, max_age, expires}:
32 Cc{no_store, True{}, public, private, max_age, expires}
33
34
35def cache.pub(c: Cc) -> Cc:
36 match c:
37 case Cc{no_store, no_cache, public, private, max_age, expires}:
38 Cc{no_store, no_cache, True{}, private, max_age, expires}
39
40
41def cache.priv(c: Cc) -> Cc:
42 match c:
43 case Cc{no_store, no_cache, public, private, max_age, expires}:
44 Cc{no_store, no_cache, public, True{}, max_age, expires}
45
46
47def cache.age(c: Cc, age: String) -> Cc:
48 match c:
49 case Cc{no_store, no_cache, public, private, max_age, expires}:
50 Cc{no_store, no_cache, public, private, age, expires}
51
52
53def cache.expires(c: Cc, when: String) -> Cc:
54 match c:
55 case Cc{no_store, no_cache, public, private, max_age, expires}:
56 Cc{no_store, no_cache, public, private, max_age, when}
57
58
59def cache.one.private(c: Cc, _name: String, _value: String, hit: Bool) -> Cc:
60 match hit:
61 case True{}:
62 cache.priv(c)
63 case False{}:
64 c
65
66
67def cache.one.public(c: Cc, +name: String, value: String, hit: Bool) -> Cc:
68 match hit:
69 case True{}:
70 cache.pub(c)
71 case False{}:
72 cache.one.private(c, name, value, String.eq(name, "private"))
73
74
75def cache.one.age_ok(c: Cc, +raw: String, m: Maybe<&2, Nat>) -> Cc:
76 match m:
77 case None{}:
78 c
79 case Some{n}:
80 cache.age(c, raw)
81
82
83def cache.one.age(c: Cc, +name: String, +value: String, hit: Bool) -> Cc:
84 match hit:
85 case True{}:
86 cache.one.age_ok(c, value, Http.digits.read(value))
87 case False{}:
88 cache.one.public(c, name, value, String.eq(name, "public"))
89
90
91def cache.one.cache(c: Cc, +name: String, +value: String, hit: Bool) -> Cc:
92 match hit:
93 case True{}:
94 cache.revalidate(c)
95 case False{}:
96 cache.one.age(c, name, value, String.eq(name, "max-age"))
97
98
99def cache.one.store(c: Cc, +name: String, +value: String, hit: Bool) -> Cc:
100 match hit:
101 case True{}:
102 cache.store(c)
103 case False{}:
104 cache.one.cache(c, name, value, String.eq(name, "no-cache"))
105
106
107def cache.one.flag(c: Cc, +name: String) -> Cc:
108 cache.one.store(c, name, "", String.eq(name, "no-store"))
109
110
111def cache.one.dispatch(c: Cc, +piece: String, cut: Http.Cut) -> Cc:
112 match cut:
113 case Http.NoCut{}:
114 cache.one.flag(c, String.to_lower(String.trim(piece)))
115 case Http.Cut{+before, after}:
116 +name = String.to_lower(String.trim(before))
117 cache.one.store(c, name, String.trim(after), String.eq(name, "no-store"))
118
119
120def cache.one(c: Cc, +piece: String) -> Cc:
121 cache.one.dispatch(c, piece, Http.divide(piece, "="))
122
123
124def cache.fold(ps: List<&2, String>, c: Cc) -> Cc:
125 match ps:
126 case []:
127 c
128 case h <> t:
129 cache.fold(t, cache.one(c, String.trim(h)))
130
131
132def cache.parse(value: String) -> Cc:
133 cache.fold(String.split(value, ','), cache.empty())
134
135
136def cache.note(value: String, expires: String) -> Cc:
137 cache.expires(cache.parse(value), expires)
138
139
140def cache.max_age(c: Cc) -> Bool:
141 match c:
142 case Cc{no_store, no_cache, public, private, max_age, expires}:
143 Bool.not(String.eq(max_age, ""))
144
145
146def cache.fresh.go(age: Nat, m: Maybe<&2, Nat>) -> Bool:
147 match m:
148 case None{}:
149 False{}
150 case Some{n}:
151 Nat.is_lt(age, n)
152
153
154def cache.fresh.cache(age: Nat, max_age: String, no_cache: Bool) -> Bool:
155 match no_cache:
156 case True{}:
157 False{}
158 case False{}:
159 cache.fresh.go(age, Http.digits.read(max_age))
160
161
162def cache.fresh.store(age: Nat, no_cache: Bool, max_age: String, no_store: Bool)
163 -> Bool:
164 match no_store:
165 case True{}:
166 False{}
167 case False{}:
168 cache.fresh.cache(age, max_age, no_cache)
169
170
171def cache.fresh(c: Cc, age: Nat) -> Bool:
172 match c:
173 case Cc{no_store, no_cache, public, private, max_age, expires}:
174 cache.fresh.store(age, no_cache, max_age, no_store)