mirror of
https://github.com/apache/httpd.git
synced 2025-08-08 15:02:10 +03:00
Begin the process of optimising the parsing of Cache-Control headers. Parse
the incoming Cache-Control and Pragma headers once, instead of on each test. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1023360 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
@@ -274,12 +274,13 @@
|
||||
* Make root parameter of ap_expr_eval() const.
|
||||
* 20100923.3 (2.3.9-dev) Add "last" member to ap_directive_t
|
||||
* 20101012.0 (2.3.9-dev) Add header to cache_status hook.
|
||||
* 20101016.0 (2.3.9-dev) Remove ap_cache_check_allowed().
|
||||
*/
|
||||
|
||||
#define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
|
||||
|
||||
#ifndef MODULE_MAGIC_NUMBER_MAJOR
|
||||
#define MODULE_MAGIC_NUMBER_MAJOR 20101012
|
||||
#define MODULE_MAGIC_NUMBER_MAJOR 20101016
|
||||
#endif
|
||||
#define MODULE_MAGIC_NUMBER_MINOR 0 /* 0...n */
|
||||
|
||||
|
2
modules/cache/cache_storage.c
vendored
2
modules/cache/cache_storage.c
vendored
@@ -216,7 +216,7 @@ int cache_select(cache_request_rec *cache, request_rec *r)
|
||||
}
|
||||
}
|
||||
|
||||
if (!ap_cache_check_allowed(r)) {
|
||||
if (!ap_cache_check_allowed(cache, r)) {
|
||||
return DECLINED;
|
||||
}
|
||||
|
||||
|
174
modules/cache/cache_util.c
vendored
174
modules/cache/cache_util.c
vendored
@@ -383,7 +383,7 @@ apr_status_t cache_remove_lock(cache_server_conf *conf,
|
||||
return apr_file_remove(lockname, r->pool);
|
||||
}
|
||||
|
||||
CACHE_DECLARE(int) ap_cache_check_allowed(request_rec *r) {
|
||||
CACHE_DECLARE(int) ap_cache_check_allowed(cache_request_rec *cache, request_rec *r) {
|
||||
const char *cc_req;
|
||||
const char *pragma;
|
||||
cache_server_conf *conf =
|
||||
@@ -409,8 +409,9 @@ CACHE_DECLARE(int) ap_cache_check_allowed(request_rec *r) {
|
||||
cc_req = apr_table_get(r->headers_in, "Cache-Control");
|
||||
pragma = apr_table_get(r->headers_in, "Pragma");
|
||||
|
||||
if (ap_cache_liststr(NULL, pragma, "no-cache", NULL)
|
||||
|| ap_cache_liststr(NULL, cc_req, "no-cache", NULL)) {
|
||||
ap_cache_control(r, &cache->control_in, cc_req, pragma, r->headers_in);
|
||||
|
||||
if (cache->control_in.no_cache) {
|
||||
|
||||
if (!conf->ignorecachecontrol) {
|
||||
return 0;
|
||||
@@ -423,7 +424,7 @@ CACHE_DECLARE(int) ap_cache_check_allowed(request_rec *r) {
|
||||
}
|
||||
}
|
||||
|
||||
if (ap_cache_liststr(NULL, cc_req, "no-store", NULL)) {
|
||||
if (cache->control_in.no_store) {
|
||||
|
||||
if (!conf->ignorecachecontrol) {
|
||||
/* We're not allowed to serve a cached copy */
|
||||
@@ -1012,3 +1013,168 @@ CACHE_DECLARE(apr_table_t *)ap_cache_cacheable_headers_out(request_rec *r)
|
||||
|
||||
return headers_out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the Cache-Control and Pragma headers in one go, marking
|
||||
* which tokens appear within the header. Populate the structure
|
||||
* passed in.
|
||||
*/
|
||||
int ap_cache_control(request_rec *r, cache_control_t *cc,
|
||||
const char *cc_header, const char *pragma_header, apr_table_t *headers)
|
||||
{
|
||||
char *last;
|
||||
|
||||
if (cc->parsed) {
|
||||
return cc->cache_control || cc->pragma;
|
||||
}
|
||||
|
||||
cc->parsed = 1;
|
||||
cc->max_age_value = -1;
|
||||
cc->max_stale_value = -1;
|
||||
cc->min_fresh_value = -1;
|
||||
cc->s_maxage_value = -1;
|
||||
|
||||
if (pragma_header) {
|
||||
char *header = apr_pstrdup(r->pool, pragma_header);
|
||||
const char *token = apr_strtok(header, ", ", &last);
|
||||
while (token) {
|
||||
/* handle most common quickest case... */
|
||||
if (!strcmp(token, "no-cache")) {
|
||||
cc->no_cache = 1;
|
||||
}
|
||||
/* ...then try slowest case */
|
||||
else if (!strcasecmp(token, "no-cache")) {
|
||||
cc->no_cache = 1;
|
||||
}
|
||||
token = apr_strtok(NULL, ", ", &last);
|
||||
}
|
||||
cc->pragma = 1;
|
||||
}
|
||||
|
||||
if (cc_header) {
|
||||
char *header = apr_pstrdup(r->pool, cc_header);
|
||||
const char *token = apr_strtok(header, ", ", &last);
|
||||
while (token) {
|
||||
switch (token[0]) {
|
||||
case 'n':
|
||||
case 'N': {
|
||||
/* handle most common quickest cases... */
|
||||
if (!strcmp(token, "no-cache")) {
|
||||
cc->no_cache = 1;
|
||||
}
|
||||
else if (!strcmp(token, "no-store")) {
|
||||
cc->no_store = 1;
|
||||
}
|
||||
/* ...then try slowest cases */
|
||||
else if (!strncasecmp(token, "no-cache", 8)) {
|
||||
if (token[8] == '=') {
|
||||
if (apr_table_get(headers, token + 9)) {
|
||||
cc->no_cache_header = 1;
|
||||
}
|
||||
}
|
||||
else if (!token[8]) {
|
||||
cc->no_cache = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (!strcasecmp(token, "no-store")) {
|
||||
cc->no_store = 1;
|
||||
}
|
||||
else if (!strcasecmp(token, "no-transform")) {
|
||||
cc->no_transform = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'm':
|
||||
case 'M': {
|
||||
/* handle most common quickest cases... */
|
||||
if (!strcmp(token, "max-age=0")) {
|
||||
cc->max_age = 1;
|
||||
cc->max_age_value = 0;
|
||||
}
|
||||
else if (!strcmp(token, "must-revalidate")) {
|
||||
cc->must_revalidate = 1;
|
||||
}
|
||||
/* ...then try slowest cases */
|
||||
else if (!strncasecmp(token, "max-age", 7)) {
|
||||
if (token[7] == '=') {
|
||||
cc->max_age = 1;
|
||||
cc->max_age_value = atoi(token + 8);
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (!strncasecmp(token, "max-stale", 9)) {
|
||||
if (token[9] == '=') {
|
||||
cc->max_stale = 1;
|
||||
cc->max_stale_value = atoi(token + 10);
|
||||
}
|
||||
else if (!token[10]) {
|
||||
cc->max_stale = 1;
|
||||
cc->max_stale_value = -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (!strncasecmp(token, "min-fresh", 9)) {
|
||||
if (token[9] == '=') {
|
||||
cc->min_fresh = 1;
|
||||
cc->min_fresh_value = atoi(token + 10);
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (!strcasecmp(token, "must-revalidate")) {
|
||||
cc->must_revalidate = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'o':
|
||||
case 'O': {
|
||||
if (!strcasecmp(token, "only-if-cached")) {
|
||||
cc->only_if_cached = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'p':
|
||||
case 'P': {
|
||||
/* handle most common quickest cases... */
|
||||
if (!strcmp(token, "private")) {
|
||||
cc->private = 1;
|
||||
}
|
||||
/* ...then try slowest cases */
|
||||
else if (!strcasecmp(token, "public")) {
|
||||
cc->public = 1;
|
||||
}
|
||||
else if (!strncasecmp(token, "private", 7)) {
|
||||
if (token[7] == '=') {
|
||||
if (apr_table_get(headers, token + 8)) {
|
||||
cc->private_header = 1;
|
||||
}
|
||||
}
|
||||
else if (!token[7]) {
|
||||
cc->private = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (!strcasecmp(token, "proxy-revalidate")) {
|
||||
cc->proxy_revalidate = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 's':
|
||||
case 'S': {
|
||||
if (!strncasecmp(token, "s-maxage", 8)) {
|
||||
if (token[8] == '=') {
|
||||
cc->s_maxage = 1;
|
||||
cc->s_maxage_value = atoi(token + 9);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
token = apr_strtok(NULL, ", ", &last);
|
||||
}
|
||||
cc->cache_control = 1;
|
||||
}
|
||||
|
||||
return (cc_header != NULL || pragma_header != NULL);
|
||||
}
|
||||
|
43
modules/cache/cache_util.h
vendored
43
modules/cache/cache_util.h
vendored
@@ -190,6 +190,31 @@ typedef struct {
|
||||
int stale_on_error_set;
|
||||
} cache_dir_conf;
|
||||
|
||||
/* a cache control header breakdown */
|
||||
typedef struct {
|
||||
unsigned int parsed:1;
|
||||
unsigned int cache_control:1;
|
||||
unsigned int pragma:1;
|
||||
unsigned int no_cache:1;
|
||||
unsigned int no_cache_header:1; /* no cache by header match */
|
||||
unsigned int no_store:1;
|
||||
unsigned int max_age:1;
|
||||
unsigned int max_stale:1;
|
||||
unsigned int min_fresh:1;
|
||||
unsigned int no_transform:1;
|
||||
unsigned int only_if_cached:1;
|
||||
unsigned int public:1;
|
||||
unsigned int private:1;
|
||||
unsigned int private_header:1; /* private by header match */
|
||||
unsigned int must_revalidate:1;
|
||||
unsigned int proxy_revalidate:1;
|
||||
unsigned int s_maxage:1;
|
||||
int max_age_value; /* if positive, then set */
|
||||
int max_stale_value; /* if positive, then set */
|
||||
int min_fresh_value; /* if positive, then set */
|
||||
int s_maxage_value; /* if positive, then set */
|
||||
} cache_control_t;
|
||||
|
||||
/* A linked-list of authn providers. */
|
||||
typedef struct cache_provider_list cache_provider_list;
|
||||
|
||||
@@ -222,8 +247,26 @@ typedef struct {
|
||||
*/
|
||||
apr_off_t size; /* the content length from the headers, or -1 */
|
||||
apr_bucket_brigade *out; /* brigade to reuse for upstream responses */
|
||||
cache_control_t control_in; /* cache control incoming */
|
||||
} cache_request_rec;
|
||||
|
||||
/**
|
||||
* Parse the Cache-Control and Pragma headers in one go, marking
|
||||
* which tokens appear within the header. Populate the structure
|
||||
* passed in.
|
||||
*/
|
||||
int ap_cache_control(request_rec *r, cache_control_t *cc, const char *cc_header,
|
||||
const char *pragma_header, apr_table_t *headers);
|
||||
|
||||
/**
|
||||
* Check the whether the request allows a cached object to be served as per RFC2616
|
||||
* section 14.9.4 (Cache Revalidation and Reload Controls)
|
||||
* @param h cache_handle_t
|
||||
* @param r request_rec
|
||||
* @return 0 ==> cache object may not be served, 1 ==> cache object may be served
|
||||
*/
|
||||
CACHE_DECLARE(int) ap_cache_check_allowed(cache_request_rec *cache, request_rec *r);
|
||||
|
||||
/**
|
||||
* Check the freshness of the cache object per RFC2616 section 13.2 (Expiration Model)
|
||||
* @param h cache_handle_t
|
||||
|
9
modules/cache/mod_cache.h
vendored
9
modules/cache/mod_cache.h
vendored
@@ -124,15 +124,6 @@ typedef enum {
|
||||
CACHE_DECLARE(apr_time_t) ap_cache_current_age(cache_info *info, const apr_time_t age_value,
|
||||
apr_time_t now);
|
||||
|
||||
/**
|
||||
* Check the whether the request allows a cached object to be served as per RFC2616
|
||||
* section 14.9.4 (Cache Revalidation and Reload Controls)
|
||||
* @param h cache_handle_t
|
||||
* @param r request_rec
|
||||
* @return 0 ==> cache object may not be served, 1 ==> cache object may be served
|
||||
*/
|
||||
CACHE_DECLARE(int) ap_cache_check_allowed(request_rec *r);
|
||||
|
||||
CACHE_DECLARE(apr_time_t) ap_cache_hex2usec(const char *x);
|
||||
CACHE_DECLARE(void) ap_cache_usec2hex(apr_time_t j, char *y);
|
||||
CACHE_DECLARE(char *) ap_cache_generate_name(apr_pool_t *p, int dirlevels,
|
||||
|
Reference in New Issue
Block a user