HttpHdrCc.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2022 The Squid Software Foundation and contributors
3  *
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.
7  */
8 
9 /* DEBUG: section 65 HTTP Cache Control Header */
10 
11 #include "squid.h"
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"
18 #include "sbuf/SBuf.h"
19 #include "StatHist.h"
20 #include "Store.h"
21 #include "StrList.h"
22 #include "util.h"
23 
24 #include <map>
25 #include <vector>
26 #include <ostream>
27 
28 // invariant: row[j].id == j
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  {"immutable", HttpHdrCcType::CC_IMMUTABLE},
44  {"Other,", HttpHdrCcType::CC_OTHER}, /* ',' will protect from matches */
46 };
48 std::vector<HttpHeaderFieldStat> ccHeaderStats(HttpHdrCcType::CC_ENUM_END);
49 
51 static HttpHdrCcType &
53 {
54  int tmp = (int)aHeader;
55  aHeader = (HttpHdrCcType)(++tmp);
56  return aHeader;
57 }
58 
60 void
62 {
63  // check invariant on initialization table
64  for (unsigned int j = 0; CcAttrs[j].name != nullptr; ++j) {
65  assert(static_cast<decltype(j)>(CcAttrs[j].id) == j);
66  }
67 }
68 
69 void
71 {
72  *this=HttpHdrCc();
73 }
74 
77 void
78 HttpHdrCc::setValue(int32_t &value, int32_t new_value, HttpHdrCcType hdr, bool setting)
79 {
80  if (setting) {
81  if (new_value < 0) {
82  debugs(65, 3, "rejecting negative-value Cache-Control directive " << hdr
83  << " value " << new_value);
84  return;
85  }
86  } else {
87  new_value = -1; //rely on the convention that "unknown" is -1
88  }
89 
90  value = new_value;
91  setMask(hdr,setting);
92 }
93 
94 bool
96 {
97  const char *item;
98  const char *p; /* '=' parameter */
99  const char *pos = nullptr;
100  int ilen;
101  int nlen;
102 
103  /* iterate through comma separated list */
104 
105  while (strListGetItem(&str, ',', &item, &ilen, &pos)) {
106  /* isolate directive name */
107 
108  if ((p = (const char *)memchr(item, '=', ilen)) && (p - item < ilen)) {
109  nlen = p - item;
110  ++p;
111  } else {
112  nlen = ilen;
113  }
114 
115  /* find type */
116  const HttpHdrCcType type = ccLookupTable.lookup(SBuf(item,nlen));
117 
118  // ignore known duplicate directives
119  if (isSet(type)) {
120  if (type != HttpHdrCcType::CC_OTHER) {
121  debugs(65, 2, "hdr cc: ignoring duplicate cache-directive: near '" << item << "' in '" << str << "'");
122  ++ ccHeaderStats[type].repCount;
123  continue;
124  }
125  }
126 
127  /* special-case-parsing and attribute-setting */
128  switch (type) {
129 
131  if (!p || !httpHeaderParseInt(p, &max_age) || max_age < 0) {
132  debugs(65, 2, "cc: invalid max-age specs near '" << item << "'");
133  clearMaxAge();
134  } else {
135  setMask(type,true);
136  }
137  break;
138 
140  if (!p || !httpHeaderParseInt(p, &s_maxage) || s_maxage < 0) {
141  debugs(65, 2, "cc: invalid s-maxage specs near '" << item << "'");
142  clearSMaxAge();
143  } else {
144  setMask(type,true);
145  }
146  break;
147 
149  if (!p || !httpHeaderParseInt(p, &max_stale) || max_stale < 0) {
150  debugs(65, 2, "cc: max-stale directive is valid without value");
152  } else {
153  setMask(type,true);
154  }
155  break;
156 
158  if (!p || !httpHeaderParseInt(p, &min_fresh) || min_fresh < 0) {
159  debugs(65, 2, "cc: invalid min-fresh specs near '" << item << "'");
160  clearMinFresh();
161  } else {
162  setMask(type,true);
163  }
164  break;
165 
167  if (!p || !httpHeaderParseInt(p, &stale_if_error) || stale_if_error < 0) {
168  debugs(65, 2, "cc: invalid stale-if-error specs near '" << item << "'");
170  } else {
171  setMask(type,true);
172  }
173  break;
174 
176  String temp;
177  if (!p) {
178  // Value parameter is optional.
179  private_.clean();
180  } else if (/* p &&*/ httpHeaderParseQuotedString(p, (ilen-nlen-1), &temp)) {
181  private_.append(temp);
182  } else {
183  debugs(65, 2, "cc: invalid private= specs near '" << item << "'");
184  }
185  // to be safe we ignore broken parameters, but always remember the 'private' part.
186  setMask(type,true);
187  }
188  break;
189 
191  String temp;
192  if (!p) {
193  // On Requests, missing value parameter is expected syntax.
194  // On Responses, value parameter is optional.
195  setMask(type,true);
196  no_cache.clean();
197  } else if (/* p &&*/ httpHeaderParseQuotedString(p, (ilen-nlen-1), &temp)) {
198  // On Requests, a value parameter is invalid syntax.
199  // XXX: identify when parsing request header and dump err message here.
200  setMask(type,true);
201  no_cache.append(temp);
202  } else {
203  debugs(65, 2, "cc: invalid no-cache= specs near '" << item << "'");
204  }
205  }
206  break;
207 
209  Public(true);
210  break;
212  noStore(true);
213  break;
215  noTransform(true);
216  break;
218  mustRevalidate(true);
219  break;
221  proxyRevalidate(true);
222  break;
224  onlyIfCached(true);
225  break;
227  Immutable(true);
228  break;
229 
231  if (other.size())
232  other.append(", ");
233 
234  other.append(item, ilen);
235  break;
236 
237  default:
238  /* note that we ignore most of '=' specs (RFCVIOLATION) */
239  break;
240  }
241  }
242 
243  return (mask != 0);
244 }
245 
246 void
248 {
249  // optimization: if the mask is empty do nothing
250  if (mask==0)
251  return;
252 
253  HttpHdrCcType flag;
254  int pcount = 0;
255  assert(p);
256 
257  for (flag = HttpHdrCcType::CC_PUBLIC; flag < HttpHdrCcType::CC_ENUM_END; ++flag) {
258  if (isSet(flag) && flag != HttpHdrCcType::CC_OTHER) {
259 
260  /* print option name for all options */
261  p->appendf((pcount ? ", %s": "%s"), CcAttrs[flag].name);
262 
263  /* for all options having values, "=value" after the name */
264  switch (flag) {
266  break;
268  if (private_.size())
270  break;
271 
273  if (no_cache.size())
275  break;
277  break;
279  break;
281  break;
283  break;
285  p->appendf("=%d", max_age);
286  break;
288  p->appendf("=%d", s_maxage);
289  break;
291  /* max-stale's value is optional.
292  If we didn't receive it, don't send it */
293  if (max_stale != MAX_STALE_ANY)
294  p->appendf("=%d", max_stale);
295  break;
297  p->appendf("=%d", min_fresh);
298  break;
300  break;
302  p->appendf("=%d", stale_if_error);
303  break;
305  break;
308  // done below after the loop
309  break;
310  }
311 
312  ++pcount;
313  }
314  }
315 
316  if (other.size() != 0)
317  p->appendf((pcount ? ", " SQUIDSTRINGPH : SQUIDSTRINGPH), SQUIDSTRINGPRINT(other));
318 }
319 
320 void
322 {
323  assert(cc);
324 
326  if (cc->isSet(c))
327  hist->count(c);
328 }
329 
330 void
331 httpHdrCcStatDumper(StoreEntry * sentry, int, double val, double, int count)
332 {
333  extern const HttpHeaderStat *dump_stat; /* argh! */
334  const int id = static_cast<int>(val);
335  const bool valid_id = id >= 0 && id < static_cast<int>(HttpHdrCcType::CC_ENUM_END);
336  const char *name = valid_id ? CcAttrs[id].name : "INVALID";
337 
338  if (count || valid_id)
339  storeAppendPrintf(sentry, "%2d\t %-20s\t %5d\t %6.2f\n",
340  id, name, count, xdiv(count, dump_stat->ccParsedCount));
341 }
342 
343 std::ostream &
344 operator<< (std::ostream &s, HttpHdrCcType c)
345 {
346  const unsigned char ic = static_cast<int>(c);
348  s << CcAttrs[ic].name << '[' << ic << ']' ;
349  else
350  s << "*invalid hdrcc* [" << ic << ']';
351  return s;
352 }
353 
void httpHdrCcUpdateStats(const HttpHdrCc *cc, StatHist *hist)
Definition: HttpHdrCc.cc:321
void httpHdrCcInitModule(void)
Module initialization hook.
Definition: HttpHdrCc.cc:61
LookupTable< HttpHdrCcType > ccLookupTable(HttpHdrCcType::CC_OTHER, CcAttrs)
std::vector< HttpHeaderFieldStat > ccHeaderStats(HttpHdrCcType::CC_ENUM_END)
std::ostream & operator<<(std::ostream &s, HttpHdrCcType c)
Definition: HttpHdrCc.cc:344
static LookupTable< HttpHdrCcType >::Record CcAttrs[]
Definition: HttpHdrCc.cc:29
static HttpHdrCcType & operator++(HttpHdrCcType &aHeader)
used to walk a table of http_header_cc_type structs
Definition: HttpHdrCc.cc:52
void httpHdrCcStatDumper(StoreEntry *sentry, int, double val, double, int count)
Definition: HttpHdrCc.cc:331
HttpHdrCcType
Definition: HttpHdrCc.h:20
@ CC_MUST_REVALIDATE
Definition: HttpHdrCc.h:26
@ CC_S_MAXAGE
Definition: HttpHdrCc.h:29
@ CC_ONLY_IF_CACHED
Definition: HttpHdrCc.h:32
@ CC_OTHER
Definition: HttpHdrCc.h:35
@ CC_ENUM_END
Definition: HttpHdrCc.h:36
@ CC_NO_STORE
Definition: HttpHdrCc.h:24
@ CC_PUBLIC
Definition: HttpHdrCc.h:21
@ CC_PRIVATE
Definition: HttpHdrCc.h:22
@ CC_MAX_STALE
Definition: HttpHdrCc.h:30
@ CC_STALE_IF_ERROR
Definition: HttpHdrCc.h:33
@ CC_IMMUTABLE
Definition: HttpHdrCc.h:34
@ CC_PROXY_REVALIDATE
Definition: HttpHdrCc.h:27
@ CC_NO_CACHE
Definition: HttpHdrCc.h:23
@ CC_MAX_AGE
Definition: HttpHdrCc.h:28
@ CC_NO_TRANSFORM
Definition: HttpHdrCc.h:25
@ CC_MIN_FRESH
Definition: HttpHdrCc.h:31
int httpHeaderParseInt(const char *start, int *value)
const HttpHeaderStat * dump_stat
Definition: HttpHeader.cc:1558
int httpHeaderParseQuotedString(const char *start, const int len, String *val)
#define SQUIDSTRINGPH
Definition: SquidString.h:21
#define SQUIDSTRINGPRINT(s)
Definition: SquidString.h:22
int strListGetItem(const String *str, char del, const char **item, int *ilen, const char **pos)
Definition: StrList.cc:86
#define assert(EX)
Definition: assert.h:19
void clear()
reset data-members to default state
Definition: HttpHdrCc.cc:70
String no_cache
List of headers sent as value for CC:no-cache="...". May be empty/undefined if the value is missing.
Definition: HttpHdrCc.h:180
void mustRevalidate(bool v)
Definition: HttpHdrCc.h:113
void clearMinFresh()
Definition: HttpHdrCc.h:142
void Immutable(bool v)
Definition: HttpHdrCc.h:156
void Public(bool v)
Definition: HttpHdrCc.h:70
void noTransform(bool v)
Definition: HttpHdrCc.h:108
void setMask(HttpHdrCcType id, bool newval=true)
low-level part of the public set method, performs no checks
Definition: HttpHdrCc.h:194
bool parse(const String &s)
parse a header-string and fill in appropriate values.
Definition: HttpHdrCc.cc:95
void clearMaxAge()
Definition: HttpHdrCc.h:124
bool isSet(HttpHdrCcType id) const
check whether the attribute value supplied by id is set
Definition: HttpHdrCc.h:160
String private_
List of headers sent as value for CC:private="...". May be empty/undefined if the value is missing.
Definition: HttpHdrCc.h:179
int32_t max_stale
Definition: HttpHdrCc.h:176
void onlyIfCached(bool v)
Definition: HttpHdrCc.h:146
void clearSMaxAge()
Definition: HttpHdrCc.h:129
static const int32_t MAX_STALE_ANY
Definition: HttpHdrCc.h:53
void setValue(int32_t &value, int32_t new_value, HttpHdrCcType hdr, bool setting=true)
Definition: HttpHdrCc.cc:78
int32_t mask
Definition: HttpHdrCc.h:173
int32_t min_fresh
Definition: HttpHdrCc.h:178
void clearStaleIfError()
Definition: HttpHdrCc.h:152
int32_t max_age
Definition: HttpHdrCc.h:174
HttpHdrCc()
Definition: HttpHdrCc.h:57
void noStore(bool v)
Definition: HttpHdrCc.h:103
String other
Definition: HttpHdrCc.h:207
void maxStale(int32_t v)
Definition: HttpHdrCc.h:136
void proxyRevalidate(bool v)
Definition: HttpHdrCc.h:118
int32_t s_maxage
Definition: HttpHdrCc.h:175
void packInto(Packable *p) const
Definition: HttpHdrCc.cc:247
int32_t stale_if_error
Definition: HttpHdrCc.h:177
HTTP per header statistics.
void appendf(const char *fmt,...) PRINTF_FORMAT_ARG2
Append operation with printf-style arguments.
Definition: Packable.h:61
Definition: SBuf.h:94
void count(double val)
Definition: StatHist.cc:55
void clean()
Definition: String.cc:118
void append(char const *buf, int len)
Definition: String.cc:149
size_type size() const
Definition: SquidString.h:73
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Stream.h:196
int type
Definition: errorpage.cc:152
void storeAppendPrintf(StoreEntry *e, const char *fmt,...)
Definition: store.cc:830
int unsigned int
Definition: stub_fd.cc:19
SQUIDCEXTERN double xdiv(double nom, double denom)
Definition: util.c:53

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors