Line data Source code
1 : // Copyright (c) 2011-2022 Made to Order Software Corp. All Rights Reserved
2 : //
3 : // https://snapwebsites.org/project/edhttp
4 : // contact@m2osw.com
5 : //
6 : // This program is free software: you can redistribute it and/or modify
7 : // it under the terms of the GNU General Public License as published by
8 : // the Free Software Foundation, either version 3 of the License, or
9 : // (at your option) any later version.
10 : //
11 : // This program is distributed in the hope that it will be useful,
12 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : // GNU General Public License for more details.
15 : //
16 : // You should have received a copy of the GNU General Public License
17 : // along with this program. If not, see <https://www.gnu.org/licenses/>.
18 :
19 : // self
20 : //
21 : #include "edhttp/cache_control.h"
22 :
23 : #include "edhttp/string_part.h"
24 : #include "edhttp/weighted_http_string.h"
25 :
26 :
27 : // advgetopt
28 : //
29 : #include <advgetopt/utils.h>
30 :
31 :
32 : // snapdev
33 : //
34 : #include <snapdev/trim_string.h>
35 :
36 :
37 : // last include
38 : //
39 : #include <snapdev/poison.h>
40 :
41 :
42 :
43 : namespace edhttp
44 : {
45 :
46 :
47 : /** \brief Initialize a cache control object with defaults.
48 : *
49 : * This function initialize this cache control object with the
50 : * defaults and returns.
51 : *
52 : * You may later apply various changes to the cache control data
53 : * using the set_...() functions and the set_cache_info() if you
54 : * have cache control data in the form of a standard HTTP string.
55 : */
56 0 : cache_control_settings::cache_control_settings()
57 : {
58 0 : }
59 :
60 :
61 : /** \brief Initializes a cache control object with the specified info.
62 : *
63 : * This function initialize this cache control object with the defaults
64 : * and then applies the \p info parameters to the controls if \p info is
65 : * not an empty string.
66 : *
67 : * \param[in] info The new cache control information to assign to this object.
68 : * \param[in] internal_setup Whether to allow our special '!' syntax.
69 : *
70 : * \sa set_cache_info()
71 : */
72 0 : cache_control_settings::cache_control_settings(std::string const & info, bool const internal_setup)
73 : {
74 0 : set_cache_info(info, internal_setup);
75 0 : }
76 :
77 :
78 : /** \brief Reset all the cache information to their defaults.
79 : *
80 : * This function resets all the cache information to their defaults so
81 : * the object looks as if it just got initialized.
82 : */
83 0 : void cache_control_settings::reset_cache_info()
84 : {
85 0 : f_max_age = 0;
86 0 : f_max_stale = IGNORE_VALUE;
87 0 : f_min_fresh = IGNORE_VALUE;
88 0 : f_must_revalidate = true;
89 0 : f_no_cache = false;
90 0 : f_no_store = true;
91 0 : f_no_transform = false;
92 0 : f_only_if_cached = false;
93 0 : f_private = false;
94 0 : f_public = false;
95 0 : f_s_maxage = IGNORE_VALUE;
96 0 : }
97 :
98 :
99 : /** \brief Set the cache information parsed from the \p info parameter.
100 : *
101 : * This function parses the \p info string for new cache definitions.
102 : * The \p info string may be empty in which case nothing is modified.
103 : * It is expected to be the string found in a Cache-Control header
104 : * sent by the client.
105 : *
106 : * If you want to start from scratch, you may call reset_cache_info()
107 : * first. You can also use a brand new object and then copy it since
108 : * the copy operator is available.
109 : *
110 : * The 'must-revalidate' and 'no-store' are set by default. Unfortunately
111 : * that would mean the page setup capability would not be able to ever
112 : * clear those two flags. That would mean you could never use a full
113 : * permanent cache definition. Instead we offer an extension to the
114 : * flags and allow one to add a '!' in front of the names as in:
115 : * '!no-cache'. This way you can force the 'no-cache' flag to false
116 : * instead of the default of true.
117 : *
118 : * \todo
119 : * Determine whether any error in the field should be considered fatal and
120 : * thus react by ignoring the entire \p info parameter. It seems that the
121 : * HTTP specification asks us to do so... (i.e. ignore all when any one
122 : * flag is not understood.) However, it seems that most browsers implement
123 : * such things the other way around: try to retrieve the maximum amount of
124 : * information as possible and use whatever they understand from that.
125 : *
126 : * \todo
127 : * Determine whether we should accept certain parameters only once.
128 : * Especially those that include values (i.e. max-age=123) because
129 : * the current implementation only takes the last one in account when
130 : * we probably should remember the first one (within one \p info string).
131 : *
132 : * \todo
133 : * Add support for private and no-cache parameters (server side only).
134 : *
135 : * \param[in] info The new cache control information to assign to this object.
136 : * \param[in] internal_setup Whether to allow our special '!' syntax.
137 : */
138 0 : void cache_control_settings::set_cache_info(std::string const & info, bool const internal_setup)
139 : {
140 : // TODO: we want the weighted HTTP strings to understand
141 : // parameters with values assigned and more than the
142 : // q=xxx then we can update this code to better test
143 : // what we are dealing with...
144 :
145 : // parse the data with the weighted HTTP string implementation
146 : //
147 0 : weighted_http_string client_cache_control(info);
148 :
149 : // no go through the list of parts and handle them appropriately
150 : //
151 0 : string_part::vector_t const & cache_control_parts(client_cache_control.get_parts());
152 0 : for(auto const & c : cache_control_parts)
153 : {
154 : // get the part name
155 : //
156 0 : std::string name(c.get_name());
157 :
158 0 : bool negate(false);
159 0 : if(internal_setup)
160 : {
161 0 : negate = name[0] == '!';
162 0 : if(negate)
163 : {
164 : // remove the negate flag
165 : //
166 0 : name = name.substr(1);
167 : }
168 : }
169 :
170 0 : if(name.empty())
171 : {
172 0 : continue;
173 : }
174 :
175 : // TODO: add code to check whether 'negate' (!) was used with
176 : // an item that does not support it
177 :
178 : // do a switch first to save a tad bit of time
179 0 : switch(name[0])
180 : {
181 0 : case 'i':
182 0 : if(name == "immutable")
183 : {
184 0 : set_immutable(!negate);
185 : }
186 0 : break;
187 :
188 0 : case 'm':
189 0 : if(name == "max-age")
190 : {
191 0 : set_max_age(c.get_value());
192 : }
193 0 : else if(name == "max-stale")
194 : {
195 0 : std::string const & value(c.get_value());
196 0 : if(value.empty())
197 : {
198 : // any stale data can be returned
199 : //
200 0 : set_max_stale(0);
201 : }
202 : else
203 : {
204 0 : set_max_stale(value);
205 : }
206 : }
207 0 : else if(name == "min-fresh")
208 : {
209 0 : set_min_fresh(c.get_value());
210 : }
211 0 : else if(name == "must-revalidate")
212 : {
213 0 : set_must_revalidate(!negate);
214 : }
215 0 : break;
216 :
217 0 : case 'n':
218 0 : if(name == "no-cache")
219 : {
220 0 : std::string const & value(c.get_value());
221 0 : if(value.empty())
222 : {
223 0 : set_no_cache(!negate);
224 : }
225 : else
226 : {
227 : // list of fields that require revalidation
228 : //
229 0 : advgetopt::string_list_t list;
230 0 : advgetopt::split_string(value, list, {","});
231 0 : for(auto const & l : list)
232 : {
233 0 : add_revalidate_field_name(l);
234 : }
235 : }
236 : }
237 0 : else if(name == "no-store")
238 : {
239 0 : set_no_store(!negate);
240 : }
241 0 : else if(name == "no-transform")
242 : {
243 0 : set_no_transform(!negate);
244 : }
245 0 : break;
246 :
247 0 : case 'o':
248 0 : if(name == "only-if-cached")
249 : {
250 0 : set_only_if_cached(!negate);
251 : }
252 0 : break;
253 :
254 0 : case 'p':
255 0 : if(name == "private")
256 : {
257 0 : std::string const & value(c.get_value());
258 0 : if(value.empty())
259 : {
260 0 : set_private(!negate);
261 : }
262 : else
263 : {
264 : // list of fields that require revalidation
265 : //
266 0 : advgetopt::string_list_t list;
267 0 : advgetopt::split_string(value, list, {","});
268 0 : for(auto const & l : list)
269 : {
270 0 : add_private_field_name(l);
271 : }
272 : }
273 : }
274 0 : else if(name == "proxy-revalidate")
275 : {
276 0 : set_proxy_revalidate(!negate);
277 : }
278 0 : else if(name == "public")
279 : {
280 0 : set_public(!negate);
281 : }
282 0 : break;
283 :
284 0 : case 's':
285 0 : if(name == "s-maxage")
286 : {
287 0 : set_s_maxage(c.get_value());
288 : }
289 0 : break;
290 :
291 : }
292 : }
293 0 : }
294 :
295 :
296 : /** \brief Set the must-revalidate to true or false.
297 : *
298 : * This function should only be called with 'true' to request
299 : * that the client revalidate the data each time it wants to
300 : * access it.
301 : *
302 : * However, the flag is set to 'true' by default, so really it
303 : * is only useful if you want to set the parameter to 'false'.
304 : *
305 : * \note
306 : * This flag may appear in the server response.
307 : *
308 : * \param[in] must_revalidate Whether the client should revalidate that
309 : * specific content on each page load.
310 : *
311 : * \sa get_must_revalidate()
312 : */
313 0 : void cache_control_settings::set_must_revalidate(bool const must_revalidate)
314 : {
315 0 : f_must_revalidate = must_revalidate;
316 0 : }
317 :
318 :
319 : /** \brief Get the current value of the must-revalidate flag.
320 : *
321 : * This function returns the current value of the must-revalidate
322 : * flag.
323 : *
324 : * \note
325 : * This flag may appear in the server response.
326 : *
327 : * \return true if the must-revalidate flag is to be specified in the
328 : * Cache-Control field.
329 : *
330 : * \sa set_must_revalidate()
331 : */
332 0 : bool cache_control_settings::get_must_revalidate() const
333 : {
334 0 : return f_must_revalidate;
335 : }
336 :
337 :
338 : /** \brief Set the 'private' flag to true or false.
339 : *
340 : * Any page that is private, and thus should not be saved in a
341 : * shared cache (i.e. proxies), must be assigned the private
342 : * flag, so this function must be called with true.
343 : *
344 : * Note that does not encrypt the data in any way. It just adds
345 : * the private flag to the Cache-Control header. If you need to
346 : * encrypt the data, make sure to enforce HTTPS before returning
347 : * a reply with secret data.
348 : *
349 : * \note
350 : * This flag may appear in the server response.
351 : *
352 : * \param[in] private_cache Whether intermediate, shared, proxy caches
353 : * are allowed to cache this data.
354 : *
355 : * \sa get_private()
356 : */
357 0 : void cache_control_settings::set_private(bool const private_cache)
358 : {
359 0 : f_private = private_cache;
360 0 : }
361 :
362 :
363 : /** \brief Get the current value of the 'private' flag.
364 : *
365 : * This function returns the current value of the 'private'
366 : * flag.
367 : *
368 : * Note that 'private' has priority over 'public'. So if 'private'
369 : * is true, 'public' is ignored. For this reason you should only
370 : * set those flags to true and never attempt to reset them to
371 : * false. Similarly, the 'no-cache' and 'no-store' have priority
372 : * over the 'private' flag.
373 : *
374 : * \note
375 : * This flag may appear in the server response.
376 : *
377 : * \return true if the 'private' flag is to be specified in the
378 : * Cache-Control field.
379 : *
380 : * \sa set_private()
381 : */
382 0 : bool cache_control_settings::get_private() const
383 : {
384 0 : return f_private;
385 : }
386 :
387 :
388 : /** \brief Set 'proxy-revalidate' to true or false.
389 : *
390 : * This function should only be called with 'true' to request
391 : * that proxy caches revalidate the data each time a client
392 : * asks for the data.
393 : *
394 : * You may instead want to use the 's-maxage' field.
395 : *
396 : * \note
397 : * This flag may appear in the server response.
398 : *
399 : * \param[in] proxy_revalidate Whether proxy caches should revalidate that
400 : * specific content.
401 : *
402 : * \sa get_proxy_revalidate()
403 : */
404 0 : void cache_control_settings::set_proxy_revalidate(bool const proxy_revalidate)
405 : {
406 0 : f_proxy_revalidate = proxy_revalidate;
407 0 : }
408 :
409 :
410 : /** \brief Set whether the resource is immutable or not.
411 : *
412 : * This function sets whether the resource is immutable. Browsers that
413 : * understand this flag will never check the server again for that
414 : * specific resource as long as they keep it in their caches.
415 : *
416 : * Immutable means that it will never change. This is true for all
417 : * our CSS and JS files because these are versioned and any changes
418 : * to those files require a change in their version.
419 : *
420 : * \param[in] immutable Whether the file is immutable or not.
421 : */
422 0 : void cache_control_settings::set_immutable(bool const immutable)
423 : {
424 0 : f_immutable = immutable;
425 0 : }
426 :
427 :
428 : /** \brief Get whether the data was marked immutable.
429 : *
430 : * This function returns true if the data attached to that resource
431 : * is considered immutable.
432 : *
433 : * For example, JS and CSS files are always considered immutable. This
434 : * is because we have a version and if you want to modify those files,
435 : * you must increase the version accordingly.
436 : *
437 : * Browsers that support the immutable flag never check the server
438 : * again because the file will be saved permanently in their caches.
439 : *
440 : * \return true if the resource is considered immutable.
441 : */
442 0 : bool cache_control_settings::get_immutable() const
443 : {
444 0 : return f_immutable;
445 : }
446 :
447 :
448 : /** \brief Get the current value of the 'proxy-revalidate' flag.
449 : *
450 : * This function returns the current value of the 'proxy-revalidate'
451 : * flag.
452 : *
453 : * Note that 'must-revalidate' has priority and if specified, the
454 : * 'proxy-revalidate' is ignored since the proxy-cache should
455 : * honor the 'must-revalidate' anyway. However, this function
456 : * directly returns the value of the 'proxy-revalidate' flag.
457 : *
458 : * \note
459 : * This flag may appear in the server response.
460 : *
461 : * \return true if the 'proxy-revalidate' flag is to be specified in the
462 : * Cache-Control field.
463 : *
464 : * \sa set_proxy_revalidate()
465 : */
466 0 : bool cache_control_settings::get_proxy_revalidate() const
467 : {
468 0 : return f_proxy_revalidate;
469 : }
470 :
471 :
472 : /** \brief Set the 'public' flag to true or false.
473 : *
474 : * Any page that is public, and thus can be saved in a public shared
475 : * cache (i.e. proxy caches).
476 : *
477 : * Snap! detects whether a page is accessible by a visitor, if so
478 : * it sets the public flag automatically. So you should not have
479 : * to set this flag unless somehow your page is public and the Snap!
480 : * test could fail or you know that your pages are always public
481 : * and thus you could avoid having to check the permissions.
482 : *
483 : * Note that if the 'private' flag is set to true, then the 'public'
484 : * flag is ignored. Further, if the 'no-cache' or 'no-store' flags
485 : * are set, then 'public' and 'private' are ignored.
486 : *
487 : * \note
488 : * This flag may appear in the server response.
489 : *
490 : * \param[in] public_cache Whether proxy caches can cache this content.
491 : *
492 : * \sa get_public()
493 : */
494 0 : void cache_control_settings::set_public(bool const public_cache)
495 : {
496 0 : f_public = public_cache;
497 0 : }
498 :
499 :
500 : /** \brief Get the current value of the 'public' flag.
501 : *
502 : * This function returns the current value of the 'public'
503 : * flag.
504 : *
505 : * Note that 'private' has priority over 'public'. So if 'private'
506 : * is true, 'public' is ignored. Similarly, the 'no-cache' and
507 : * 'no-store' have priority over the 'private' flag. However, this
508 : * function directly returns the 'public' flag.
509 : *
510 : * \note
511 : * This flag may appear in the server response.
512 : *
513 : * \return true if the 'public' flag is to be specified in the
514 : * Cache-Control field.
515 : *
516 : * \sa set_public()
517 : */
518 0 : bool cache_control_settings::get_public() const
519 : {
520 0 : return f_public;
521 : }
522 :
523 :
524 : /** \brief Add a field name that needs to get revalidated by proxy caches.
525 : *
526 : * The Cache-Control header can include a no-cache parameter that includes
527 : * a list of field names that should not be cached and be revalidated
528 : * whenever a new client request is received.
529 : *
530 : * Note that means there are three possibilities with the no-cache parameters:
531 : *
532 : * \li the parameter is not present, caching may still not be allowed
533 : * (i.e. max-age=0)
534 : * \li the parameter is present on its own, absolutely no caching is possible
535 : * \li the parameter is set to a list of field names, in which case caching
536 : * is allowed, but the specified fields must be revalidated from the
537 : * server (and should probably not be saved in the cache)
538 : *
539 : * \note
540 : * If the string is empty after left and right trimming the request to
541 : * add a field name is ignored.
542 : *
543 : * References:
544 : *
545 : * https://tools.ietf.org/html/rfc7234#section-5.2.2
546 : *
547 : * \param[in] field_name The name of the HTTP header field which needs to
548 : * never be cached.
549 : *
550 : * \sa add_private_field_name()
551 : */
552 0 : void cache_control_settings::add_revalidate_field_name(std::string const & field_name)
553 : {
554 : // we just have to insert, it will be inserted just once
555 : //
556 0 : std::string const name(snapdev::trim_string(field_name));
557 0 : if(!name.empty())
558 : {
559 0 : f_revalidate_field_names.insert(name);
560 : }
561 0 : }
562 :
563 :
564 : /** \brief Retrieve the existing list of field names to never cache.
565 : *
566 : * The Cache-Control field can include a no-cache="<list of field names>".
567 : * This is that list.
568 : *
569 : * By default this list is empty (Contrary to the private list which
570 : * includes the "Set-Cookie".)
571 : *
572 : * For certain pages that require the "Set-Cookie" or some other user
573 : * fields, such should be added to this list. That way the cache will
574 : * make sure to revalidate the page conditionally.
575 : *
576 : * Other fields that are specific to a user need to be added to this
577 : * list with one of the add_revalidate_field_name() functions.
578 : *
579 : * \return A list of field names.
580 : */
581 0 : cache_control_settings::tags_t const & cache_control_settings::get_revalidate_field_names() const
582 : {
583 0 : return f_revalidate_field_names;
584 : }
585 :
586 :
587 : /** \brief Add a field name that needs to remain private.
588 : *
589 : * The Cache-Control header can include a private parameter that includes
590 : * a list of field names that need to not be cached, except by private
591 : * caches (i.e. client browser).
592 : *
593 : * Note that means there are three possibilities with the private parameters:
594 : *
595 : * \li the parameter is not present, the data is considered private anyway
596 : * \li the parameter is present on its own, all data is considered private
597 : * \li the parameter is set to a list of field names, in which case caching
598 : * is allowed, but the specified fields must be removed from the HTTP
599 : * header before caching the header
600 : *
601 : * Note that this is different from the no-cache parameter which requires
602 : * a hit to the server to revalidate the header. In case of the private
603 : * parameter, no revalidation is required. We can simply send the cache
604 : * without the private fields (which with Snap! C++ is fine for pretty
605 : * much all our attachments.)
606 : *
607 : * \note
608 : * If the string is empty after left and right trimming the request to
609 : * add a field name is ignored.
610 : *
611 : * References:
612 : *
613 : * https://tools.ietf.org/html/rfc7234#section-5.2.2
614 : *
615 : * \param[in] field_name The name of the HTTP header field which needs to
616 : * never be cached.
617 : *
618 : * \sa add_revalidate_field_name()
619 : */
620 0 : void cache_control_settings::add_private_field_name(std::string const & field_name)
621 : {
622 : // we just have to insert, it will be inserted just once
623 : //
624 0 : std::string const name(snapdev::trim_string(field_name));
625 0 : if(!name.empty())
626 : {
627 0 : f_private_field_names.insert(name);
628 : }
629 0 : }
630 :
631 :
632 : /** \brief Retrieve the existing list of field names to never cache.
633 : *
634 : * The Cache-Control field can include a private="<list of field names>".
635 : * This is that list.
636 : *
637 : * By default, this list is set to "Set-Cookie" which is more than likely
638 : * a field that include many user specific data such as a session
639 : * identifier.
640 : *
641 : * Other fields that are specific to a user need to be added to this
642 : * list with one of the add_private_field_name() functions.
643 : *
644 : * \return A list of field names.
645 : */
646 0 : cache_control_settings::tags_t const & cache_control_settings::get_private_field_names() const
647 : {
648 0 : return f_private_field_names;
649 : }
650 :
651 :
652 : /** \brief Add a tag to the existing list of tags.
653 : *
654 : * This function adds the specified tag_name parameter to the list of
655 : * tags to send to the client. This is used by CDN systems to allow
656 : * for segregation of files to be cached.
657 : *
658 : * Note that a page which cache is turned off (i.e. Cache-Control has
659 : * the no-cache parameter set) does not get tagged. These tags will be
660 : * ignored in that situation.
661 : *
662 : * By default we use the "Cache-Tag" HTTP header as defined by CloudFlare.
663 : * The name can be changed in the snapserver.conf file. You may also
664 : * add multiple names. Drupal uses "X-Drupal-Cache-Tags". Akamai uses
665 : * "Edge-Cache-Tag".
666 : *
667 : * References:
668 : *
669 : * https://support.cloudflare.com/hc/en-us/articles/206596608-How-to-Purge-Cache-Using-Cache-Tags-Enterprise-only-
670 : *
671 : * https://www.drupal.org/docs/8/api/cache-api/cache-tags
672 : *
673 : * https://learn.akamai.com/en-us/webhelp/fast-purge/fast-purge/GUID-9AEF6978-697F-410C-A347-8155FDB535C8.html
674 : *
675 : * \param[in] tag_name The name of the tag to add to the list.
676 : */
677 0 : void cache_control_settings::add_tag(std::string const & tag_name)
678 : {
679 : // we just have to insert, it will be inserted just once
680 : //
681 0 : f_tags.insert(tag_name);
682 0 : }
683 :
684 :
685 : /** \brief Retrieve the existing list of cache tags.
686 : *
687 : * Various CDN systems accept a cache tag. This function returns the
688 : * list of tags that will be used with that HTTP header.
689 : *
690 : * By default, this is expected to be empty and no tag will be added
691 : * anywhere.
692 : *
693 : * \return A list of tag names.
694 : */
695 0 : cache_control_settings::tags_t const & cache_control_settings::get_tags() const
696 : {
697 0 : return f_tags;
698 : }
699 :
700 :
701 : /** \brief Set the maximum number of seconds to cache this data.
702 : *
703 : * This function requests for the specified data to be cached
704 : * for that many seconds.
705 : *
706 : * By default the value of max-age is set to 0, meaning that the
707 : * data will not be cached.
708 : *
709 : * In order to create a cache on the client's side (and within proxies,)
710 : * the value can be set to a number of seconds between 1 and AGE_MAXIMUM.
711 : * Any value under 60 is probably not going to be very useful. Any
712 : * value larger than AGE_MAXIMUM (which is one year, as per HTTP/1.1)
713 : * is clamped to AGE_MAXIMUM.
714 : *
715 : * You may also set \p max_age to -1 in order for the system to ignore
716 : * the 'max-age' cache control parameter.
717 : *
718 : * \note
719 : * This flag may appear in the client request or the server response.
720 : *
721 : * \param[in] max_age The maximum age the data can have before checking
722 : * the data again.
723 : *
724 : * \sa update_max_age()
725 : * \sa get_max_age()
726 : */
727 0 : void cache_control_settings::set_max_age(int64_t const max_age)
728 : {
729 0 : if(max_age >= AGE_MAXIMUM)
730 : {
731 : // 1 year in seconds
732 0 : f_max_age = AGE_MAXIMUM;
733 : }
734 0 : else if(max_age < 0)
735 : {
736 0 : f_max_age = IGNORE_VALUE;
737 : }
738 : else
739 : {
740 0 : f_max_age = max_age;
741 : }
742 0 : }
743 :
744 :
745 : /** \brief Set the 'max-age' field value from a string.
746 : *
747 : * This function accepts a string as input to setup the 'max-age'
748 : * field.
749 : *
750 : * The value may be set to IGNORE_VALUE if the string does not represent
751 : * a valid decimal number (no signs allowed.) It is also clamped to a
752 : * maximum of AGE_MAXIMUM.
753 : *
754 : * \param[in] max_age The maximum age as a string.
755 : *
756 : * \sa update_max_age()
757 : * \sa get_max_age()
758 : */
759 0 : void cache_control_settings::set_max_age(std::string const & max_age)
760 : {
761 : // in this case -1 is what we want in case of an error
762 : // and not 1 year in seconds... no other negative values
763 : // are possible so we are fine
764 : //
765 0 : f_max_age = string_to_seconds(max_age);
766 0 : }
767 :
768 :
769 : /** \brief Update the maximum number of seconds to cache this data.
770 : *
771 : * This function keeps the smaller 'max-age' of the existing setup and
772 : * the new value specified to this function.
773 : *
774 : * Note that if the current value is IGNORE_VALUE, then the new maximum
775 : * is automatically used, whatever it is.
776 : *
777 : * Negative values are ignored.
778 : *
779 : * \param[in] max_age The maximum age the data can have before the client
780 : * is expected to check the data again.
781 : *
782 : * \sa set_max_age()
783 : * \sa get_max_age()
784 : */
785 0 : void cache_control_settings::update_max_age(int64_t max_age)
786 : {
787 0 : if(max_age > AGE_MAXIMUM)
788 : {
789 : // 1 year in seconds
790 : //
791 0 : max_age = AGE_MAXIMUM;
792 : }
793 0 : f_max_age = minimum(f_max_age, max_age);
794 0 : }
795 :
796 :
797 : /** \brief Retrieve the current max-age field.
798 : *
799 : * The Cache-Control can specify how long the data being returned
800 : * can be cached for. The 'max-age' field defines that duration
801 : * in seconds.
802 : *
803 : * By default the data is marked as 'do not cache' (i.e. max-age
804 : * is set to zero.)
805 : *
806 : * This function may return IGNORE_VALUE in which case the
807 : * 'max-age' field is ignored.
808 : *
809 : * \note
810 : * This flag may appear in the client request or the server response.
811 : *
812 : * \return The number of seconds to cache the data or IGNORE_VALUE.
813 : *
814 : * \sa update_max_age()
815 : * \sa get_max_age()
816 : */
817 0 : int64_t cache_control_settings::get_max_age() const
818 : {
819 0 : return f_max_age;
820 : }
821 :
822 :
823 : /** \brief Set the 'no-cache' flag to true or false.
824 : *
825 : * This function should only be called with 'true' to request
826 : * that the client and intermediate caches do not cache any
827 : * of the data. This does not prevent the client to store
828 : * the data.
829 : *
830 : * When the client sets this field to true, it means that we
831 : * should regenerate the specified page data.
832 : *
833 : * \note
834 : * This flag may appear in the client request or the server response.
835 : *
836 : * \param[in] no_cache Whether the client and intermediate caches
837 : * must not cache the data.
838 : *
839 : * \sa get_no_cache()
840 : */
841 0 : void cache_control_settings::set_no_cache(bool const no_cache)
842 : {
843 0 : f_no_cache = no_cache;
844 0 : }
845 :
846 :
847 : /** \brief Retrieve the 'no-cache' flag.
848 : *
849 : * This function returns the current value of the 'no-cache' flag.
850 : *
851 : * The system ignores the 'public' and 'private' flags when the
852 : * 'no-cache' flag is true.
853 : *
854 : * \note
855 : * This flag may appear in the client request or the server response.
856 : *
857 : * \return true if the 'no-cache' flag is to be specified in the
858 : * Cache-Control field.
859 : *
860 : * \sa set_no_cache()
861 : */
862 0 : bool cache_control_settings::get_no_cache() const
863 : {
864 0 : return f_no_cache;
865 : }
866 :
867 :
868 : /** \brief Set the 'no-store' flag to true or false.
869 : *
870 : * This function sets the 'no-store' flag to true or false. This
871 : * flag means that any of the data in that request needs to be
872 : * transferred only and not stored anywhere except in 100%
873 : * temporary buffers on the client's machine.
874 : *
875 : * Further, shared/proxy caches should clear all the data bufferized
876 : * to process this request as soon as it is done with it.
877 : *
878 : * \note
879 : * This flag may appear in the client request or the server response.
880 : *
881 : * \param[in] no_store Whether the data can be stored or not.
882 : *
883 : * \sa get_no_store()
884 : */
885 0 : void cache_control_settings::set_no_store(bool const no_store)
886 : {
887 0 : f_no_store = no_store;
888 0 : }
889 :
890 :
891 : /** \brief Retrieve the 'no-store' flag.
892 : *
893 : * This function returns the current 'no-store' flag status.
894 : *
895 : * In most cases, this flag is not required. It should be true
896 : * only on pages that include extremely secure content such
897 : * as a page recording the settings of an electronic payment
898 : * (i.e. the e-payment Paypal page allows you to enter your
899 : * Paypal identifiers and those should not be stored anywhere.)
900 : *
901 : * Since most of our HTML pages are already marked as 'no-cache',
902 : * the 'no-store' is generally not required.
903 : *
904 : * \note
905 : * This flag may appear in the client request or the server response.
906 : *
907 : * \return true if the data in this request should not be stored
908 : * anywhere.
909 : *
910 : * \sa set_no_store()
911 : */
912 0 : bool cache_control_settings::get_no_store() const
913 : {
914 0 : return f_no_store;
915 : }
916 :
917 :
918 : /** \brief Set whether the data can be transformed.
919 : *
920 : * The 'no-transform' flag can be used to make sure that caches do
921 : * not transform the data. This can also appear in the request from
922 : * the client in which case an exact original is required.
923 : *
924 : * This is generally important only for document files that may be
925 : * converted to a lousy format such as images that could be saved
926 : * as JPEG images although we enforce it when the client sends us
927 : * an AJAX request.
928 : *
929 : * \note
930 : * This flag may appear in the client request or the server response.
931 : *
932 : * \param[in] no_transform Set to true to retrieve the original document as is.
933 : *
934 : * \sa get_no_transform()
935 : */
936 0 : void cache_control_settings::set_no_transform(bool const no_transform)
937 : {
938 0 : f_no_transform = no_transform;
939 0 : }
940 :
941 :
942 : /** \brief Retrieve whether the data can be transformed.
943 : *
944 : * Check whether the client or the server are requesting that the data
945 : * not be transformed. If true, then the original data should be
946 : * transferred as is.
947 : *
948 : * \note
949 : * This flag may appear in the client request or the server response.
950 : *
951 : * \return true if the 'no-transform' flag is set.
952 : *
953 : * \sa set_no_transform()
954 : */
955 0 : bool cache_control_settings::get_no_transform() const
956 : {
957 0 : return f_no_transform;
958 : }
959 :
960 :
961 : /** \brief Set the number of seconds to cache this data in shared caches.
962 : *
963 : * This function requests for the specified data to be cached
964 : * for that many seconds in any shared caches between the client
965 : * and the server. The client ignores that information.
966 : *
967 : * To use the maximum, call this function with AGE_MAXIMUM.
968 : *
969 : * To ignore this value, call this function with IGNORE_VALUE. This is
970 : * the default value for this field.
971 : *
972 : * \note
973 : * This flag may appear in the client request or the server response.
974 : *
975 : * \param[in] s_maxage The maximum age the data can have before checking
976 : * the source again.
977 : *
978 : * \sa update_s_maxage()
979 : * \sa get_s_maxage()
980 : */
981 0 : void cache_control_settings::set_s_maxage(int64_t const s_maxage)
982 : {
983 0 : if(s_maxage >= AGE_MAXIMUM)
984 : {
985 0 : f_s_maxage = AGE_MAXIMUM;
986 : }
987 0 : else if(s_maxage < 0)
988 : {
989 0 : f_s_maxage = IGNORE_VALUE;
990 : }
991 : else
992 : {
993 0 : f_s_maxage = s_maxage;
994 : }
995 0 : }
996 :
997 :
998 : /** \brief Set the 's-maxage' field value from a string.
999 : *
1000 : * This function accepts a string as input to setup the 's-maxage'
1001 : * field.
1002 : *
1003 : * The value may be set to -1 if the string does not represent a valid
1004 : * decimal number (no signs allowed.) It will be clamped to a maximum
1005 : * of AGE_MAXIMUM.
1006 : *
1007 : * \param[in] s_maxage The new maximum age defined as a string.
1008 : *
1009 : * \sa update_s_maxage()
1010 : * \sa get_s_maxage()
1011 : */
1012 0 : void cache_control_settings::set_s_maxage(std::string const & s_maxage)
1013 : {
1014 : // in this case -1 is what we want in case of an error
1015 : // and not 1 year in seconds... no other negative values
1016 : // are possible so we are fine
1017 : //
1018 0 : f_s_maxage = string_to_seconds(s_maxage);
1019 0 : }
1020 :
1021 :
1022 : /** \brief Update the maximum number of seconds to cache this data on proxies.
1023 : *
1024 : * This function keeps the smaller maximum of the existing setup and
1025 : * the new value specified to this function.
1026 : *
1027 : * Note that if the current value is IGNORE_VALUE, then the new maximum
1028 : * is always used.
1029 : *
1030 : * Negative values are ignored.
1031 : *
1032 : * \param[in] s_maxage The maximum age the data can have before checking
1033 : * the data again from shared proxy cache.
1034 : *
1035 : * \sa set_s_maxage()
1036 : * \sa get_s_maxage()
1037 : */
1038 0 : void cache_control_settings::update_s_maxage(int64_t s_maxage)
1039 : {
1040 0 : if(s_maxage >= AGE_MAXIMUM)
1041 : {
1042 : // 1 year in seconds
1043 : //
1044 0 : s_maxage = AGE_MAXIMUM;
1045 : }
1046 0 : f_s_maxage = minimum(f_s_maxage, s_maxage);
1047 0 : }
1048 :
1049 :
1050 : /** \brief Retrieve the current 's-maxage' field.
1051 : *
1052 : * The 'Cache-Control' HTTP header can specify how long the data
1053 : * being returned can be cached for in a shared cache. The
1054 : * 's-maxage' field defines that duration in seconds.
1055 : *
1056 : * By default shared caches are expected to use the 'max-age' parameter
1057 : * when the 's-maxage' parameter is not defined. So if the value is
1058 : * the same, you do not have to specified 's-maxage'.
1059 : *
1060 : * The value of 0 means that shared caches will not cache anything.
1061 : *
1062 : * \note
1063 : * This field may appear in the client request or the server response.
1064 : *
1065 : * \return The number of seconds to cache the data or IGNORE_VALUE.
1066 : *
1067 : * \sa set_s_maxage()
1068 : * \sa update_s_maxage()
1069 : */
1070 0 : int64_t cache_control_settings::get_s_maxage() const
1071 : {
1072 0 : return f_s_maxage;
1073 : }
1074 :
1075 :
1076 : /** \brief How long of a 'stale' is accepted by the client.
1077 : *
1078 : * The client may asks for data that is stale. Assuming that
1079 : * a cache may keep data after it became stale, the client may
1080 : * retrieve that data if they specified the stale parameter.
1081 : *
1082 : * A value of zero means that any stale data is acceptable.
1083 : * A greater value specifies the number of seconds after the
1084 : * normal cache threshold the data can be to be considered
1085 : * okay to be returned to the client.
1086 : *
1087 : * In general, this is for cache systems and not the server
1088 : * so our server generally ignores that data.
1089 : *
1090 : * You may use the AGE_MAXIMUM parameter to set the 'stale'
1091 : * parameter to the maximum possible.
1092 : *
1093 : * You may set the 'stale' parameter to IGNORE_VALUE in which
1094 : * case any possible user of the parameter has to ignore the
1095 : * value (do as if it was not specified).
1096 : *
1097 : * \note
1098 : * This flag may appear in the client request.
1099 : *
1100 : * \param[in] max_stale The maximum number of seconds for the stale
1101 : * data to be before the request is forwarded
1102 : * to the server.
1103 : *
1104 : * \sa get_max_stale()
1105 : */
1106 0 : void cache_control_settings::set_max_stale(int64_t const max_stale)
1107 : {
1108 0 : if(max_stale >= AGE_MAXIMUM)
1109 : {
1110 0 : f_max_stale = AGE_MAXIMUM;
1111 : }
1112 0 : else if(max_stale < 0)
1113 : {
1114 0 : f_max_stale = IGNORE_VALUE;
1115 : }
1116 : else
1117 : {
1118 0 : f_max_stale = max_stale;
1119 : }
1120 0 : }
1121 :
1122 :
1123 : /** \brief Set the 'max-stale' field value from a string.
1124 : *
1125 : * This function accepts a string as input to setup the 'max-stale'
1126 : * field.
1127 : *
1128 : * The value may be set to IGNORE_VALUE if the string does not
1129 : * represent a valid decimal number (no signs allowed.)
1130 : *
1131 : * The value is clamped to a maximum of AGE_MAXIMUM.
1132 : *
1133 : * \param[in] max_stale The 'max-stale' parameter as a string.
1134 : *
1135 : * \sa get_max_stale()
1136 : */
1137 0 : void cache_control_settings::set_max_stale(std::string const & max_stale)
1138 : {
1139 0 : set_max_stale(string_to_seconds(max_stale));
1140 0 : }
1141 :
1142 :
1143 : /** \brief Retrieve the current maximum 'stale' value.
1144 : *
1145 : * This function returns the maximum number of seconds the client is
1146 : * willing to accept after the cache expiration date.
1147 : *
1148 : * So if your cache expires at 14:30:00 and the user makes a new
1149 : * request on 14:32:50 with a 'max-stale' value of 3600, then you
1150 : * may return the stale cache instead of regenerating it.
1151 : *
1152 : * Note that only shared caches are expected to return stale data.
1153 : * The server itself currently always regenerate the data as
1154 : * required.
1155 : *
1156 : * The stale value may be set to zero in which case the cache data
1157 : * is always returned if available.
1158 : *
1159 : * \note
1160 : * This flag may appear in the client request.
1161 : *
1162 : * \return The number of seconds the cache may be stale by before
1163 : * regenerating it.
1164 : *
1165 : * \sa set_max_stale()
1166 : */
1167 0 : int64_t cache_control_settings::get_max_stale() const
1168 : {
1169 0 : return f_max_stale;
1170 : }
1171 :
1172 :
1173 : /** \brief Set the number of seconds of freshness required by the client.
1174 : *
1175 : * The freshness is the amount of seconds before the cache goes stale.
1176 : * So if the cache goes stale in 60 seconds and the freshness query
1177 : * is 3600, then the cache is ignored.
1178 : *
1179 : * Note that freshness cannot always be satisfied since a page cache
1180 : * duration ('max-age') may always be smaller than the specified
1181 : * freshness amount.
1182 : *
1183 : * You may set this parameter to its maximum using the AGE_MAXIMUM
1184 : * value.
1185 : *
1186 : * You may set this parameter to IGNORE_VALUE to mark it as being
1187 : * ignored (not set by client.)
1188 : *
1189 : * \note
1190 : * This flag may appear in the client request.
1191 : *
1192 : * \param[in] min_fresh The minimum freshness in seconds.
1193 : *
1194 : * \sa get_min_fresh()
1195 : */
1196 0 : void cache_control_settings::set_min_fresh(int64_t const min_fresh)
1197 : {
1198 0 : if(min_fresh >= AGE_MAXIMUM)
1199 : {
1200 0 : f_min_fresh = AGE_MAXIMUM;
1201 : }
1202 0 : else if(min_fresh < 0)
1203 : {
1204 0 : f_min_fresh = IGNORE_VALUE;
1205 : }
1206 : else
1207 : {
1208 0 : f_min_fresh = min_fresh;
1209 : }
1210 0 : }
1211 :
1212 :
1213 : /** \brief Set the 'min-fresh' field value from a string.
1214 : *
1215 : * This function accepts a string as input to setup the 'min-fresh'
1216 : * field.
1217 : *
1218 : * The value may be set to INGORE_VALUE if the string does not represent
1219 : * a valid decimal number (no signs allowed.) It will be clamped to
1220 : * a maximum of AGE_MAXIMUM.
1221 : *
1222 : * \param[in] min_fresh The minimum freshness required by the client.
1223 : *
1224 : * \sa get_min_fresh()
1225 : */
1226 0 : void cache_control_settings::set_min_fresh(std::string const & min_fresh)
1227 : {
1228 0 : set_min_fresh(string_to_seconds(min_fresh));
1229 0 : }
1230 :
1231 :
1232 : /** \brief Retrieve the 'min-fresh' value from the Cache-Control.
1233 : *
1234 : * If the cache is to get stale within less than 'min-fresh' then
1235 : * the server is expected to recalculate the page.
1236 : *
1237 : * Pages that are given a 'max-age' of less than what 'min-fresh'
1238 : * is set at will react as fully dynamic pages (i.e. as if no
1239 : * caches were available.)
1240 : *
1241 : * \note
1242 : * This flag may appear in the client request.
1243 : *
1244 : * \return The number of seconds of freshness that are required.
1245 : *
1246 : * \sa set_min_fresh()
1247 : */
1248 0 : int64_t cache_control_settings::get_min_fresh() const
1249 : {
1250 0 : return f_min_fresh;
1251 : }
1252 :
1253 :
1254 : /** \brief Set the 'only-if-cached' flag.
1255 : *
1256 : * The 'only-if-cached' flag is used by clients with poor network
1257 : * connectivity to request any available data from any cache instead
1258 : * of gettings newer data.
1259 : *
1260 : * The server ignores that flag since the user connected to the server
1261 : * it would not make sense to not return a valid response from that
1262 : * point.
1263 : *
1264 : * \note
1265 : * This flag may appear in the client request.
1266 : *
1267 : * \param[in] only_if_cached The new flag value.
1268 : *
1269 : * \sa get_only_if_cached()
1270 : */
1271 0 : void cache_control_settings::set_only_if_cached(bool const only_if_cached)
1272 : {
1273 0 : f_only_if_cached = only_if_cached;
1274 0 : }
1275 :
1276 :
1277 : /** \brief Retrieve the 'only-if-cached' flag.
1278 : *
1279 : * This function returns the current status of the 'only-if-cached' flag.
1280 : *
1281 : * The server ignores this flag since it is generally used so a client
1282 : * can request one of the in between caches to return any data they have
1283 : * available, instead of trying to reconnect to the server. However,
1284 : * the server may still check the flag and if true change the behavior.
1285 : * Yet, that would mean the cache behavior would change for all clients.
1286 : *
1287 : * Note that caches still do not return stale data unless the client
1288 : * also specifies the max-stale parameter.
1289 : *
1290 : * \code
1291 : * Cache-Control: max-stale=0,only-if-cached
1292 : * \endcode
1293 : *
1294 : * \return Return true if the only-if-cached flag was specified in the
1295 : * request.
1296 : *
1297 : * \sa set_only_if_cached()
1298 : */
1299 0 : bool cache_control_settings::get_only_if_cached() const
1300 : {
1301 0 : return f_only_if_cached;
1302 : }
1303 :
1304 :
1305 : /** \brief Convert a string to a number.
1306 : *
1307 : * This function returns a number as defined in a string. The input
1308 : * string must exclusively be composed of decimal digits.
1309 : *
1310 : * No plus or minus signs are allowed. If any character is not valid,
1311 : * then the function returns IGNORE_VALUE.
1312 : *
1313 : * If the value is larger than AGE_MAXIMUM, it will be clamped at
1314 : * AGE_MAXIMUM.
1315 : *
1316 : * \note
1317 : * The function only accepts decimal numbers.
1318 : *
1319 : * \param[in] max_age The maximum age decimal number defined as a string.
1320 : *
1321 : * \return The number of seconds the string represents
1322 : * or IGNORE_VALUE on errors.
1323 : */
1324 0 : int64_t cache_control_settings::string_to_seconds(std::string const & max_age)
1325 : {
1326 0 : if(max_age.empty())
1327 : {
1328 : // undefined / invalid (not 0)
1329 : //
1330 0 : return IGNORE_VALUE;
1331 : }
1332 :
1333 0 : char const * s(max_age.c_str());
1334 0 : char const * const start(s);
1335 0 : int64_t result(0);
1336 0 : for(; *s != '\0'; ++s)
1337 : {
1338 0 : if(*s < '0'
1339 0 : || *s > '9'
1340 0 : || s - start > 9) // too large! (for 1 year in seconds we need 8 digits maximum)
1341 : {
1342 : // invalid
1343 : //
1344 0 : return IGNORE_VALUE;
1345 : }
1346 0 : result = result * 10 + *s - '0';
1347 : }
1348 :
1349 0 : return result > AGE_MAXIMUM ? AGE_MAXIMUM : result;
1350 : }
1351 :
1352 :
1353 : /** \brief Retrieve the smallest value of two.
1354 : *
1355 : * This special minimum function returns the smallest of two values,
1356 : * only if one of those values is IGNORE_VALUE, then it is ignored
1357 : * and the other is returned. Of course, if both are IGNORE_VALUE,
1358 : * you get IGNORE_VALUE as a result.
1359 : *
1360 : * \note
1361 : * This function is expected to be used with the 'max-age' and
1362 : * 's-maxage' numbers. These numbers are expected to be defined
1363 : * between 0 and AGE_MAXIMUM, or set to IGNORE_VALUE.
1364 : *
1365 : * \param[in] a The left hand side value.
1366 : * \param[in] b The right hand side value.
1367 : *
1368 : * \return The smallest of a and b, ignoring either if set to IGNORE_VALUE.
1369 : */
1370 0 : int64_t cache_control_settings::minimum(int64_t const a, int64_t const b)
1371 : {
1372 : // if a or b are -1, then return the other
1373 : //
1374 0 : if(a == IGNORE_VALUE)
1375 : {
1376 : // in this case the value may return -1
1377 : //
1378 0 : return b;
1379 : }
1380 0 : if(b == IGNORE_VALUE)
1381 : {
1382 0 : return a;
1383 : }
1384 :
1385 : // normal std::min() otherwise
1386 : //
1387 0 : return std::min(a, b);
1388 : }
1389 :
1390 :
1391 : } // namespace edhttp
1392 : // vim: ts=4 sw=4 et
|