]>
Commit | Line | Data |
---|---|---|
0abdd70d | 1 | /* |
b8ae064d | 2 | * Copyright (C) 1996-2023 The Squid Software Foundation and contributors |
0abdd70d | 3 | * |
bbc27441 AJ |
4 | * Squid software is distributed under GPLv2+ license and includes |
5 | * contributions from numerous individuals and organizations. | |
6 | * Please see the COPYING and CONTRIBUTORS files for details. | |
0abdd70d FC |
7 | */ |
8 | ||
ff9d9458 FC |
9 | #ifndef SQUID_SRC_HTTPHDRCC_H |
10 | #define SQUID_SRC_HTTPHDRCC_H | |
0abdd70d | 11 | |
22056ef8 | 12 | #include "defines.h" |
b56ab9e7 | 13 | #include "dlink.h" |
ed6e9fb9 | 14 | #include "mem/forward.h" |
0abdd70d | 15 | #include "SquidString.h" |
6b1c9146 | 16 | #include <iosfwd> |
0abdd70d | 17 | |
17802cf1 | 18 | class Packable; |
43ca19e0 | 19 | |
1da82544 | 20 | enum HttpHdrCcType : unsigned char { |
b56ab9e7 FC |
21 | CC_PUBLIC = 0, |
22 | CC_PRIVATE, | |
23 | CC_NO_CACHE, | |
24 | CC_NO_STORE, | |
25 | CC_NO_TRANSFORM, | |
26 | CC_MUST_REVALIDATE, | |
27 | CC_PROXY_REVALIDATE, | |
28 | CC_MAX_AGE, | |
29 | CC_S_MAXAGE, | |
30 | CC_MAX_STALE, | |
31 | CC_MIN_FRESH, | |
32 | CC_ONLY_IF_CACHED, | |
33 | CC_STALE_IF_ERROR, | |
8311b837 | 34 | CC_IMMUTABLE, /* RFC 8246 */ |
b56ab9e7 FC |
35 | CC_OTHER, |
36 | CC_ENUM_END /* also used to mean "invalid" */ | |
1da82544 | 37 | }; |
b56ab9e7 | 38 | |
7ebe76de | 39 | /** Http Cache-Control header representation |
ce394734 | 40 | * |
7ebe76de | 41 | * Store and parse the Cache-Control HTTP header. |
ce394734 | 42 | */ |
0abdd70d FC |
43 | class HttpHdrCc |
44 | { | |
741c2986 | 45 | MEMPROXY_CLASS(HttpHdrCc); |
0abdd70d FC |
46 | |
47 | public: | |
77da1817 A |
48 | static const int32_t MAX_AGE_UNKNOWN=-1; //max-age is unset |
49 | static const int32_t S_MAXAGE_UNKNOWN=-1; //s-maxage is unset | |
50 | static const int32_t MAX_STALE_UNKNOWN=-1; //max-stale is unset | |
51 | ///used to mark a valueless Cache-Control: max-stale directive, which instructs | |
52 | /// us to treat responses of any age as fresh | |
53 | static const int32_t MAX_STALE_ANY=0x7fffffff; | |
54 | static const int32_t STALE_IF_ERROR_UNKNOWN=-1; //stale_if_error is unset | |
55 | static const int32_t MIN_FRESH_UNKNOWN=-1; //min_fresh is unset | |
70aff22f | 56 | |
c57b8f05 | 57 | HttpHdrCc() : |
f53969cc SM |
58 | mask(0), max_age(MAX_AGE_UNKNOWN), s_maxage(S_MAXAGE_UNKNOWN), |
59 | max_stale(MAX_STALE_UNKNOWN), stale_if_error(STALE_IF_ERROR_UNKNOWN), | |
60 | min_fresh(MIN_FRESH_UNKNOWN) {} | |
ce394734 | 61 | |
c57b8f05 | 62 | /// reset data-members to default state |
ce394734 | 63 | void clear(); |
c57b8f05 FC |
64 | |
65 | /// parse a header-string and fill in appropriate values. | |
1ba0611a | 66 | bool parse(const String & s); |
70aff22f | 67 | |
cf7c2e94 | 68 | //manipulation for Cache-Control: public header |
1da82544 | 69 | bool hasPublic() const {return isSet(HttpHdrCcType::CC_PUBLIC);} |
1da82544 FC |
70 | void Public(bool v) {setMask(HttpHdrCcType::CC_PUBLIC,v);} |
71 | void clearPublic() {setMask(HttpHdrCcType::CC_PUBLIC,false);} | |
cf7c2e94 FC |
72 | |
73 | //manipulation for Cache-Control: private header | |
810d879f | 74 | bool hasPrivate(const String **val = nullptr) const { return hasDirective(HttpHdrCcType::CC_PRIVATE, &private_, val); } |
43446566 | 75 | void Private(const String &v) { |
1da82544 | 76 | setMask(HttpHdrCcType::CC_PRIVATE,true); |
43446566 AR |
77 | if (!v.size()) |
78 | return; | |
1259f9cf | 79 | // uses append for multi-line headers |
b38b26cb | 80 | if (private_.size() > 0) |
1259f9cf AJ |
81 | private_.append(","); |
82 | private_.append(v); | |
83 | } | |
1da82544 | 84 | void clearPrivate() {setMask(HttpHdrCcType::CC_PRIVATE,false); private_.clean();} |
cf7c2e94 FC |
85 | |
86 | //manipulation for Cache-Control: no-cache header | |
810d879f EB |
87 | bool hasNoCacheWithParameters() const { return hasNoCache() && no_cache.size(); } |
88 | bool hasNoCacheWithoutParameters() const { return hasNoCache() && !no_cache.size(); } | |
89 | bool hasNoCache(const String **val = nullptr) const { return hasDirective(HttpHdrCcType::CC_NO_CACHE, &no_cache, val); } | |
43446566 | 90 | void noCache(const String &v) { |
1da82544 | 91 | setMask(HttpHdrCcType::CC_NO_CACHE,true); |
43446566 AR |
92 | if (!v.size()) |
93 | return; | |
1259f9cf | 94 | // uses append for multi-line headers |
43446566 | 95 | if (no_cache.size() > 0 && v.size() > 0) |
1259f9cf AJ |
96 | no_cache.append(","); |
97 | no_cache.append(v); | |
98 | } | |
1da82544 | 99 | void clearNoCache() {setMask(HttpHdrCcType::CC_NO_CACHE,false); no_cache.clean();} |
cf7c2e94 FC |
100 | |
101 | //manipulation for Cache-Control: no-store header | |
1da82544 | 102 | bool hasNoStore() const {return isSet(HttpHdrCcType::CC_NO_STORE);} |
1da82544 FC |
103 | void noStore(bool v) {setMask(HttpHdrCcType::CC_NO_STORE,v);} |
104 | void clearNoStore() {setMask(HttpHdrCcType::CC_NO_STORE,false);} | |
cf7c2e94 FC |
105 | |
106 | //manipulation for Cache-Control: no-transform header | |
1da82544 | 107 | bool hasNoTransform() const {return isSet(HttpHdrCcType::CC_NO_TRANSFORM);} |
1da82544 FC |
108 | void noTransform(bool v) {setMask(HttpHdrCcType::CC_NO_TRANSFORM,v);} |
109 | void clearNoTransform() {setMask(HttpHdrCcType::CC_NO_TRANSFORM,false);} | |
cf7c2e94 FC |
110 | |
111 | //manipulation for Cache-Control: must-revalidate header | |
1da82544 | 112 | bool hasMustRevalidate() const {return isSet(HttpHdrCcType::CC_MUST_REVALIDATE);} |
1da82544 FC |
113 | void mustRevalidate(bool v) {setMask(HttpHdrCcType::CC_MUST_REVALIDATE,v);} |
114 | void clearMustRevalidate() {setMask(HttpHdrCcType::CC_MUST_REVALIDATE,false);} | |
cf7c2e94 FC |
115 | |
116 | //manipulation for Cache-Control: proxy-revalidate header | |
1da82544 | 117 | bool hasProxyRevalidate() const {return isSet(HttpHdrCcType::CC_PROXY_REVALIDATE);} |
1da82544 FC |
118 | void proxyRevalidate(bool v) {setMask(HttpHdrCcType::CC_PROXY_REVALIDATE,v);} |
119 | void clearProxyRevalidate() {setMask(HttpHdrCcType::CC_PROXY_REVALIDATE,false);} | |
cf7c2e94 FC |
120 | |
121 | //manipulation for Cache-Control: max-age header | |
810d879f | 122 | bool hasMaxAge(int32_t *val = nullptr) const { return hasDirective(HttpHdrCcType::CC_MAX_AGE, max_age, val); } |
1da82544 FC |
123 | void maxAge(int32_t v) {setValue(max_age,v,HttpHdrCcType::CC_MAX_AGE); } |
124 | void clearMaxAge() {setValue(max_age,MAX_AGE_UNKNOWN,HttpHdrCcType::CC_MAX_AGE,false);} | |
cf7c2e94 | 125 | |
4ce6e3b5 | 126 | //manipulation for Cache-Control: s-maxage header |
810d879f | 127 | bool hasSMaxAge(int32_t *val = nullptr) const { return hasDirective(HttpHdrCcType::CC_S_MAXAGE, s_maxage, val); } |
1da82544 FC |
128 | void sMaxAge(int32_t v) {setValue(s_maxage,v,HttpHdrCcType::CC_S_MAXAGE); } |
129 | void clearSMaxAge() {setValue(s_maxage,MAX_AGE_UNKNOWN,HttpHdrCcType::CC_S_MAXAGE,false);} | |
4ce6e3b5 FC |
130 | |
131 | //manipulation for Cache-Control: max-stale header | |
810d879f | 132 | bool hasMaxStale(int32_t *val = nullptr) const { return hasDirective(HttpHdrCcType::CC_MAX_STALE, max_stale, val); } |
d74ad83f | 133 | // max-stale has a special value (MAX_STALE_ANY) which correspond to having |
4ce6e3b5 FC |
134 | // the directive without a numeric specification, and directs to consider the object |
135 | // as always-expired. | |
1da82544 FC |
136 | void maxStale(int32_t v) {setValue(max_stale,v,HttpHdrCcType::CC_MAX_STALE);} |
137 | void clearMaxStale() {setValue(max_stale,MAX_STALE_UNKNOWN,HttpHdrCcType::CC_MAX_STALE,false);} | |
4ce6e3b5 FC |
138 | |
139 | //manipulation for Cache-Control:min-fresh header | |
e0072b1d | 140 | bool hasMinFresh(int32_t *val = nullptr) const { return hasDirective(HttpHdrCcType::CC_MIN_FRESH, min_fresh, val); } |
1da82544 FC |
141 | void minFresh(int32_t v) {if (v < 0) return; setValue(min_fresh,v,HttpHdrCcType::CC_MIN_FRESH); } |
142 | void clearMinFresh() {setValue(min_fresh,MIN_FRESH_UNKNOWN,HttpHdrCcType::CC_MIN_FRESH,false);} | |
4ce6e3b5 FC |
143 | |
144 | //manipulation for Cache-Control: only-if-cached header | |
1da82544 | 145 | bool hasOnlyIfCached() const {return isSet(HttpHdrCcType::CC_ONLY_IF_CACHED);} |
1da82544 FC |
146 | void onlyIfCached(bool v) {setMask(HttpHdrCcType::CC_ONLY_IF_CACHED,v);} |
147 | void clearOnlyIfCached() {setMask(HttpHdrCcType::CC_ONLY_IF_CACHED,false);} | |
4ce6e3b5 FC |
148 | |
149 | //manipulation for Cache-Control: stale-if-error header | |
810d879f | 150 | bool hasStaleIfError(int32_t *val = nullptr) const { return hasDirective(HttpHdrCcType::CC_STALE_IF_ERROR, stale_if_error, val); } |
1da82544 FC |
151 | void staleIfError(int32_t v) {setValue(stale_if_error,v,HttpHdrCcType::CC_STALE_IF_ERROR); } |
152 | void clearStaleIfError() {setValue(stale_if_error,STALE_IF_ERROR_UNKNOWN,HttpHdrCcType::CC_STALE_IF_ERROR,false);} | |
cf7c2e94 | 153 | |
caf65351 | 154 | //manipulation for Cache-Control: immutable header |
810d879f | 155 | bool hasImmutable() const {return isSet(HttpHdrCcType::CC_IMMUTABLE);} |
caf65351 AJ |
156 | void Immutable(bool v) {setMask(HttpHdrCcType::CC_IMMUTABLE,v);} |
157 | void clearImmutable() {setMask(HttpHdrCcType::CC_IMMUTABLE,false);} | |
158 | ||
cf7c2e94 | 159 | /// check whether the attribute value supplied by id is set |
22056ef8 AJ |
160 | bool isSet(HttpHdrCcType id) const { |
161 | assert(id < HttpHdrCcType::CC_ENUM_END); | |
162 | return EBIT_TEST(mask, static_cast<long>(id)); | |
163 | } | |
cf7c2e94 | 164 | |
17802cf1 | 165 | void packInto(Packable * p) const; |
4ce6e3b5 | 166 | |
c57b8f05 FC |
167 | /** bit-mask representing what header values are set among those |
168 | * recognized by squid. | |
169 | * | |
170 | * managed via EBIT_SET/TEST/CLR | |
171 | */ | |
1ba0611a | 172 | private: |
b17b9d8d | 173 | int32_t mask; |
7ebe76de FC |
174 | int32_t max_age; |
175 | int32_t s_maxage; | |
176 | int32_t max_stale; | |
177 | int32_t stale_if_error; | |
178 | int32_t min_fresh; | |
1259f9cf AJ |
179 | String private_; ///< List of headers sent as value for CC:private="...". May be empty/undefined if the value is missing. |
180 | String no_cache; ///< List of headers sent as value for CC:no-cache="...". May be empty/undefined if the value is missing. | |
181 | ||
810d879f EB |
182 | /// implements typical has*() method logic |
183 | template<class Value> | |
184 | bool hasDirective(const HttpHdrCcType hdrType, const Value &parsedVal, Value *outVal = nullptr) const { | |
185 | if (isSet(hdrType)) { | |
186 | if (outVal) | |
187 | *outVal = parsedVal; | |
188 | return true; | |
189 | } | |
190 | return false; | |
191 | } | |
192 | ||
cf7c2e94 | 193 | /// low-level part of the public set method, performs no checks |
22056ef8 AJ |
194 | void setMask(HttpHdrCcType id, bool newval=true) { |
195 | if (newval) | |
196 | EBIT_SET(mask,static_cast<long>(id)); | |
197 | else | |
198 | EBIT_CLR(mask, static_cast<long>(id)); | |
199 | } | |
200 | ||
201 | void setValue(int32_t &value, int32_t new_value, HttpHdrCcType hdr, bool setting=true); | |
cf7c2e94 | 202 | |
422acb7f | 203 | public: |
c57b8f05 FC |
204 | /**comma-separated representation of the header values which were |
205 | * received but are not recognized. | |
206 | */ | |
7ebe76de | 207 | String other; |
0abdd70d FC |
208 | }; |
209 | ||
9a117495 FC |
210 | class StatHist; |
211 | class StoreEntry; | |
212 | ||
8a648e8d FC |
213 | void httpHdrCcUpdateStats(const HttpHdrCc * cc, StatHist * hist); |
214 | void httpHdrCcStatDumper(StoreEntry * sentry, int idx, double val, double size, int count); | |
9a117495 | 215 | |
22056ef8 | 216 | std::ostream & operator<< (std::ostream &, HttpHdrCcType); |
9774b48e | 217 | |
ff9d9458 | 218 | #endif /* SQUID_SRC_HTTPHDRCC_H */ |
f53969cc | 219 |