📄 proxy_cache.c
字号:
/* get etag */ if ((etag = ap_table_get(c->hdrs, "Etag"))) { wetag = ap_pstrcat(r->pool, "W/", etag, NULL); } /* check for If-Match, If-Unmodified-Since */ while (1) { /* * check If-Match and If-Unmodified-Since exist * * If neither of these exist, the request is not conditional, and we * serve it normally */ if (!c->im && BAD_DATE == c->ius) { break; } /* * check If-Match * * we check if the Etag on the cached file is in the list of Etags in * the If-Match field. The comparison must be a strong comparison, so * the Etag cannot be marked as weak. If the comparision fails we * return 412 Precondition Failed. * * if If-Match is specified AND If-Match is not a "*" AND Etag is * missing or weak or not in the list THEN return 412 Precondition * Failed */ if (c->im) { if (strcmp(c->im, "*") && (!etag || (strlen(etag) > 1 && 'W' == etag[0] && '/' == etag[1]) || !ap_proxy_liststr(c->im, etag, NULL))) { ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "If-Match specified, and it didn't - return 412"); } else { ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "If-Match specified, and it matched"); break; } } /* * check If-Unmodified-Since * * if If-Unmodified-Since is specified AND Last-Modified is specified * somewhere AND If-Unmodified-Since is in the past compared to * Last-Modified THEN return 412 Precondition Failed */ if (BAD_DATE != c->ius && BAD_DATE != c->lmod) { if (c->ius < c->lmod) { ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "If-Unmodified-Since specified, but it wasn't - return 412"); } else { ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "If-Unmodified-Since specified, and it was unmodified"); break; } } /* if cache file is being updated */ if (c->origfp) { ap_proxy_write_headers(c, c->resp_line, c->hdrs); ap_proxy_send_fb(c->origfp, r, c, c->len, 1, 0, IOBUFSIZE); ap_proxy_cache_tidy(c); } else ap_pclosef(r->pool, ap_bfileno(cachefp, B_WR)); ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "Use your cached copy, conditional precondition failed."); return HTTP_PRECONDITION_FAILED; } /* check for If-None-Match, If-Modified-Since */ while (1) { /* * check for existance of If-None-Match and If-Modified-Since * * if neither of these headers have been set, then the request is not * conditional, and we just send the cached response and be done with * it. */ if (!c->inm && BAD_DATE == c->ims) { break; } /* * check If-None-Match * * we check if the Etag on the cached file is in the list of Etags in * the If-None-Match field. The comparison must be a strong * comparison, so the Etag cannot be marked as weak. If the * comparision fails we return 412 Precondition Failed. * * if If-None-Match is specified: if If-None-Match is a "*" THEN 304 * else if Etag is specified AND we get a match THEN 304 else if Weak * Etag is specified AND we get a match THEN 304 else sent the * original object */ if (c->inm) { if (!strcmp(c->inm, "*")) { ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "If-None-Match: * specified, return 304"); } else if (etag && ap_proxy_liststr(c->inm, etag, NULL)) { ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "If-None-Match: specified and we got a strong match - return 304"); } else if (wetag && ap_proxy_liststr(c->inm, wetag, NULL)) { ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "If-None-Match specified, and we got a weak match - return 304"); } else break; } /* * check If-Modified-Since * * if If-Modified-Since is specified AND Last-Modified is specified * somewhere: if last modification date is earlier than * If-Modified-Since THEN 304 else send the original object */ if (BAD_DATE != c->ims && BAD_DATE != c->lmod) { if (c->ims >= c->lmod) { ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "If-Modified-Since specified and not modified, try return 304"); } else break; } /* are we updating the cache file? */ if (c->origfp) { ap_proxy_write_headers(c, c->resp_line, c->hdrs); ap_proxy_send_fb(c->origfp, r, c, c->len, 1, 0, IOBUFSIZE); ap_proxy_cache_tidy(c); } else ap_pclosef(r->pool, ap_bfileno(cachefp, B_WR)); ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "Use local copy, cached file hasn't changed"); return HTTP_NOT_MODIFIED; } /* No conditional - just send it cousin! */ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "Local copy modified, send it"); r->status_line = strchr(c->resp_line, ' ') + 1; r->status = c->status; /* Prepare and send headers to client */ ap_proxy_table_replace(r->headers_out, c->hdrs); /* make sure our X-Cache header does not stomp on a previous header */ ap_table_mergen(r->headers_out, "X-Cache", c->xcache); /* content type is already set in the headers */ r->content_type = ap_table_get(r->headers_out, "Content-Type"); ap_send_http_header(r); /* are we rewriting the cache file? */ if (c->origfp) { ap_proxy_write_headers(c, c->resp_line, c->hdrs); ap_proxy_send_fb(c->origfp, r, c, c->len, r->header_only, 0, IOBUFSIZE); ap_proxy_cache_tidy(c); return OK; } /* no, we not */ if (!r->header_only) { ap_proxy_send_fb(cachefp, r, NULL, c->len, 0, 0, IOBUFSIZE); } else { ap_pclosef(r->pool, ap_bfileno(cachefp, B_WR)); } return OK;}/* * Call this to test for a resource in the cache * Returns DECLINED if we need to check the remote host * or an HTTP status code if successful * * Functions: * if URL is cached then * if cached file is not expired then * if last modified after if-modified-since then send body * else send 304 Not modified * else if cached file is expired then * if last modified after if-modified-since then add * last modified date to request */int ap_proxy_cache_check(request_rec *r, char *url, struct cache_conf * conf, cache_req **cr){ const char *datestr, *pragma_req = NULL, *pragma_cresp = NULL, *cc_req = NULL, *cc_cresp = NULL; cache_req *c; BUFF *cachefp; int i; void *sconf = r->server->module_config; proxy_server_conf *pconf = (proxy_server_conf *)ap_get_module_config(sconf, &proxy_module); const char *agestr = NULL; char *val; time_t age_c = 0; time_t age, maxage_req, maxage_cresp, maxage, smaxage, maxstale, minfresh; c = ap_pcalloc(r->pool, sizeof(cache_req)); *cr = c; c->req = r; c->url = ap_pstrdup(r->pool, url); c->filename = NULL; c->tempfile = NULL; c->fp = NULL; c->origfp = NULL; c->version = 0; c->len = -1; c->req_hdrs = NULL; c->hdrs = NULL; c->xcache = NULL; /* get the If-Modified-Since date of the request, if it exists */ c->ims = BAD_DATE; datestr = ap_table_get(r->headers_in, "If-Modified-Since"); if (datestr != NULL) { /* this may modify the value in the original table */ datestr = ap_proxy_date_canon(r->pool, datestr); c->ims = ap_parseHTTPdate(datestr); if (c->ims == BAD_DATE) /* bad or out of range date; remove it */ ap_table_unset(r->headers_in, "If-Modified-Since"); }/* get the If-Unmodified-Since date of the request, if it exists */ c->ius = BAD_DATE; datestr = ap_table_get(r->headers_in, "If-Unmodified-Since"); if (datestr != NULL) { /* this may modify the value in the original table */ datestr = ap_proxy_date_canon(r->pool, datestr); c->ius = ap_parseHTTPdate(datestr); if (c->ius == BAD_DATE) /* bad or out of range date; remove it */ ap_table_unset(r->headers_in, "If-Unmodified-Since"); }/* get the If-Match of the request, if it exists */ c->im = ap_table_get(r->headers_in, "If-Match");/* get the If-None-Match of the request, if it exists */ c->inm = ap_table_get(r->headers_in, "If-None-Match");/* find the filename for this cache entry */ if (conf->root != NULL) { char hashfile[66]; ap_proxy_hash(url, hashfile, pconf->cache.dirlevels, pconf->cache.dirlength); c->filename = ap_pstrcat(r->pool, conf->root, "/", hashfile, NULL); } else { c->filename = NULL; c->fp = NULL; ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "No CacheRoot, so no caching. Declining."); return DECLINED; }/* find certain cache controlling headers */ pragma_req = ap_table_get(r->headers_in, "Pragma"); cc_req = ap_table_get(r->headers_in, "Cache-Control");/* first things first - does the request allow us to return * cached information at all? If not, just decline the request. * * Note that there is a big difference between not being allowed * to cache a request (no-store) and not being allowed to return * a cached request without revalidation (max-age=0). * * Caching is forbidden under the following circumstances: * * - RFC2616 14.9.2 Cache-Control: no-store * we are not supposed to store this request at all. Behave as a tunnel. * */ if (ap_proxy_liststr(cc_req, "no-store", NULL)) {/* delete the previously cached file */ if (c->filename) unlink(c->filename); c->fp = NULL; c->filename = NULL; ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "no-store forbids caching. Declining."); return DECLINED; }/* if the cache file exists, open it */ cachefp = NULL; ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "Request for %s, pragma_req=%s, ims=%ld", url, (pragma_req == NULL) ? "(unset)" : pragma_req, c->ims);/* find out about whether the request can access the cache */ if (c->filename != NULL && r->method_number == M_GET && strlen(url) < 1024) { cachefp = ap_proxy_open_cachefile(r, c->filename); } /* * if a cache file exists, try reading body and headers from cache file */ if (cachefp != NULL) { i = rdcache(r, cachefp, c); if (i == -1) ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "proxy: error reading cache file %s", c->filename); else if (i == 0) ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, r, "proxy: bad (short?) cache file: %s", c->filename); if (i != 1) { ap_pclosef(r->pool, ap_bfileno(cachefp, B_WR)); cachefp = NULL; } if (c->hdrs) { cc_cresp = ap_table_get(c->hdrs, "Cache-Control"); pragma_cresp = ap_table_get(c->hdrs, "Pragma"); if ((agestr = ap_table_get(c->hdrs, "Age"))) { age_c = atoi(agestr); } } } /* if a cache file does not exist, create empty header array *//* fixed? in this case, we want to get the headers from the remote server it will be handled later if we don't do this (I hope ;-) if (cachefp == NULL) c->hdrs = ap_make_table(r->pool, 20);*/ /* FIXME: Shouldn't we check the URL somewhere? */ /* * Check Content-Negotiation - Vary * * At this point we need to make sure that the object we found in the cache * is the same object that would be delivered to the client, when the * effects of content negotiation are taken into effect. * * In plain english, we want to make sure that a language-negotiated * document in one language is not given to a client asking for a * language negotiated document in a different language by mistake. * * RFC2616 13.6 and 14.44 describe the Vary mechanism. */ if (c->hdrs && c->req_hdrs) { char *vary = ap_pstrdup(r->pool, ap_table_get(c->hdrs, "Vary")); while (vary && *vary) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -