]>
Commit | Line | Data |
---|---|---|
7faf2bdb | 1 | /* |
7faf2bdb | 2 | * |
3 | * DEBUG: section 65 HTTP Cache Control Header | |
7faf2bdb | 4 | * |
2b6662ba | 5 | * SQUID Web Proxy Cache http://www.squid-cache.org/ |
e25c139f | 6 | * ---------------------------------------------------------- |
7faf2bdb | 7 | * |
2b6662ba | 8 | * Squid is the result of efforts by numerous individuals from |
9 | * the Internet community; see the CONTRIBUTORS file for full | |
10 | * details. Many organizations have provided support for Squid's | |
11 | * development; see the SPONSORS file for full details. Squid is | |
12 | * Copyrighted (C) 2001 by the Regents of the University of | |
13 | * California; see the COPYRIGHT file for full details. Squid | |
14 | * incorporates software developed and/or copyrighted by other | |
15 | * sources; see the CREDITS file for full details. | |
7faf2bdb | 16 | * |
17 | * This program is free software; you can redistribute it and/or modify | |
18 | * it under the terms of the GNU General Public License as published by | |
19 | * the Free Software Foundation; either version 2 of the License, or | |
20 | * (at your option) any later version. | |
26ac0430 | 21 | * |
7faf2bdb | 22 | * This program is distributed in the hope that it will be useful, |
23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
25 | * GNU General Public License for more details. | |
26ac0430 | 26 | * |
7faf2bdb | 27 | * You should have received a copy of the GNU General Public License |
28 | * along with this program; if not, write to the Free Software | |
cbdec147 | 29 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. |
7faf2bdb | 30 | * |
31 | */ | |
32 | ||
33 | #include "squid.h" | |
46cba5d3 | 34 | #include "base/StringArea.h" |
e6ccf245 | 35 | #include "Store.h" |
36 | #include "HttpHeader.h" | |
ce394734 FC |
37 | #include "HttpHdrCc.h" |
38 | ||
39 | #if HAVE_MAP | |
40 | #include <map> | |
41 | #endif | |
42 | ||
d4cb5913 | 43 | /* a row in the table used for parsing cache control header and statistics */ |
ce394734 FC |
44 | typedef struct { |
45 | const char *name; | |
46 | http_hdr_cc_type id; | |
47 | HttpHeaderFieldStat stat; | |
48 | } HttpHeaderCcFields; | |
49 | ||
50 | /* order must match that of enum http_hdr_cc_type. The constraint is verified at initialization time */ | |
51 | static HttpHeaderCcFields CcAttrs[CC_ENUM_END] = { | |
52 | {"public", CC_PUBLIC}, | |
53 | {"private", CC_PRIVATE}, | |
54 | {"no-cache", CC_NO_CACHE}, | |
55 | {"no-store", CC_NO_STORE}, | |
56 | {"no-transform", CC_NO_TRANSFORM}, | |
57 | {"must-revalidate", CC_MUST_REVALIDATE}, | |
58 | {"proxy-revalidate", CC_PROXY_REVALIDATE}, | |
59 | {"max-age", CC_MAX_AGE}, | |
60 | {"s-maxage", CC_S_MAXAGE}, | |
61 | {"max-stale", CC_MAX_STALE}, | |
62 | {"min-fresh", CC_MIN_FRESH}, | |
63 | {"only-if-cached", CC_ONLY_IF_CACHED}, | |
64 | {"stale-if-error", CC_STALE_IF_ERROR}, | |
65 | {"Other,", CC_OTHER} /* ',' will protect from matches */ | |
26ac0430 | 66 | }; |
62e76326 | 67 | |
ce394734 | 68 | /// Map an header name to its type, to expedite parsing |
46cba5d3 | 69 | typedef std::map<const StringArea,http_hdr_cc_type> CcNameToIdMap_t; |
7ebe76de | 70 | static CcNameToIdMap_t CcNameToIdMap; |
7faf2bdb | 71 | |
d74ad83f | 72 | /// used to walk a table of http_header_cc_type structs |
e6ccf245 | 73 | http_hdr_cc_type &operator++ (http_hdr_cc_type &aHeader) |
74 | { | |
1f1ae50a | 75 | int tmp = (int)aHeader; |
76 | aHeader = (http_hdr_cc_type)(++tmp); | |
e6ccf245 | 77 | return aHeader; |
78 | } | |
79 | ||
80 | ||
c23f7c32 | 81 | /// Module initialization hook |
7faf2bdb | 82 | void |
9bc73deb | 83 | httpHdrCcInitModule(void) |
7faf2bdb | 84 | { |
ce394734 | 85 | /* build lookup and accounting structures */ |
7ebe76de | 86 | for (int32_t i = 0;i < CC_ENUM_END; ++i) { |
46cba5d3 FC |
87 | const HttpHeaderCcFields &f=CcAttrs[i]; |
88 | assert(i == f.id); /* verify assumption: the id is the key into the array */ | |
89 | const StringArea k(f.name,strlen(f.name)); | |
90 | CcNameToIdMap[k]=f.id; | |
ce394734 | 91 | } |
de336bbe | 92 | } |
93 | ||
c23f7c32 | 94 | /// Module cleanup hook. |
de336bbe | 95 | void |
9bc73deb | 96 | httpHdrCcCleanModule(void) |
de336bbe | 97 | { |
ce394734 | 98 | // HdrCcNameToIdMap is self-cleaning |
7faf2bdb | 99 | } |
100 | ||
ce394734 FC |
101 | void |
102 | HttpHdrCc::clear() | |
7faf2bdb | 103 | { |
7ebe76de | 104 | *this=HttpHdrCc(); |
7faf2bdb | 105 | } |
106 | ||
ce394734 | 107 | bool |
7ebe76de | 108 | HttpHdrCc::parse(const String & str) |
7faf2bdb | 109 | { |
110 | const char *item; | |
111 | const char *p; /* '=' parameter */ | |
112 | const char *pos = NULL; | |
e6ccf245 | 113 | http_hdr_cc_type type; |
7faf2bdb | 114 | int ilen; |
1b2e9616 | 115 | int nlen; |
7faf2bdb | 116 | |
7faf2bdb | 117 | /* iterate through comma separated list */ |
62e76326 | 118 | |
ce394734 | 119 | while (strListGetItem(&str, ',', &item, &ilen, &pos)) { |
1b2e9616 | 120 | /* isolate directive name */ |
62e76326 | 121 | |
1b2e9616 | 122 | if ((p = (const char *)memchr(item, '=', ilen)) && (p - item < ilen)) |
123 | nlen = p++ - item; | |
124 | else | |
125 | nlen = ilen; | |
62e76326 | 126 | |
127 | /* find type */ | |
cf7c2e94 | 128 | const CcNameToIdMap_t::const_iterator i=CcNameToIdMap.find(StringArea(item,nlen)); |
7ebe76de | 129 | if (i==CcNameToIdMap.end()) |
ce394734 FC |
130 | type=CC_OTHER; |
131 | else | |
132 | type=i->second; | |
62e76326 | 133 | |
aa62670a | 134 | // ignore known duplicate directives |
f9517ad8 | 135 | if (isSet(type)) { |
aa62670a | 136 | if (type != CC_OTHER) { |
e8466ea9 | 137 | debugs(65, 2, "hdr cc: ignoring duplicate cache-directive: near '" << item << "' in '" << str << "'"); |
7ebe76de | 138 | ++CcAttrs[type].stat.repCount; |
aa62670a AR |
139 | continue; |
140 | } | |
62e76326 | 141 | } |
142 | ||
4ce6e3b5 | 143 | /* special-case-parsing and attribute-setting */ |
62e76326 | 144 | switch (type) { |
145 | ||
146 | case CC_MAX_AGE: | |
d74ad83f | 147 | if (!p || !httpHeaderParseInt(p, &max_age) || max_age < 0) { |
bf8fe701 | 148 | debugs(65, 2, "cc: invalid max-age specs near '" << item << "'"); |
4ce6e3b5 | 149 | clearMaxAge(); |
1ba0611a | 150 | } else { |
d74ad83f | 151 | setMask(type,true); |
62e76326 | 152 | } |
62e76326 | 153 | break; |
154 | ||
155 | case CC_S_MAXAGE: | |
d74ad83f | 156 | if (!p || !httpHeaderParseInt(p, &s_maxage) || s_maxage < 0) { |
bf8fe701 | 157 | debugs(65, 2, "cc: invalid s-maxage specs near '" << item << "'"); |
4ce6e3b5 | 158 | clearSMaxAge(); |
d74ad83f FC |
159 | } else { |
160 | setMask(type,true); | |
62e76326 | 161 | } |
62e76326 | 162 | break; |
163 | ||
164 | case CC_MAX_STALE: | |
d74ad83f | 165 | if (!p || !httpHeaderParseInt(p, &max_stale) || max_stale < 0) { |
bf8fe701 | 166 | debugs(65, 2, "cc: max-stale directive is valid without value"); |
d74ad83f FC |
167 | maxStale(MAX_STALE_ANY); |
168 | } else { | |
169 | setMask(type,true); | |
62e76326 | 170 | } |
62e76326 | 171 | break; |
172 | ||
64f8c2cb | 173 | case CC_MIN_FRESH: |
d74ad83f | 174 | if (!p || !httpHeaderParseInt(p, &min_fresh) || min_fresh < 0) { |
64f8c2cb | 175 | debugs(65, 2, "cc: invalid min-fresh specs near '" << item << "'"); |
4ce6e3b5 | 176 | clearMinFresh(); |
d74ad83f FC |
177 | } else { |
178 | setMask(type,true); | |
64f8c2cb | 179 | } |
64f8c2cb AR |
180 | break; |
181 | ||
65fd3895 | 182 | case CC_STALE_IF_ERROR: |
d74ad83f | 183 | if (!p || !httpHeaderParseInt(p, &stale_if_error) || stale_if_error < 0) { |
65fd3895 | 184 | debugs(65, 2, "cc: invalid stale-if-error specs near '" << item << "'"); |
4ce6e3b5 | 185 | clearStaleIfError(); |
d74ad83f FC |
186 | } else { |
187 | setMask(type,true); | |
65fd3895 AJ |
188 | } |
189 | break; | |
190 | ||
4ce6e3b5 FC |
191 | case CC_PUBLIC: Public(true); break; |
192 | case CC_PRIVATE: Private(true); break; | |
193 | case CC_NO_CACHE: noCache(true); break; | |
194 | case CC_NO_STORE: noStore(true); break; | |
195 | case CC_NO_TRANSFORM: noTransform(true); break; | |
196 | case CC_MUST_REVALIDATE: mustRevalidate(true); break; | |
197 | case CC_PROXY_REVALIDATE: proxyRevalidate(true); break; | |
198 | case CC_ONLY_IF_CACHED: onlyIfCached(true); break; | |
1b2e9616 | 199 | |
4ce6e3b5 | 200 | case CC_OTHER: |
f9517ad8 FC |
201 | if (other.size()) |
202 | other.append(", "); | |
1b2e9616 | 203 | |
f9517ad8 | 204 | other.append(item, ilen); |
1b2e9616 | 205 | break; |
206 | ||
62e76326 | 207 | default: |
1b2e9616 | 208 | /* note that we ignore most of '=' specs (RFCVIOLATION) */ |
62e76326 | 209 | break; |
210 | } | |
7faf2bdb | 211 | } |
62e76326 | 212 | |
f9517ad8 | 213 | return (mask != 0); |
7faf2bdb | 214 | } |
215 | ||
7faf2bdb | 216 | void |
4ce6e3b5 | 217 | HttpHdrCc::packInto(Packer * p) const |
7faf2bdb | 218 | { |
219 | http_hdr_cc_type flag; | |
220 | int pcount = 0; | |
4ce6e3b5 | 221 | assert(p); |
62e76326 | 222 | |
e6ccf245 | 223 | for (flag = CC_PUBLIC; flag < CC_ENUM_END; ++flag) { |
4ce6e3b5 | 224 | if (isSet(flag) && flag != CC_OTHER) { |
62e76326 | 225 | |
226 | /* print option name */ | |
ce394734 | 227 | packerPrintf(p, (pcount ? ", %s": "%s") , CcAttrs[flag].name); |
91274dd0 | 228 | |
62e76326 | 229 | /* handle options with values */ |
91274dd0 | 230 | |
62e76326 | 231 | if (flag == CC_MAX_AGE) |
4ce6e3b5 | 232 | packerPrintf(p, "=%d", (int) maxAge()); |
91274dd0 | 233 | |
62e76326 | 234 | if (flag == CC_S_MAXAGE) |
4ce6e3b5 | 235 | packerPrintf(p, "=%d", (int) sMaxAge()); |
7e3ce7b9 | 236 | |
d74ad83f | 237 | if (flag == CC_MAX_STALE && maxStale()!=MAX_STALE_ANY) |
4ce6e3b5 | 238 | packerPrintf(p, "=%d", (int) maxStale()); |
49ff0930 | 239 | |
64f8c2cb | 240 | if (flag == CC_MIN_FRESH) |
4ce6e3b5 | 241 | packerPrintf(p, "=%d", (int) minFresh()); |
64f8c2cb | 242 | |
7ebe76de | 243 | ++pcount; |
62e76326 | 244 | } |
7faf2bdb | 245 | } |
1b2e9616 | 246 | |
4ce6e3b5 | 247 | if (other.size() != 0) |
826a1fed | 248 | packerPrintf(p, (pcount ? ", " SQUIDSTRINGPH : SQUIDSTRINGPH), |
4ce6e3b5 | 249 | SQUIDSTRINGPRINT(other)); |
7faf2bdb | 250 | } |
251 | ||
7faf2bdb | 252 | void |
253 | httpHdrCcUpdateStats(const HttpHdrCc * cc, StatHist * hist) | |
254 | { | |
255 | http_hdr_cc_type c; | |
256 | assert(cc); | |
62e76326 | 257 | |
e6ccf245 | 258 | for (c = CC_PUBLIC; c < CC_ENUM_END; ++c) |
f9517ad8 | 259 | if (cc->isSet(c)) |
62e76326 | 260 | statHistCount(hist, c); |
7faf2bdb | 261 | } |
262 | ||
263 | void | |
264 | httpHdrCcStatDumper(StoreEntry * sentry, int idx, double val, double size, int count) | |
265 | { | |
0cdcddb9 | 266 | extern const HttpHeaderStat *dump_stat; /* argh! */ |
7faf2bdb | 267 | const int id = (int) val; |
268 | const int valid_id = id >= 0 && id < CC_ENUM_END; | |
ce394734 | 269 | const char *name = valid_id ? CcAttrs[id].name : "INVALID"; |
62e76326 | 270 | |
7faf2bdb | 271 | if (count || valid_id) |
62e76326 | 272 | storeAppendPrintf(sentry, "%2d\t %-20s\t %5d\t %6.2f\n", |
273 | id, name, count, xdiv(count, dump_stat->ccParsedCount)); | |
7faf2bdb | 274 | } |
1ba0611a | 275 | |
9774b48e FC |
276 | #if !_USE_INLINE_ |
277 | #include "HttpHdrCc.cci" | |
278 | #endif |