📄 proxy_cache.c
字号:
struct dirent *ent;#endif struct gc_ent *fent; int nfiles = 0; ap_snprintf(cachedir, sizeof(cachedir), "%s%s", cachebasedir, cachesubdir); Explain1("GC Examining directory %s", cachedir); dir = opendir(cachedir); if (dir == NULL) { ap_log_error(APLOG_MARK, APLOG_ERR, r->server, "proxy gc: opendir(%s)", cachedir); return 0; } while ((ent = readdir(dir)) != NULL) { if (ent->d_name[0] == '.') continue; sprintf(filename, "%s%s", cachedir, ent->d_name); Explain1("GC Examining file %s", filename);/* is it a temporary file? */ if (strncmp(ent->d_name, "tmp", 3) == 0) {/* then stat it to see how old it is; delete temporary files > 1 day old */ if (stat(filename, &buf) == -1) { if (errno != ENOENT) ap_log_error(APLOG_MARK, APLOG_ERR, r->server, "proxy gc: stat(%s)", filename); } else if (garbage_now != -1 && buf.st_atime < garbage_now - SEC_ONE_DAY && buf.st_mtime < garbage_now - SEC_ONE_DAY) { Explain1("GC unlink %s", filename); ap_log_error(APLOG_MARK, APLOG_INFO|APLOG_NOERRNO, r->server, "proxy gc: deleting orphaned cache file %s", filename);#if TESTING fprintf(stderr, "Would unlink %s\n", filename);#else unlink(filename);#endif } continue; } ++nfiles;/* is it another file? */ /* FIXME: Shouldn't any unexpected files be deleted? */ /* if (strlen(ent->d_name) != HASH_LEN) continue; *//* under OS/2 use dirent's d_attr to identify a diretory */#ifdef OS2/* is it a directory? */ if (ent->d_attr & A_DIR) { char newcachedir[HUGE_STRING_LEN]; ap_snprintf(newcachedir, sizeof(newcachedir), "%s%s/", cachesubdir, ent->d_name); if (!sub_garbage_coll(r, files, cachebasedir, newcachedir)) { ap_snprintf(newcachedir, sizeof(newcachedir), "%s%s", cachedir, ent->d_name);#if TESTING fprintf(stderr, "Would remove directory %s\n", newcachedir);#else rmdir(newcachedir);#endif --nfiles; } continue; }#endif/* read the file */ fd = open(filename, O_RDONLY | O_BINARY); if (fd == -1) { if (errno != ENOENT) ap_log_error(APLOG_MARK, APLOG_ERR, r->server, "proxy gc: open(%s)", filename); continue; } if (fstat(fd, &buf) == -1) { ap_log_error(APLOG_MARK, APLOG_ERR, r->server, "proxy gc: fstat(%s)", filename); close(fd); continue; }/* In OS/2 this has already been done above */#ifndef OS2 if (S_ISDIR(buf.st_mode)) { char newcachedir[HUGE_STRING_LEN]; close(fd); ap_snprintf(newcachedir, sizeof(newcachedir), "%s%s/", cachesubdir, ent->d_name); if (!sub_garbage_coll(r, files, cachebasedir, newcachedir)) { ap_snprintf(newcachedir, sizeof(newcachedir), "%s%s", cachedir, ent->d_name);#if TESTING fprintf(stderr, "Would remove directory %s\n", newcachedir);#else rmdir(newcachedir);#endif --nfiles; } else { /* Directory is not empty. Account for its size: */ add_long61(&curbytes, ROUNDUP2BLOCKS(buf.st_size)); } continue; }#endif i = read(fd, line, 26); close(fd); if (i == -1) { ap_log_error(APLOG_MARK, APLOG_ERR, r->server, "proxy gc: read(%s)", filename); continue; } line[i] = '\0'; garbage_expire = ap_proxy_hex2sec(line + 18); if (!ap_checkmask(line, "&&&&&&&& &&&&&&&& &&&&&&&&") || garbage_expire == BAD_DATE) { /* bad file */ if (garbage_now != -1 && buf.st_atime > garbage_now + SEC_ONE_DAY && buf.st_mtime > garbage_now + SEC_ONE_DAY) { ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, r->server, "proxy: deleting bad cache file with future date: %s", filename);#if TESTING fprintf(stderr, "Would unlink bad file %s\n", filename);#else unlink(filename);#endif } continue; }/* * we need to calculate an 'old' factor, and remove the 'oldest' files * so that the space requirement is met; sort by the expires date of the * file. * */ fent = (struct gc_ent *) ap_push_array(files); fent->len = buf.st_size; fent->expire = garbage_expire; strcpy(fent->file, cachesubdir); strcat(fent->file, ent->d_name);/* accumulate in blocks, to cope with directories > 4Gb */ add_long61(&curbytes, ROUNDUP2BLOCKS(buf.st_size)); } closedir(dir); return nfiles;}/* * read a cache file; * returns 1 on success, * 0 on failure (bad file or wrong URL) * -1 on UNIX error */static int rdcache(request_rec *r, BUFF *cachefp, cache_req *c){ char urlbuff[1034], *strp; int len;/* read the data from the cache file *//* format * date SP lastmod SP expire SP count SP content-length CRLF * dates are stored as hex seconds since 1970 */ len = ap_bgets(urlbuff, sizeof urlbuff, cachefp); if (len == -1) return -1; if (len == 0 || urlbuff[len - 1] != '\n') return 0; urlbuff[len - 1] = '\0'; if (!ap_checkmask(urlbuff, "&&&&&&&& &&&&&&&& &&&&&&&& &&&&&&&& &&&&&&&&")) return 0; c->date = ap_proxy_hex2sec(urlbuff); c->lmod = ap_proxy_hex2sec(urlbuff + 9); c->expire = ap_proxy_hex2sec(urlbuff + 18); c->version = ap_proxy_hex2sec(urlbuff + 27); c->len = ap_proxy_hex2sec(urlbuff + 36);/* check that we have the same URL */ len = ap_bgets(urlbuff, sizeof urlbuff, cachefp); if (len == -1) return -1; if (len == 0 || strncmp(urlbuff, "X-URL: ", 7) != 0 || urlbuff[len - 1] != '\n') return 0; urlbuff[len - 1] = '\0'; if (strcmp(urlbuff + 7, c->url) != 0) return 0;/* What follows is the message */ len = ap_bgets(urlbuff, sizeof urlbuff, cachefp); if (len == -1) return -1; if (len == 0 || urlbuff[len - 1] != '\n') return 0; urlbuff[--len] = '\0'; c->resp_line = ap_pstrdup(r->pool, urlbuff); strp = strchr(urlbuff, ' '); if (strp == NULL) return 0; c->status = atoi(strp); c->hdrs = ap_proxy_read_headers(r, urlbuff, sizeof urlbuff, cachefp); if (c->hdrs == NULL) return -1; if (c->len != -1) { /* add a content-length header */ if (ap_table_get(c->hdrs, "Content-Length") == NULL) { ap_table_set(c->hdrs, "Content-Length", ap_psprintf(r->pool, "%lu", (unsigned long)c->len)); } } return 1;}/* * 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 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){ char hashfile[66]; const char *imstr, *pragma, *auth; cache_req *c; time_t now; BUFF *cachefp; int cfd, i; const long int zero = 0L; void *sconf = r->server->module_config; proxy_server_conf *pconf = (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module); c = ap_pcalloc(r->pool, sizeof(cache_req)); *cr = c; c->req = r; c->url = ap_pstrdup(r->pool, url);/* get the If-Modified-Since date of the request */ c->ims = BAD_DATE; imstr = ap_table_get(r->headers_in, "If-Modified-Since"); if (imstr != NULL) {/* this may modify the value in the original table */ imstr = ap_proxy_date_canon(r->pool, imstr); c->ims = ap_parseHTTPdate(imstr); if (c->ims == BAD_DATE) /* bad or out of range date; remove it */ ap_table_unset(r->headers_in, "If-Modified-Since"); }/* find the filename for this cache entry */ ap_proxy_hash(url, hashfile, pconf->cache.dirlevels, pconf->cache.dirlength); if (conf->root != NULL) c->filename = ap_pstrcat(r->pool, conf->root, "/", hashfile, NULL); else c->filename = NULL; cachefp = NULL;/* find out about whether the request can access the cache */ pragma = ap_table_get(r->headers_in, "Pragma"); auth = ap_table_get(r->headers_in, "Authorization"); Explain5("Request for %s, pragma=%s, auth=%s, ims=%ld, imstr=%s", url, pragma, auth, c->ims, imstr); if (c->filename != NULL && r->method_number == M_GET && strlen(url) < 1024 && !ap_proxy_liststr(pragma, "no-cache") && auth == NULL) { Explain1("Check file %s", c->filename); cfd = open(c->filename, O_RDWR | O_BINARY); if (cfd != -1) { ap_note_cleanups_for_fd(r->pool, cfd); cachefp = ap_bcreate(r->pool, B_RD | B_WR); ap_bpushfd(cachefp, cfd, cfd); } else if (errno != ENOENT) ap_log_rerror(APLOG_MARK, APLOG_ERR, r, "proxy: error opening cache file %s", c->filename);#ifdef EXPLAIN else Explain1("File %s not found", c->filename);#endif } 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, cachefp->fd); cachefp = NULL; } }/* 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? */ now = time(NULL);/* Ok, have we got some un-expired data? */ if (cachefp != NULL && c->expire != BAD_DATE && now < c->expire) { Explain0("Unexpired data available");/* check IMS */ if (c->lmod != BAD_DATE && c->ims != BAD_DATE && c->ims >= c->lmod) {/* has the cached file changed since this request? */ if (c->date == BAD_DATE || c->date > c->ims) {/* No, but these header values may have changed, so we send them with the * 304 HTTP_NOT_MODIFIED response */ const char *q; if ((q = ap_table_get(c->hdrs, "Expires")) != NULL) ap_table_set(r->headers_out, "Expires", q); } ap_pclosef(r->pool, cachefp->fd); Explain0("Use local copy, cached file hasn't changed"); return HTTP_NOT_MODIFIED; }/* Ok, has been modified */ Explain0("Local copy modified, send it"); r->status_line = strchr(c->resp_line, ' ') + 1; r->status = c->status; if (!r->assbackwards) { ap_soft_timeout("proxy send headers", r); ap_proxy_send_headers(r, c->resp_line, c->hdrs); ap_kill_timeout(r); } ap_bsetopt(r->connection->client, BO_BYTECT, &zero); r->sent_bodyct = 1; if (!r->header_only) ap_proxy_send_fb(cachefp, r, NULL); ap_pclosef(r->pool, cachefp->fd); return OK; }/* if we already have data and a last-modified date, and it is not a head * request, then add an If-Modified-Since */ if (cachefp != NULL && c->lmod != BAD_DATE && !r->header_only) {/* * use the later of the one from the request and the last-modified date * from the cache */ if (c->ims == BAD_DATE || c->ims < c->lmod) { const char *q; if ((q = ap_table_get(c->hdrs, "Last-Modified")) != NULL) ap_table_set(r->headers_in, "If-Modified-Since", (char *) q); } } c->fp = cachefp; Explain0("Local copy not present or expired. Declining."); return DECLINED;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -