📄 proxy_cache.c
字号:
dates = ap_table_get(resp_hdrs, "Date"); if (dates != NULL) date = ap_parseHTTPdate(dates); else date = BAD_DATE; now = time(NULL); if (date == BAD_DATE) { /* No, or bad date *//* no date header! *//* add one; N.B. use the time _now_ rather than when we were checking the cache */ date = now; dates = ap_gm_timestr_822(r->pool, now); ap_table_set(resp_hdrs, "Date", dates); ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "Added date header"); }/* set response_time for HTTP/1.1 age calculations */ c->resp_time = now;/* check last-modified date */ if (lmod != BAD_DATE && lmod > date)/* if its in the future, then replace by date */ { lmod = date; lmods = dates; ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "Last modified is in the future, replacing with now"); }/* if the response did not contain the header, then use the cached version */ if (lmod == BAD_DATE && c->fp != NULL) { lmod = c->lmod; ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "Reusing cached last modified"); }/* we now need to calculate the expire data for the object. */ if (expire == NULL && c->fp != NULL) { /* no expiry data sent in * response */ expire = ap_table_get(c->hdrs, "Expires"); if (expire != NULL) expc = ap_parseHTTPdate(expire); }/* so we now have the expiry date *//* if no expiry date then * if lastmod * expiry date = now + min((date - lastmod) * factor, maxexpire) * else * expire date = now + defaultexpire */ ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "Expiry date is %ld", (long)expc); if (expc == BAD_DATE) { if (lmod != BAD_DATE) { double x = (double)(date - lmod) * conf->cache.lmfactor; double maxex = conf->cache.maxexpire; if (x > maxex) x = maxex; expc = now + (int)x; } else expc = now + conf->cache.defaultexpire; ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "Expiry date calculated %ld", (long)expc); }/* get the content-length header */ clen = ap_table_get(resp_hdrs, "Content-Length"); if (clen == NULL) c->len = -1; else c->len = ap_strtol(clen, NULL, 10);/* we have all the header information we need - write it to the cache file */ c->version++; ap_proxy_sec2hex(date, buff + 17 * (0)); buff[17 * (1) - 1] = ' '; ap_proxy_sec2hex(lmod, buff + 17 * (1)); buff[17 * (2) - 1] = ' '; ap_proxy_sec2hex(expc, buff + 17 * (2)); buff[17 * (3) - 1] = ' '; ap_proxy_sec2hex(c->version, buff + 17 * (3)); buff[17 * (4) - 1] = ' '; ap_proxy_sec2hex(c->req_time, buff + 17 * (4)); buff[17 * (5) - 1] = ' '; ap_proxy_sec2hex(c->resp_time, buff + 17 * (5)); buff[17 * (6) - 1] = ' '; ap_proxy_sec2hex(c->len, buff + 17 * (6)); buff[17 * (7) - 1] = '\n'; buff[17 * (7)] = '\0';/* Was the server response a 304 Not Modified? * * If it was, it means that we requested a revalidation, and that * the result of that revalidation was that the object was fresh. * *//* if response from server 304 not modified */ if (r->status == HTTP_NOT_MODIFIED) {/* Have the headers changed? * * if not - we fulfil the request and return now. */ if (c->hdrs) { /* recall at this point that c->len is already set from resp_hdrs. If Content-Length was NULL, then c->len is -1, otherwise it's set to whatever the value was. */ if (c->len == 0 || c->len == -1) { const char *c_clen_str; off_t c_clen; if ( (c_clen_str = ap_table_get(c->hdrs, "Content-Length")) && ( (c_clen = ap_strtol(c_clen_str, NULL, 10)) > 0) ) { ap_table_set(resp_hdrs, "Content-Length", c_clen_str); c->len = c_clen; ap_proxy_sec2hex(c->len, buff + 17 * (6)); buff[17 * (7) - 1] = '\n'; buff[17 * (7)] = '\0'; } } if (!ap_proxy_table_replace(c->hdrs, resp_hdrs)) { c->xcache = ap_pstrcat(r->pool, "HIT from ", ap_get_server_name(r), " (with revalidation)", NULL); return ap_proxy_cache_conditional(r, c, c->fp); } } else c->hdrs = resp_hdrs;/* if we get here - the headers have changed. Go through the motions * of creating a new temporary cache file below, we'll then serve * the request like we would have in ap_proxy_cache_conditional() * above, and at the same time we will also rewrite the contents * to the new temporary file. */ }/* * Ok - lets prepare and open the cached file * * If a cached file (in c->fp) is already open, then we want to * update that cached file. Copy the c->fp to c->origfp and open * up a new one. * * If the cached file (in c->fp) is NULL, we must open a new cached * file from scratch. * * The new cache file will be moved to it's final location in the * directory tree later, overwriting the old cache file should it exist. *//* if a cache file was already open */ if (c->fp != NULL) { c->origfp = c->fp; } while (1) {/* create temporary filename */#ifndef TPF#define TMPFILESTR "/tmpXXXXXX" if (conf->cache.root == NULL) { c = ap_proxy_cache_error(c); break; } c->tempfile = ap_palloc(r->pool, strlen(conf->cache.root) + sizeof(TMPFILESTR)); strcpy(c->tempfile, conf->cache.root); strcat(c->tempfile, TMPFILESTR);#undef TMPFILESTR p = mktemp(c->tempfile);#else if (conf->cache.root == NULL) { c = ap_proxy_cache_error(c); break; } c->tempfile = ap_palloc(r->pool, strlen(conf->cache.root) + 1 + L_tmpnam); strcpy(c->tempfile, conf->cache.root); strcat(c->tempfile, "/"); p = tmpnam(NULL); strcat(c->tempfile, p);#endif if (p == NULL) { c = ap_proxy_cache_error(c); break; } ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "Create temporary file %s", c->tempfile);/* create the new file */ c->fp = ap_proxy_create_cachefile(r, c->tempfile); if (NULL == c->fp) { c = ap_proxy_cache_error(c); break; }/* write away the cache header and the URL */ if (ap_bvputs(c->fp, buff, "X-URL: ", c->url, "\n", NULL) == -1) { ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "proxy: error writing cache file(%s)", c->tempfile); c = ap_proxy_cache_error(c); break; }/* get original request headers */ if (c->req_hdrs) req_hdrs = ap_copy_table(r->pool, c->req_hdrs); else req_hdrs = ap_copy_table(r->pool, r->headers_in);/* remove hop-by-hop headers */ ap_proxy_clear_connection(r->pool, req_hdrs);/* save original request headers */ if (c->req_hdrs) ap_table_do(ap_proxy_send_hdr_line, c, c->req_hdrs, NULL); else ap_table_do(ap_proxy_send_hdr_line, c, r->headers_in, NULL); if (ap_bputs(CRLF, c->fp) == -1) { ap_log_rerror(APLOG_MARK, APLOG_ERR, c->req, "proxy: error writing request headers terminating CRLF to %s", c->tempfile); c = ap_proxy_cache_error(c); break; } break; }/* Was the server response a 304 Not Modified? * * If so, we have some work to do that we didn't do when we first * checked above. We need to fulfil the request, and we need to * copy the body from the old object to the new one. *//* if response from server 304 not modified */ if (r->status == HTTP_NOT_MODIFIED) {/* fulfil the request */ c->xcache = ap_pstrcat(r->pool, "HIT from ", ap_get_server_name(r), " (with revalidation)", NULL); return ap_proxy_cache_conditional(r, c, c->fp); } return DECLINED;}void ap_proxy_cache_tidy(cache_req *c){ server_rec *s; long int bc; if (!c || !c->fp) return; s = c->req->server;/* don't care how much was sent, but rather how much was written to cache ap_bgetopt(c->req->connection->client, BO_BYTECT, &bc); */ bc = c->written; if (c->len != -1) {/* file lengths don't match; don't cache it */ if (bc != c->len) { ap_pclosef(c->req->pool, ap_bfileno(c->fp, B_WR)); /* no need to flush */ unlink(c->tempfile); return; } }/* don't care if aborted, cache it if fully retrieved from host! else if (c->req->connection->aborted) { ap_pclosef(c->req->pool, c->fp->fd); / no need to flush / unlink(c->tempfile); return; }*/ else {/* update content-length of file */ char buff[17]; off_t curpos; c->len = bc; ap_bflush(c->fp); ap_proxy_sec2hex(c->len, buff); curpos = lseek(ap_bfileno(c->fp, B_WR), 17 * 6, SEEK_SET); if (curpos == -1) ap_log_error(APLOG_MARK, APLOG_ERR, s, "proxy: error seeking on cache file %s", c->tempfile); else if (write(ap_bfileno(c->fp, B_WR), buff, sizeof(buff) - 1) == -1) ap_log_error(APLOG_MARK, APLOG_ERR, s, "proxy: error updating cache file %s", c->tempfile); } if (ap_bflush(c->fp) == -1) { ap_log_error(APLOG_MARK, APLOG_ERR, s, "proxy: error writing to cache file %s", c->tempfile); ap_pclosef(c->req->pool, ap_bfileno(c->fp, B_WR)); unlink(c->tempfile); return; } if (ap_pclosef(c->req->pool, ap_bfileno(c->fp, B_WR))== -1) { ap_log_error(APLOG_MARK, APLOG_ERR, s, "proxy: error closing cache file %s", c->tempfile); unlink(c->tempfile); return; } if (unlink(c->filename) == -1 && errno != ENOENT) { ap_log_error(APLOG_MARK, APLOG_ERR, s, "proxy: error deleting old cache file %s", c->filename); (void)unlink(c->tempfile); } else { char *p; proxy_server_conf *conf = (proxy_server_conf *)ap_get_module_config(s->module_config, &proxy_module); for (p = c->filename + strlen(conf->cache.root) + 1;;) { p = strchr(p, '/'); if (!p) break; *p = '\0';#if defined(WIN32) || defined(NETWARE) if (mkdir(c->filename) < 0 && errno != EEXIST)#elif defined(__TANDEM) if (mkdir(c->filename, S_IRWXU | S_IRWXG | S_IRWXO) < 0 && errno != EEXIST)#else if (mkdir(c->filename, S_IREAD | S_IWRITE | S_IEXEC) < 0 && errno != EEXIST)#endif /* WIN32 */ ap_log_error(APLOG_MARK, APLOG_ERR, s, "proxy: error creating cache directory %s", c->filename); *p = '/'; ++p; }#if defined(OS2) || defined(WIN32) || defined(NETWARE) || defined(MPE) /* Under OS/2 use rename. */ if (rename(c->tempfile, c->filename) == -1) { ap_log_error(APLOG_MARK, APLOG_ERR, s, "proxy: error renaming cache file %s to %s", c->tempfile, c->filename); (void)unlink(c->tempfile); }#else if (link(c->tempfile, c->filename) == -1) ap_log_error(APLOG_MARK, APLOG_INFO, s, "proxy: error linking cache file %s to %s", c->tempfile, c->filename); if (unlink(c->tempfile) == -1) ap_log_error(APLOG_MARK, APLOG_ERR, s, "proxy: error deleting temp file %s", c->tempfile);#endif }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -