3 * $Id: HttpHdrCc.cc,v 1.22 2001/01/12 00:37:13 wessels Exp $
5 * DEBUG: section 65 HTTP Cache Control Header
6 * AUTHOR: Alex Rousskov
8 * SQUID Web Proxy Cache http://www.squid-cache.org/
9 * ----------------------------------------------------------
11 * Squid is the result of efforts by numerous individuals from
12 * the Internet community; see the CONTRIBUTORS file for full
13 * details. Many organizations have provided support for Squid's
14 * development; see the SPONSORS file for full details. Squid is
15 * Copyrighted (C) 2001 by the Regents of the University of
16 * California; see the COPYRIGHT file for full details. Squid
17 * incorporates software developed and/or copyrighted by other
18 * sources; see the CREDITS file for full details.
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
38 /* this table is used for parsing cache control header */
39 static const HttpHeaderFieldAttrs CcAttrs
[CC_ENUM_END
] =
41 {"public", CC_PUBLIC
},
42 {"private", CC_PRIVATE
},
43 {"no-cache", CC_NO_CACHE
},
44 {"no-store", CC_NO_STORE
},
45 {"no-transform", CC_NO_TRANSFORM
},
46 {"must-revalidate", CC_MUST_REVALIDATE
},
47 {"proxy-revalidate", CC_PROXY_REVALIDATE
},
48 {"only-if-cached", CC_ONLY_IF_CACHED
},
49 {"max-age", CC_MAX_AGE
},
50 {"s-maxage", CC_S_MAXAGE
},
51 {"max-stale", CC_MAX_STALE
},
52 {"Other,", CC_OTHER
} /* ',' will protect from matches */
54 HttpHeaderFieldInfo
*CcFieldsInfo
= NULL
;
56 /* local prototypes */
57 static int httpHdrCcParseInit(HttpHdrCc
* cc
, const String
* str
);
60 /* module initialization */
63 httpHdrCcInitModule(void)
65 CcFieldsInfo
= httpHeaderBuildFieldsInfo(CcAttrs
, CC_ENUM_END
);
69 httpHdrCcCleanModule(void)
71 httpHeaderDestroyFieldsInfo(CcFieldsInfo
, CC_ENUM_END
);
80 HttpHdrCc
*cc
= memAllocate(MEM_HTTP_HDR_CC
);
81 cc
->max_age
= cc
->s_maxage
= cc
->max_stale
= -1;
85 /* creates an cc object from a 0-terminating string */
87 httpHdrCcParseCreate(const String
* str
)
89 HttpHdrCc
*cc
= httpHdrCcCreate();
90 if (!httpHdrCcParseInit(cc
, str
)) {
97 /* parses a 0-terminating string and inits cc */
99 httpHdrCcParseInit(HttpHdrCc
* cc
, const String
* str
)
102 const char *p
; /* '=' parameter */
103 const char *pos
= NULL
;
108 /* iterate through comma separated list */
109 while (strListGetItem(str
, ',', &item
, &ilen
, &pos
)) {
110 /* strip '=' statements @?@ */
111 if ((p
= strchr(item
, '=')) && (p
- item
< ilen
))
114 type
= httpHeaderIdByName(item
, ilen
,
115 CcFieldsInfo
, CC_ENUM_END
);
117 debug(65, 2) ("hdr cc: unknown cache-directive: near '%s' in '%s'\n", item
, strBuf(*str
));
120 if (EBIT_TEST(cc
->mask
, type
)) {
121 if (type
!= CC_OTHER
)
122 debug(65, 2) ("hdr cc: ignoring duplicate cache-directive: near '%s' in '%s'\n", item
, strBuf(*str
));
123 CcFieldsInfo
[type
].stat
.repCount
++;
127 EBIT_SET(cc
->mask
, type
);
128 /* post-processing special cases */
131 if (!p
|| !httpHeaderParseInt(p
, &cc
->max_age
)) {
132 debug(65, 2) ("cc: invalid max-age specs near '%s'\n", item
);
134 EBIT_CLR(cc
->mask
, type
);
138 if (!p
|| !httpHeaderParseInt(p
, &cc
->s_maxage
)) {
139 debug(65, 2) ("cc: invalid s-maxage specs near '%s'\n", item
);
141 EBIT_CLR(cc
->mask
, type
);
145 if (!p
|| !httpHeaderParseInt(p
, &cc
->max_stale
)) {
146 debug(65, 2) ("cc: max-stale directive is valid without value\n");
151 /* note that we ignore most of '=' specs */
155 return cc
->mask
!= 0;
159 httpHdrCcDestroy(HttpHdrCc
* cc
)
162 memFree(cc
, MEM_HTTP_HDR_CC
);
166 httpHdrCcDup(const HttpHdrCc
* cc
)
170 dup
= httpHdrCcCreate();
171 dup
->mask
= cc
->mask
;
172 dup
->max_age
= cc
->max_age
;
173 dup
->s_maxage
= cc
->s_maxage
;
174 dup
->max_stale
= cc
->max_stale
;
179 httpHdrCcPackInto(const HttpHdrCc
* cc
, Packer
* p
)
181 http_hdr_cc_type flag
;
184 for (flag
= 0; flag
< CC_ENUM_END
; flag
++) {
185 if (EBIT_TEST(cc
->mask
, flag
) && flag
!= CC_OTHER
) {
187 /* print option name */
188 packerPrintf(p
, (pcount
? ", %s" : "%s"), strBuf(CcFieldsInfo
[flag
].name
));
190 /* handle options with values */
191 if (flag
== CC_MAX_AGE
)
192 packerPrintf(p
, "=%d", (int) cc
->max_age
);
194 if (flag
== CC_S_MAXAGE
)
195 packerPrintf(p
, "=%d", (int) cc
->s_maxage
);
197 if (flag
== CC_MAX_STALE
)
198 packerPrintf(p
, "=%d", (int) cc
->max_stale
);
206 httpHdrCcJoinWith(HttpHdrCc
* cc
, const HttpHdrCc
* new_cc
)
208 assert(cc
&& new_cc
);
210 cc
->max_age
= new_cc
->max_age
;
211 if (cc
->s_maxage
< 0)
212 cc
->s_maxage
= new_cc
->s_maxage
;
213 if (cc
->max_stale
< 0)
214 cc
->max_stale
= new_cc
->max_stale
;
215 cc
->mask
|= new_cc
->mask
;
218 /* negative max_age will clean old max_Age setting */
220 httpHdrCcSetMaxAge(HttpHdrCc
* cc
, int max_age
)
223 cc
->max_age
= max_age
;
225 EBIT_SET(cc
->mask
, CC_MAX_AGE
);
227 EBIT_CLR(cc
->mask
, CC_MAX_AGE
);
230 /* negative s_maxage will clean old s-maxage setting */
232 httpHdrCcSetSMaxAge(HttpHdrCc
* cc
, int s_maxage
)
235 cc
->s_maxage
= s_maxage
;
237 EBIT_SET(cc
->mask
, CC_S_MAXAGE
);
239 EBIT_CLR(cc
->mask
, CC_S_MAXAGE
);
243 httpHdrCcUpdateStats(const HttpHdrCc
* cc
, StatHist
* hist
)
247 for (c
= 0; c
< CC_ENUM_END
; c
++)
248 if (EBIT_TEST(cc
->mask
, c
))
249 statHistCount(hist
, c
);
253 httpHdrCcStatDumper(StoreEntry
* sentry
, int idx
, double val
, double size
, int count
)
255 extern const HttpHeaderStat
*dump_stat
; /* argh! */
256 const int id
= (int) val
;
257 const int valid_id
= id
>= 0 && id
< CC_ENUM_END
;
258 const char *name
= valid_id
? strBuf(CcFieldsInfo
[id
].name
) : "INVALID";
259 if (count
|| valid_id
)
260 storeAppendPrintf(sentry
, "%2d\t %-20s\t %5d\t %6.2f\n",
261 id
, name
, count
, xdiv(count
, dump_stat
->ccParsedCount
));