MINOR: http: add a function to check request's cache-control header field
The new function check_request_for_cacheability() is used to check if a request may be served from the cache, and/or allows the response to be stored into the cache. For this it checks the cache-control and pragma header fields, and adjusts the existing TX_CACHEABLE and a new TX_CACHE_IGNORE flags. For now, just like its response side counterpart, it only checks the first value of the header field. These functions should be reworked to improve their parsers and validate all elements.
This commit is contained in:
parent
faf2909f9f
commit
0ad8e0dfea
@ -72,6 +72,7 @@ int apply_filters_to_request(struct stream *s, struct channel *req, struct proxy
|
||||
int apply_filters_to_response(struct stream *s, struct channel *rtr, struct proxy *px);
|
||||
void manage_client_side_cookies(struct stream *s, struct channel *req);
|
||||
void manage_server_side_cookies(struct stream *s, struct channel *rtr);
|
||||
void check_request_for_cacheability(struct stream *s, struct channel *chn);
|
||||
void check_response_for_cacheability(struct stream *s, struct channel *rtr);
|
||||
int stats_check_uri(struct stream_interface *si, struct http_txn *txn, struct proxy *backend);
|
||||
void init_proto_http();
|
||||
|
@ -68,9 +68,10 @@
|
||||
/* cacheability management, bits values 0x1000 to 0x3000 (0-3 shift 12) */
|
||||
#define TX_CACHEABLE 0x00001000 /* at least part of the response is cacheable */
|
||||
#define TX_CACHE_COOK 0x00002000 /* a cookie in the response is cacheable */
|
||||
#define TX_CACHE_IGNORE 0x00004000 /* do not retrieve object from cache */
|
||||
#define TX_CACHE_SHIFT 12 /* bit shift */
|
||||
|
||||
/* Unused: 0x4000, 0x8000 */
|
||||
/* Unused: 0x8000 */
|
||||
|
||||
#define TX_WAIT_CLEANUP 0x0010000 /* this transaction is waiting for a clean up */
|
||||
|
||||
|
@ -7679,6 +7679,95 @@ void manage_server_side_cookies(struct stream *s, struct channel *res)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Parses the Cache-Control and Pragma request header fields to determine if
|
||||
* the request may be served from the cache and/or if it is cacheable. Updates
|
||||
* s->txn->flags.
|
||||
*/
|
||||
void check_request_for_cacheability(struct stream *s, struct channel *chn)
|
||||
{
|
||||
struct http_txn *txn = s->txn;
|
||||
char *p1, *p2;
|
||||
char *cur_ptr, *cur_end, *cur_next;
|
||||
int pragma_found;
|
||||
int cc_found;
|
||||
int cur_idx;
|
||||
|
||||
if ((txn->flags & (TX_CACHEABLE|TX_CACHE_IGNORE)) == TX_CACHE_IGNORE)
|
||||
return; /* nothing more to do here */
|
||||
|
||||
cur_idx = 0;
|
||||
pragma_found = cc_found = 0;
|
||||
cur_next = chn->buf->p + hdr_idx_first_pos(&txn->hdr_idx);
|
||||
|
||||
while ((cur_idx = txn->hdr_idx.v[cur_idx].next)) {
|
||||
struct hdr_idx_elem *cur_hdr;
|
||||
int val;
|
||||
|
||||
cur_hdr = &txn->hdr_idx.v[cur_idx];
|
||||
cur_ptr = cur_next;
|
||||
cur_end = cur_ptr + cur_hdr->len;
|
||||
cur_next = cur_end + cur_hdr->cr + 1;
|
||||
|
||||
/* We have one full header between cur_ptr and cur_end, and the
|
||||
* next header starts at cur_next.
|
||||
*/
|
||||
|
||||
val = http_header_match2(cur_ptr, cur_end, "Pragma", 6);
|
||||
if (val) {
|
||||
if ((cur_end - (cur_ptr + val) >= 8) &&
|
||||
strncasecmp(cur_ptr + val, "no-cache", 8) == 0) {
|
||||
pragma_found = 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
val = http_header_match2(cur_ptr, cur_end, "Cache-control", 13);
|
||||
if (!val)
|
||||
continue;
|
||||
|
||||
/* OK, right now we know we have a cache-control header at cur_ptr */
|
||||
cc_found = 1;
|
||||
p1 = cur_ptr + val; /* first non-space char after 'cache-control:' */
|
||||
|
||||
if (p1 >= cur_end) /* no more info */
|
||||
continue;
|
||||
|
||||
/* p1 is at the beginning of the value */
|
||||
p2 = p1;
|
||||
while (p2 < cur_end && *p2 != '=' && *p2 != ',' && !isspace((unsigned char)*p2))
|
||||
p2++;
|
||||
|
||||
/* we have a complete value between p1 and p2. We don't check the
|
||||
* values after max-age, max-stale nor min-fresh, we simply don't
|
||||
* use the cache when they're specified.
|
||||
*/
|
||||
if (((p2 - p1 == 7) && strncasecmp(p1, "max-age", 7) == 0) ||
|
||||
((p2 - p1 == 8) && strncasecmp(p1, "no-cache", 8) == 0) ||
|
||||
((p2 - p1 == 9) && strncasecmp(p1, "max-stale", 9) == 0) ||
|
||||
((p2 - p1 == 9) && strncasecmp(p1, "min-fresh", 9) == 0)) {
|
||||
txn->flags |= TX_CACHE_IGNORE;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((p2 - p1 == 8) && strncasecmp(p1, "no-store", 8) == 0) {
|
||||
txn->flags &= ~TX_CACHEABLE & ~TX_CACHE_COOK;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* RFC7234#5.4:
|
||||
* When the Cache-Control header field is also present and
|
||||
* understood in a request, Pragma is ignored.
|
||||
* When the Cache-Control header field is not present in a
|
||||
* request, caches MUST consider the no-cache request
|
||||
* pragma-directive as having the same effect as if
|
||||
* "Cache-Control: no-cache" were present.
|
||||
*/
|
||||
if (!cc_found && pragma_found)
|
||||
txn->flags |= TX_CACHE_IGNORE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if response is cacheable or not. Updates s->txn->flags.
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user