]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/HttpHdrCc.cc
2 * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
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.
9 /* DEBUG: section 65 HTTP Cache Control Header */
12 #include "base/LookupTable.h"
13 #include "HttpHdrCc.h"
14 #include "HttpHeader.h"
15 #include "HttpHeaderFieldStat.h"
16 #include "HttpHeaderStat.h"
17 #include "HttpHeaderTools.h"
27 // invariant: row[j].id == j
28 static LookupTable
<http_hdr_cc_type
>::Record CcAttrs
[] = {
29 {"public", CC_PUBLIC
},
30 {"private", CC_PRIVATE
},
31 {"no-cache", CC_NO_CACHE
},
32 {"no-store", CC_NO_STORE
},
33 {"no-transform", CC_NO_TRANSFORM
},
34 {"must-revalidate", CC_MUST_REVALIDATE
},
35 {"proxy-revalidate", CC_PROXY_REVALIDATE
},
36 {"max-age", CC_MAX_AGE
},
37 {"s-maxage", CC_S_MAXAGE
},
38 {"max-stale", CC_MAX_STALE
},
39 {"min-fresh", CC_MIN_FRESH
},
40 {"only-if-cached", CC_ONLY_IF_CACHED
},
41 {"stale-if-error", CC_STALE_IF_ERROR
},
42 {"Other,", CC_OTHER
}, /* ',' will protect from matches */
43 {nullptr, CC_ENUM_END
}
45 LookupTable
<http_hdr_cc_type
> ccLookupTable(CC_OTHER
,CcAttrs
);
46 std::vector
<HttpHeaderFieldStat
> ccHeaderStats(CC_ENUM_END
);
48 /// used to walk a table of http_header_cc_type structs
49 http_hdr_cc_type
&operator++ (http_hdr_cc_type
&aHeader
)
51 int tmp
= (int)aHeader
;
52 aHeader
= (http_hdr_cc_type
)(++tmp
);
56 /// Module initialization hook
58 httpHdrCcInitModule(void)
60 // check invariant on initialization table
61 for (int j
= 0; CcAttrs
[j
].name
!= nullptr; ++j
) {
62 assert (CcAttrs
[j
].id
== j
);
66 /// Module cleanup hook.
68 httpHdrCcCleanModule(void)
79 HttpHdrCc::parse(const String
& str
)
82 const char *p
; /* '=' parameter */
83 const char *pos
= NULL
;
87 /* iterate through comma separated list */
89 while (strListGetItem(&str
, ',', &item
, &ilen
, &pos
)) {
90 /* isolate directive name */
92 if ((p
= (const char *)memchr(item
, '=', ilen
)) && (p
- item
< ilen
)) {
100 const http_hdr_cc_type type
= ccLookupTable
.lookup(SBuf(item
,nlen
));
102 // ignore known duplicate directives
104 if (type
!= CC_OTHER
) {
105 debugs(65, 2, "hdr cc: ignoring duplicate cache-directive: near '" << item
<< "' in '" << str
<< "'");
106 ++ ccHeaderStats
[type
].repCount
;
111 /* special-case-parsing and attribute-setting */
115 if (!p
|| !httpHeaderParseInt(p
, &max_age
) || max_age
< 0) {
116 debugs(65, 2, "cc: invalid max-age specs near '" << item
<< "'");
124 if (!p
|| !httpHeaderParseInt(p
, &s_maxage
) || s_maxage
< 0) {
125 debugs(65, 2, "cc: invalid s-maxage specs near '" << item
<< "'");
133 if (!p
|| !httpHeaderParseInt(p
, &max_stale
) || max_stale
< 0) {
134 debugs(65, 2, "cc: max-stale directive is valid without value");
135 maxStale(MAX_STALE_ANY
);
142 if (!p
|| !httpHeaderParseInt(p
, &min_fresh
) || min_fresh
< 0) {
143 debugs(65, 2, "cc: invalid min-fresh specs near '" << item
<< "'");
150 case CC_STALE_IF_ERROR
:
151 if (!p
|| !httpHeaderParseInt(p
, &stale_if_error
) || stale_if_error
< 0) {
152 debugs(65, 2, "cc: invalid stale-if-error specs near '" << item
<< "'");
162 // Value parameter is optional.
164 } else if (/* p &&*/ httpHeaderParseQuotedString(p
, (ilen
-nlen
-1), &temp
)) {
165 private_
.append(temp
);
167 debugs(65, 2, "cc: invalid private= specs near '" << item
<< "'");
169 // to be safe we ignore broken parameters, but always remember the 'private' part.
177 // On Requests, missing value parameter is expected syntax.
178 // On Responses, value parameter is optional.
181 } else if (/* p &&*/ httpHeaderParseQuotedString(p
, (ilen
-nlen
-1), &temp
)) {
182 // On Requests, a value parameter is invalid syntax.
183 // XXX: identify when parsing request header and dump err message here.
185 no_cache
.append(temp
);
187 debugs(65, 2, "cc: invalid no-cache= specs near '" << item
<< "'");
198 case CC_NO_TRANSFORM
:
201 case CC_MUST_REVALIDATE
:
202 mustRevalidate(true);
204 case CC_PROXY_REVALIDATE
:
205 proxyRevalidate(true);
207 case CC_ONLY_IF_CACHED
:
215 other
.append(item
, ilen
);
219 /* note that we ignore most of '=' specs (RFCVIOLATION) */
228 HttpHdrCc::packInto(Packable
* p
) const
230 // optimization: if the mask is empty do nothing
234 http_hdr_cc_type flag
;
238 for (flag
= CC_PUBLIC
; flag
< CC_ENUM_END
; ++flag
) {
239 if (isSet(flag
) && flag
!= CC_OTHER
) {
241 /* print option name for all options */
242 p
->appendf((pcount
? ", %s": "%s") , CcAttrs
[flag
].name
);
244 /* for all options having values, "=value" after the name */
247 p
->appendf("=%d", maxAge());
250 p
->appendf("=%d", sMaxAge());
253 /* max-stale's value is optional.
254 If we didn't receive it, don't send it */
255 if (maxStale()!=MAX_STALE_ANY
)
256 p
->appendf("=%d", maxStale());
259 p
->appendf("=%d", minFresh());
262 /* do nothing, directive was already printed */
270 if (other
.size() != 0)
271 p
->appendf((pcount
? ", " SQUIDSTRINGPH
: SQUIDSTRINGPH
), SQUIDSTRINGPRINT(other
));
275 httpHdrCcUpdateStats(const HttpHdrCc
* cc
, StatHist
* hist
)
279 for (http_hdr_cc_type c
= CC_PUBLIC
; c
< CC_ENUM_END
; ++c
)
285 httpHdrCcStatDumper(StoreEntry
* sentry
, int, double val
, double, int count
)
287 extern const HttpHeaderStat
*dump_stat
; /* argh! */
288 const int id
= static_cast<int>(val
);
289 const int valid_id
= id
< CC_ENUM_END
;
290 const char *name
= valid_id
? CcAttrs
[id
].name
: "INVALID";
292 if (count
|| valid_id
)
293 storeAppendPrintf(sentry
, "%2d\t %-20s\t %5d\t %6.2f\n",
294 id
, name
, count
, xdiv(count
, dump_stat
->ccParsedCount
));
298 #include "HttpHdrCc.cci"