HttpHdrCc.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2017 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 
52 {
53  int tmp = (int)aHeader;
54  aHeader = (HttpHdrCcType)(++tmp);
55  return aHeader;
56 }
57 
59 void
61 {
62  // check invariant on initialization table
63  for (unsigned int j = 0; CcAttrs[j].name != nullptr; ++j) {
64  assert (static_cast<int>(CcAttrs[j].id) == j);
65  }
66 }
67 
68 void
70 {
71  *this=HttpHdrCc();
72 }
73 
76 void
77 HttpHdrCc::setValue(int32_t &value, int32_t new_value, HttpHdrCcType hdr, bool setting)
78 {
79  if (setting) {
80  if (new_value < 0) {
81  debugs(65, 3, "rejecting negative-value Cache-Control directive " << hdr
82  << " value " << new_value);
83  return;
84  }
85  } else {
86  new_value = -1; //rely on the convention that "unknown" is -1
87  }
88 
89  value = new_value;
90  setMask(hdr,setting);
91 }
92 
93 bool
95 {
96  const char *item;
97  const char *p; /* '=' parameter */
98  const char *pos = NULL;
99  int ilen;
100  int nlen;
101 
102  /* iterate through comma separated list */
103 
104  while (strListGetItem(&str, ',', &item, &ilen, &pos)) {
105  /* isolate directive name */
106 
107  if ((p = (const char *)memchr(item, '=', ilen)) && (p - item < ilen)) {
108  nlen = p - item;
109  ++p;
110  } else {
111  nlen = ilen;
112  }
113 
114  /* find type */
115  const HttpHdrCcType type = ccLookupTable.lookup(SBuf(item,nlen));
116 
117  // ignore known duplicate directives
118  if (isSet(type)) {
119  if (type != HttpHdrCcType::CC_OTHER) {
120  debugs(65, 2, "hdr cc: ignoring duplicate cache-directive: near '" << item << "' in '" << str << "'");
121  ++ ccHeaderStats[type].repCount;
122  continue;
123  }
124  }
125 
126  /* special-case-parsing and attribute-setting */
127  switch (type) {
128 
130  if (!p || !httpHeaderParseInt(p, &max_age) || max_age < 0) {
131  debugs(65, 2, "cc: invalid max-age specs near '" << item << "'");
132  clearMaxAge();
133  } else {
134  setMask(type,true);
135  }
136  break;
137 
139  if (!p || !httpHeaderParseInt(p, &s_maxage) || s_maxage < 0) {
140  debugs(65, 2, "cc: invalid s-maxage specs near '" << item << "'");
141  clearSMaxAge();
142  } else {
143  setMask(type,true);
144  }
145  break;
146 
148  if (!p || !httpHeaderParseInt(p, &max_stale) || max_stale < 0) {
149  debugs(65, 2, "cc: max-stale directive is valid without value");
151  } else {
152  setMask(type,true);
153  }
154  break;
155 
157  if (!p || !httpHeaderParseInt(p, &min_fresh) || min_fresh < 0) {
158  debugs(65, 2, "cc: invalid min-fresh specs near '" << item << "'");
159  clearMinFresh();
160  } else {
161  setMask(type,true);
162  }
163  break;
164 
166  if (!p || !httpHeaderParseInt(p, &stale_if_error) || stale_if_error < 0) {
167  debugs(65, 2, "cc: invalid stale-if-error specs near '" << item << "'");
169  } else {
170  setMask(type,true);
171  }
172  break;
173 
175  String temp;
176  if (!p) {
177  // Value parameter is optional.
178  private_.clean();
179  } else if (/* p &&*/ httpHeaderParseQuotedString(p, (ilen-nlen-1), &temp)) {
180  private_.append(temp);
181  } else {
182  debugs(65, 2, "cc: invalid private= specs near '" << item << "'");
183  }
184  // to be safe we ignore broken parameters, but always remember the 'private' part.
185  setMask(type,true);
186  }
187  break;
188 
190  String temp;
191  if (!p) {
192  // On Requests, missing value parameter is expected syntax.
193  // On Responses, value parameter is optional.
194  setMask(type,true);
195  no_cache.clean();
196  } else if (/* p &&*/ httpHeaderParseQuotedString(p, (ilen-nlen-1), &temp)) {
197  // On Requests, a value parameter is invalid syntax.
198  // XXX: identify when parsing request header and dump err message here.
199  setMask(type,true);
200  no_cache.append(temp);
201  } else {
202  debugs(65, 2, "cc: invalid no-cache= specs near '" << item << "'");
203  }
204  }
205  break;
206 
208  Public(true);
209  break;
211  noStore(true);
212  break;
214  noTransform(true);
215  break;
217  mustRevalidate(true);
218  break;
220  proxyRevalidate(true);
221  break;
223  onlyIfCached(true);
224  break;
226  Immutable(true);
227  break;
228 
230  if (other.size())
231  other.append(", ");
232 
233  other.append(item, ilen);
234  break;
235 
236  default:
237  /* note that we ignore most of '=' specs (RFCVIOLATION) */
238  break;
239  }
240  }
241 
242  return (mask != 0);
243 }
244 
245 void
247 {
248  // optimization: if the mask is empty do nothing
249  if (mask==0)
250  return;
251 
252  HttpHdrCcType flag;
253  int pcount = 0;
254  assert(p);
255 
256  for (flag = HttpHdrCcType::CC_PUBLIC; flag < HttpHdrCcType::CC_ENUM_END; ++flag) {
257  if (isSet(flag) && flag != HttpHdrCcType::CC_OTHER) {
258 
259  /* print option name for all options */
260  p->appendf((pcount ? ", %s": "%s"), CcAttrs[flag].name);
261 
262  /* for all options having values, "=value" after the name */
263  switch (flag) {
265  break;
267  if (private_.size())
269  break;
270 
272  if (no_cache.size())
274  break;
276  break;
278  break;
280  break;
282  break;
284  p->appendf("=%d", max_age);
285  break;
287  p->appendf("=%d", s_maxage);
288  break;
290  /* max-stale's value is optional.
291  If we didn't receive it, don't send it */
292  if (max_stale != MAX_STALE_ANY)
293  p->appendf("=%d", max_stale);
294  break;
296  p->appendf("=%d", min_fresh);
297  break;
299  break;
301  p->appendf("=%d", stale_if_error);
302  break;
304  break;
306  case HttpHdrCcType::CC_ENUM_END:
307  // done below after the loop
308  break;
309  }
310 
311  ++pcount;
312  }
313  }
314 
315  if (other.size() != 0)
316  p->appendf((pcount ? ", " SQUIDSTRINGPH : SQUIDSTRINGPH), SQUIDSTRINGPRINT(other));
317 }
318 
319 void
321 {
322  assert(cc);
323 
325  if (cc->isSet(c))
326  hist->count(c);
327 }
328 
329 void
330 httpHdrCcStatDumper(StoreEntry * sentry, int, double val, double, int count)
331 {
332  extern const HttpHeaderStat *dump_stat; /* argh! */
333  const int id = static_cast<int>(val);
334  const bool valid_id = id >= 0 && id < static_cast<int>(HttpHdrCcType::CC_ENUM_END);
335  const char *name = valid_id ? CcAttrs[id].name : "INVALID";
336 
337  if (count || valid_id)
338  storeAppendPrintf(sentry, "%2d\t %-20s\t %5d\t %6.2f\n",
339  id, name, count, xdiv(count, dump_stat->ccParsedCount));
340 }
341 
342 std::ostream &
343 operator<< (std::ostream &s, HttpHdrCcType c)
344 {
345  const unsigned char ic = static_cast<int>(c);
347  s << CcAttrs[ic].name << '[' << ic << ']' ;
348  else
349  s << "*invalid hdrcc* [" << ic << ']';
350  return s;
351 }
352 
void clearStaleIfError()
Definition: HttpHdrCc.h:152
int32_t max_age
Definition: HttpHdrCc.h:174
#define SQUIDSTRINGPH
Definition: SquidString.h:20
void count(double val)
Definition: StatHist.cc:57
int strListGetItem(const String *str, char del, const char **item, int *ilen, const char **pos)
Definition: StrList.cc:77
#define assert(EX)
Definition: assert.h:17
#define SQUIDSTRINGPRINT(s)
Definition: SquidString.h:21
String other
Definition: HttpHdrCc.h:207
int httpHeaderParseQuotedString(const char *start, const int len, String *val)
int type
Definition: errorpage.cc:79
Definition: SBuf.h:87
HttpHdrCcType & operator++(HttpHdrCcType &aHeader)
used to walk a table of http_header_cc_type structs
Definition: HttpHdrCc.cc:51
void clearMaxAge()
Definition: HttpHdrCc.h:124
void clearSMaxAge()
Definition: HttpHdrCc.h:129
void httpHdrCcStatDumper(StoreEntry *sentry, int, double val, double, int count)
Definition: HttpHdrCc.cc:330
char * p
Definition: membanger.c:43
std::ostream & operator<<(std::ostream &s, HttpHdrCcType c)
Definition: HttpHdrCc.cc:343
size_type size() const
Definition: SquidString.h:71
void append(char const *buf, int len)
Definition: String.cc:161
int32_t mask
Definition: HttpHdrCc.h:173
HttpHdrCc()
Definition: HttpHdrCc.h:57
void maxStale(int32_t v)
Definition: HttpHdrCc.h:136
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Debug.h:123
void noTransform(bool v)
Definition: HttpHdrCc.h:108
static const int32_t MAX_STALE_ANY
Definition: HttpHdrCc.h:53
void mustRevalidate(bool v)
Definition: HttpHdrCc.h:113
void setValue(int32_t &value, int32_t new_value, HttpHdrCcType hdr, bool setting=true)
Definition: HttpHdrCc.cc:77
int32_t min_fresh
Definition: HttpHdrCc.h:178
int32_t s_maxage
Definition: HttpHdrCc.h:175
int32_t stale_if_error
Definition: HttpHdrCc.h:177
bool parse(const String &s)
parse a header-string and fill in appropriate values.
Definition: HttpHdrCc.cc:94
void Public(bool v)
Definition: HttpHdrCc.h: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 Immutable(bool v)
Definition: HttpHdrCc.h:156
HTTP per header statistics.
bool SIGHDLR int STUB void int
Definition: stub_tools.cc:68
void httpHdrCcInitModule(void)
Module initialization hook.
Definition: HttpHdrCc.cc:60
void noStore(bool v)
Definition: HttpHdrCc.h:103
void onlyIfCached(bool v)
Definition: HttpHdrCc.h:146
String private_
List of headers sent as value for CC:private="...". May be empty/undefined if the value is missing...
Definition: HttpHdrCc.h:179
SQUIDCEXTERN double xdiv(double nom, double denom)
Definition: util.c:72
void appendf(const char *fmt,...) PRINTF_FORMAT_ARG2
Append operation with printf-style arguments.
Definition: Packable.h:61
void proxyRevalidate(bool v)
Definition: HttpHdrCc.h:118
void packInto(Packable *p) const
Definition: HttpHdrCc.cc:246
void httpHdrCcUpdateStats(const HttpHdrCc *cc, StatHist *hist)
Definition: HttpHdrCc.cc:320
LookupTable< HttpHdrCcType > ccLookupTable(HttpHdrCcType::CC_OTHER, CcAttrs)
void clearMinFresh()
Definition: HttpHdrCc.h:142
void clean()
Definition: String.cc:125
bool isSet(HttpHdrCcType id) const
check whether the attribute value supplied by id is set
Definition: HttpHdrCc.h:160
const HttpHeaderStat * dump_stat
Definition: HttpHeader.cc:1565
HttpHdrCcType
Definition: HttpHdrCc.h:20
void clear()
reset data-members to default state
Definition: HttpHdrCc.cc:69
const char * name
Definition: LookupTable.h:29
void storeAppendPrintf(StoreEntry *e, const char *fmt,...)
Definition: store.cc:904
int32_t max_stale
Definition: HttpHdrCc.h:176
#define NULL
Definition: types.h:166
void setMask(HttpHdrCcType id, bool newval=true)
low-level part of the public set method, performs no checks
Definition: HttpHdrCc.h:194
std::vector< HttpHeaderFieldStat > ccHeaderStats(HttpHdrCcType::CC_ENUM_END)
int httpHeaderParseInt(const char *start, int *value)

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors