]>
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"
28 // invariant: row[j].id == j
29 static LookupTable
<HttpHdrCcType
>::Record CcAttrs
[] = {
30 {"public", HttpHdrCcType::CC_PUBLIC
},
31 {"private", HttpHdrCcType::CC_PRIVATE
},
32 {"no-cache", HttpHdrCcType::CC_NO_CACHE
},
33 {"no-store", HttpHdrCcType::CC_NO_STORE
},
34 {"no-transform", HttpHdrCcType::CC_NO_TRANSFORM
},
35 {"must-revalidate", HttpHdrCcType::CC_MUST_REVALIDATE
},
36 {"proxy-revalidate", HttpHdrCcType::CC_PROXY_REVALIDATE
},
37 {"max-age", HttpHdrCcType::CC_MAX_AGE
},
38 {"s-maxage", HttpHdrCcType::CC_S_MAXAGE
},
39 {"max-stale", HttpHdrCcType::CC_MAX_STALE
},
40 {"min-fresh", HttpHdrCcType::CC_MIN_FRESH
},
41 {"only-if-cached", HttpHdrCcType::CC_ONLY_IF_CACHED
},
42 {"stale-if-error", HttpHdrCcType::CC_STALE_IF_ERROR
},
43 {"Other,", HttpHdrCcType::CC_OTHER
}, /* ',' will protect from matches */
44 {nullptr, HttpHdrCcType::CC_ENUM_END
}
46 LookupTable
<HttpHdrCcType
> ccLookupTable(HttpHdrCcType::CC_OTHER
,CcAttrs
);
47 std::vector
<HttpHeaderFieldStat
> ccHeaderStats(HttpHdrCcType::CC_ENUM_END
);
49 /// used to walk a table of http_header_cc_type structs
50 HttpHdrCcType
&operator++ (HttpHdrCcType
&aHeader
)
52 int tmp
= (int)aHeader
;
53 aHeader
= (HttpHdrCcType
)(++tmp
);
57 /// Module initialization hook
59 httpHdrCcInitModule(void)
61 // check invariant on initialization table
62 for (unsigned int j
= 0; CcAttrs
[j
].name
!= nullptr; ++j
) {
63 assert (static_cast<int>(CcAttrs
[j
].id
) == j
);
74 HttpHdrCc::parse(const String
& str
)
77 const char *p
; /* '=' parameter */
78 const char *pos
= NULL
;
82 /* iterate through comma separated list */
84 while (strListGetItem(&str
, ',', &item
, &ilen
, &pos
)) {
85 /* isolate directive name */
87 if ((p
= (const char *)memchr(item
, '=', ilen
)) && (p
- item
< ilen
)) {
95 const HttpHdrCcType type
= ccLookupTable
.lookup(SBuf(item
,nlen
));
97 // ignore known duplicate directives
99 if (type
!= HttpHdrCcType::CC_OTHER
) {
100 debugs(65, 2, "hdr cc: ignoring duplicate cache-directive: near '" << item
<< "' in '" << str
<< "'");
101 ++ ccHeaderStats
[type
].repCount
;
106 /* special-case-parsing and attribute-setting */
109 case HttpHdrCcType::CC_MAX_AGE
:
110 if (!p
|| !httpHeaderParseInt(p
, &max_age
) || max_age
< 0) {
111 debugs(65, 2, "cc: invalid max-age specs near '" << item
<< "'");
118 case HttpHdrCcType::CC_S_MAXAGE
:
119 if (!p
|| !httpHeaderParseInt(p
, &s_maxage
) || s_maxage
< 0) {
120 debugs(65, 2, "cc: invalid s-maxage specs near '" << item
<< "'");
127 case HttpHdrCcType::CC_MAX_STALE
:
128 if (!p
|| !httpHeaderParseInt(p
, &max_stale
) || max_stale
< 0) {
129 debugs(65, 2, "cc: max-stale directive is valid without value");
130 maxStale(MAX_STALE_ANY
);
136 case HttpHdrCcType::CC_MIN_FRESH
:
137 if (!p
|| !httpHeaderParseInt(p
, &min_fresh
) || min_fresh
< 0) {
138 debugs(65, 2, "cc: invalid min-fresh specs near '" << item
<< "'");
145 case HttpHdrCcType::CC_STALE_IF_ERROR
:
146 if (!p
|| !httpHeaderParseInt(p
, &stale_if_error
) || stale_if_error
< 0) {
147 debugs(65, 2, "cc: invalid stale-if-error specs near '" << item
<< "'");
154 case HttpHdrCcType::CC_PRIVATE
: {
157 // Value parameter is optional.
159 } else if (/* p &&*/ httpHeaderParseQuotedString(p
, (ilen
-nlen
-1), &temp
)) {
160 private_
.append(temp
);
162 debugs(65, 2, "cc: invalid private= specs near '" << item
<< "'");
164 // to be safe we ignore broken parameters, but always remember the 'private' part.
169 case HttpHdrCcType::CC_NO_CACHE
: {
172 // On Requests, missing value parameter is expected syntax.
173 // On Responses, value parameter is optional.
176 } else if (/* p &&*/ httpHeaderParseQuotedString(p
, (ilen
-nlen
-1), &temp
)) {
177 // On Requests, a value parameter is invalid syntax.
178 // XXX: identify when parsing request header and dump err message here.
180 no_cache
.append(temp
);
182 debugs(65, 2, "cc: invalid no-cache= specs near '" << item
<< "'");
187 case HttpHdrCcType::CC_PUBLIC
:
190 case HttpHdrCcType::CC_NO_STORE
:
193 case HttpHdrCcType::CC_NO_TRANSFORM
:
196 case HttpHdrCcType::CC_MUST_REVALIDATE
:
197 mustRevalidate(true);
199 case HttpHdrCcType::CC_PROXY_REVALIDATE
:
200 proxyRevalidate(true);
202 case HttpHdrCcType::CC_ONLY_IF_CACHED
:
206 case HttpHdrCcType::CC_OTHER
:
210 other
.append(item
, ilen
);
214 /* note that we ignore most of '=' specs (RFCVIOLATION) */
223 HttpHdrCc::packInto(Packable
* p
) const
225 // optimization: if the mask is empty do nothing
233 for (flag
= HttpHdrCcType::CC_PUBLIC
; flag
< HttpHdrCcType::CC_ENUM_END
; ++flag
) {
234 if (isSet(flag
) && flag
!= HttpHdrCcType::CC_OTHER
) {
236 /* print option name for all options */
237 p
->appendf((pcount
? ", %s": "%s") , CcAttrs
[flag
].name
);
239 /* for all options having values, "=value" after the name */
241 case HttpHdrCcType::CC_MAX_AGE
:
242 p
->appendf("=%d", maxAge());
244 case HttpHdrCcType::CC_S_MAXAGE
:
245 p
->appendf("=%d", sMaxAge());
247 case HttpHdrCcType::CC_MAX_STALE
:
248 /* max-stale's value is optional.
249 If we didn't receive it, don't send it */
250 if (maxStale()!=MAX_STALE_ANY
)
251 p
->appendf("=%d", maxStale());
253 case HttpHdrCcType::CC_MIN_FRESH
:
254 p
->appendf("=%d", minFresh());
257 /* do nothing, directive was already printed */
265 if (other
.size() != 0)
266 p
->appendf((pcount
? ", " SQUIDSTRINGPH
: SQUIDSTRINGPH
), SQUIDSTRINGPRINT(other
));
270 httpHdrCcUpdateStats(const HttpHdrCc
* cc
, StatHist
* hist
)
274 for (HttpHdrCcType c
= HttpHdrCcType::CC_PUBLIC
; c
< HttpHdrCcType::CC_ENUM_END
; ++c
)
280 httpHdrCcStatDumper(StoreEntry
* sentry
, int, double val
, double, int count
)
282 extern const HttpHeaderStat
*dump_stat
; /* argh! */
283 const int id
= static_cast<int>(val
);
284 const bool valid_id
= id
< HttpHdrCcType::CC_ENUM_END
;
285 const char *name
= valid_id
? CcAttrs
[id
].name
: "INVALID";
287 if (count
|| valid_id
)
288 storeAppendPrintf(sentry
, "%2d\t %-20s\t %5d\t %6.2f\n",
289 id
, name
, count
, xdiv(count
, dump_stat
->ccParsedCount
));
293 operator<< (std::ostream
&s
, HttpHdrCcType c
)
295 const unsigned char ic
= static_cast<int>(c
);
296 if (c
< HttpHdrCcType::CC_ENUM_END
)
297 s
<< CcAttrs
[ic
].name
<< '[' << ic
<< ']' ;
299 s
<< "*invalid hdrcc* [" << ic
<< ']';
304 #include "HttpHdrCc.cci"