Return-Path: Delivered-To: apmail-apache-cvs-archive@apache.org Received: (qmail 11901 invoked by uid 500); 8 Jun 2001 07:39:41 -0000 Mailing-List: contact apache-cvs-help@apache.org; run by ezmlm Precedence: bulk Reply-To: new-httpd@apache.org list-help: list-unsubscribe: list-post: Delivered-To: mailing list apache-cvs@apache.org Received: (qmail 11517 invoked by uid 500); 8 Jun 2001 07:39:29 -0000 Delivered-To: apmail-httpd-proxy-cvs@apache.org Date: 8 Jun 2001 07:39:19 -0000 Message-ID: <20010608073919.11435.qmail@apache.org> From: chuck@apache.org To: httpd-proxy-cvs@apache.org Subject: cvs commit: httpd-proxy/module-1.0 CHANGES mod_proxy.h proxy_cache.c proxy_ftp.c proxy_http.c proxy_util.c chuck 01/06/08 00:39:18 Modified: module-1.0 CHANGES mod_proxy.h proxy_cache.c proxy_ftp.c proxy_http.c proxy_util.c Log: Add Christian's changes for persistent connections (2 of 3) This is now the 1.3.19 patch. Revision Changes Path 1.2 +8 -0 httpd-proxy/module-1.0/CHANGES Index: CHANGES =================================================================== RCS file: /home/cvs/httpd-proxy/module-1.0/CHANGES,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- CHANGES 2001/06/07 19:50:56 1.1 +++ CHANGES 2001/06/08 07:39:02 1.2 @@ -1,6 +1,14 @@ mod_proxy changes for httpd 1.3.21-dev + *) Add persistent connection handling + The patch changes mod_proxy to write the reply-headers using + ap_send_http_header() instead of directly using ap_bvputs(). This not + only simplifies mod_proxy, in my opinion at least, but enables it to + make use of the features of Apache's normal header and persistent + connection machinery. + [Christian von Roques ] + *) Graham Leggett's original 1.3.12 patch, updated for 1.3.19 Original comments: 1.2 +31 -9 httpd-proxy/module-1.0/mod_proxy.h Index: mod_proxy.h =================================================================== RCS file: /home/cvs/httpd-proxy/module-1.0/mod_proxy.h,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- mod_proxy.h 2001/06/07 19:50:57 1.1 +++ mod_proxy.h 2001/06/08 07:39:04 1.2 @@ -71,6 +71,36 @@ If TESTING is set, then garbage collection doesn't delete ... probably a good idea when hacking. + This code is still experimental! + + Things to do: + + 1. Make it garbage collect in the background, not while someone is waiting for + a response! + + 2. Check the logic thoroughly. + + 3. Empty directories are only removed the next time round (but this does avoid + two passes). Consider doing them the first time round. + + Ben Laurie 30 Mar 96 + + More things to do: + + 0. Code cleanup (ongoing) + + 1. add 230 response output for ftp now that it works + + 2. Make the ftp proxy transparent, also same with (future) gopher & wais + + 3. Use protocol handler struct a la Apache module handlers (Dirk van Gulik) + + 4. Use a cache expiry database for more efficient GC (Jeremy Wohl) + + 5. Bulletproof GC against SIGALRM + + Chuck Murcko 15 April 1997 + */ #define TESTING 0 @@ -243,13 +273,6 @@ char *xcache; /* the X-Cache header value to be sent to client */ } cache_req; -/* Additional information passed to the function called by ap_table_do() */ -struct tbl_do_args { - request_rec *req; - cache_req *cache; - size_t len; -}; - struct per_thread_data { struct hostent hpbuf; u_long ipaddr; @@ -294,7 +317,7 @@ const char *ap_proxy_date_canon(pool *p, const char *x); table *ap_proxy_read_headers(request_rec *r, char *buffer, int size, BUFF *f); long int ap_proxy_send_fb(BUFF *f, request_rec *r, cache_req *c, off_t len, int nowrite); -void ap_proxy_send_headers(request_rec *r, cache_req *c, const char *respline, const char *xcache, table *t); +void ap_proxy_write_headers(cache_req *c, const char *respline, table *t); int ap_proxy_liststr(const char *list, const char *key, char **val); void ap_proxy_hash(const char *it, char *val, int ndepth, int nlength); int ap_proxy_hex2sec(const char *x); @@ -309,7 +332,6 @@ int ap_proxy_doconnect(int sock, struct sockaddr_in *addr, request_rec *r); int ap_proxy_garbage_init(server_rec *, pool *); /* This function is called by ap_table_do() for all header lines */ -int ap_proxy_count_hdr_line(void *p, const char *key, const char *value); int ap_proxy_send_hdr_line(void *p, const char *key, const char *value); unsigned ap_proxy_bputs2(const char *data, BUFF *client, cache_req *cache); time_t ap_proxy_current_age(cache_req *c, const time_t age_value); 1.2 +28 -51 httpd-proxy/module-1.0/proxy_cache.c Index: proxy_cache.c =================================================================== RCS file: /home/cvs/httpd-proxy/module-1.0/proxy_cache.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- proxy_cache.c 2001/06/07 19:50:58 1.1 +++ proxy_cache.c 2001/06/08 07:39:06 1.2 @@ -62,6 +62,7 @@ #include "http_conf_globals.h" #include "http_log.h" #include "http_main.h" +#include "http_core.h" #include "util_date.h" #ifdef WIN32 #include @@ -726,17 +727,14 @@ */ int ap_proxy_cache_conditional(request_rec *r, cache_req *c, BUFF *cachefp) { - const long int zero = 0L; const char *etag, *wetag; /* get etag */ - if (etag = ap_table_get(c->hdrs, "Etag")) { + if ((etag = ap_table_get(c->hdrs, "Etag"))) { wetag = ap_pstrcat(r->pool, "W/", etag, NULL); } - /* check for If-Match, If-Unmodified-Since - * - */ + /* check for If-Match, If-Unmodified-Since */ while (1) { /* check If-Match and If-Unmodified-Since exist @@ -791,7 +789,7 @@ /* if cache file is being updated */ if (c->origfp) { - ap_proxy_send_headers(NULL, c, c->resp_line, c->xcache, c->hdrs); + ap_proxy_write_headers(c, c->resp_line, c->hdrs); ap_proxy_send_fb(c->origfp, r, c, c->len, 1); ap_pclosef(r->pool, ap_bfileno(c->origfp, B_WR)); ap_proxy_cache_tidy(c); @@ -804,9 +802,7 @@ } - /* check for If-None-Match, If-Modified-Since - * - */ + /* check for If-None-Match, If-Modified-Since */ while (1) { /* check for existance of If-None-Match and If-Modified-Since @@ -864,7 +860,7 @@ /* are we updating the cache file? */ if (c->origfp) { - ap_proxy_send_headers(NULL, c, c->resp_line, c->xcache, c->hdrs); + ap_proxy_write_headers(c, c->resp_line, c->hdrs); ap_proxy_send_fb(c->origfp, r, c, c->len, 1); ap_pclosef(r->pool, ap_bfileno(c->origfp, B_WR)); ap_proxy_cache_tidy(c); @@ -881,17 +877,16 @@ 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, NULL, c->resp_line, c->xcache, c->hdrs); - ap_kill_timeout(r); - } - ap_bsetopt(r->connection->client, BO_BYTECT, &zero); - r->sent_bodyct = 1; + /* Prepare and send headers to client */ + ap_overlap_tables(r->headers_out, c->hdrs, AP_OVERLAP_TABLES_SET); + ap_table_setn(r->headers_out, "X-Cache", c->xcache); + 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_send_headers(NULL, c, c->resp_line, NULL, c->hdrs); + ap_proxy_write_headers(c, c->resp_line, c->hdrs); ap_proxy_send_fb(c->origfp, r, c, c->len, r->header_only); ap_pclosef(r->pool, ap_bfileno(c->origfp, B_WR)); ap_proxy_cache_tidy(c); @@ -924,15 +919,11 @@ int ap_proxy_cache_check(request_rec *r, char *url, struct cache_conf *conf, cache_req **cr) { - char hashfile[66]; - const char *datestr, *pragma_req = NULL, *pragma_cresp = NULL; - const char *etag = NULL, *wetag = NULL, *cc_req = NULL, *cc_cresp = NULL; - const char *vary = NULL, *ifmatch = NULL, *ifnonematch = NULL; - const char *imstr, *pragma, *auth; + const char *datestr, *pragma_req = NULL, *pragma_cresp = NULL, *cc_req = NULL, *cc_cresp = NULL, *vary = NULL; cache_req *c; time_t now; BUFF *cachefp; - int cfd, i; + int i; void *sconf = r->server->module_config; proxy_server_conf *pconf = (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module); @@ -954,13 +945,14 @@ 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); -/* get the If-Modified-Since date of the request */ - 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"); } @@ -983,8 +975,9 @@ c->inm = ap_table_get(r->headers_in, "If-None-Match"); /* find the filename for this cache entry */ - ap_proxy_hash(url, hashfile, pconf->cache.dirlevels, pconf->cache.dirlength); 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 { @@ -1024,14 +1017,16 @@ /* if the cache file exists, open it */ cachefp = NULL; + Explain3("Request for %s, pragma_req=%s, ims=%ld", url, + pragma_req, c->ims); /* find out about whether the request can access the cache */ - Explain5("Request for %s, pragma_req=%s, auth=%s, ims=%ld, imstr=%s", url, - pragma_req, auth, c->ims, imstr); 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) @@ -1049,7 +1044,7 @@ cc_cresp = ap_table_get(c->hdrs, "Cache-Control"); pragma_cresp = ap_table_get(c->hdrs, "Pragma"); vary = ap_table_get(c->hdrs, "Vary"); - if (agestr = ap_table_get(c->hdrs, "Age")) { + if ((agestr = ap_table_get(c->hdrs, "Age"))) { age_c = atoi(agestr); } } @@ -1064,8 +1059,6 @@ */ /* 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 @@ -1080,8 +1073,6 @@ */ if (c->hdrs && c->req_hdrs) { char *vary = ap_pstrdup(r->pool, ap_table_get(c->hdrs, "Vary")); - char *p; - int i; while (vary && *vary) { char *name = vary; @@ -1111,7 +1102,6 @@ c->fp = cachefp; Explain0("Vary header mismatch - object must be fetched from scratch. Declining."); return DECLINED; - } } } @@ -1305,18 +1295,13 @@ #endif request_rec *r = c->req; char *p; - int i; const char *expire, *lmods, *dates, *clen; time_t expc, date, lmod, now; char buff[17*7+1]; void *sconf = r->server->module_config; proxy_server_conf *conf = (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module); - const long int zero = 0L; const char *cc_resp; - off_t orig_clen; - /* buffer to store response headers */ - char *hdr_buff[HUGE_STRING_LEN]; table *req_hdrs; cc_resp = ap_table_get(resp_hdrs, "Cache-Control"); @@ -1411,9 +1396,6 @@ } - - - /* It's safe to cache the response. * * We now want to update the cache file header information with @@ -1495,8 +1477,7 @@ else c->len = atoi(clen); -/* we have all the header information we need - write it to the cache file - */ +/* 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] = ' '; @@ -1565,8 +1546,6 @@ } while (1) { - struct tbl_do_args tdo; - /* create temporary filename */ #ifndef TPF #define TMPFILESTR "/tmpXXXXXX" @@ -1622,12 +1601,10 @@ ap_proxy_clear_connection(r->pool, req_hdrs); /* save original request headers */ - tdo.req = NULL; - tdo.cache = c; if (c->req_hdrs) - ap_table_do(ap_proxy_send_hdr_line, &tdo, c->req_hdrs, NULL); + ap_table_do(ap_proxy_send_hdr_line, c, c->req_hdrs, NULL); else - ap_table_do(ap_proxy_send_hdr_line, &tdo, r->headers_in, NULL); + 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); 1.2 +15 -31 httpd-proxy/module-1.0/proxy_ftp.c Index: proxy_ftp.c =================================================================== RCS file: /home/cvs/httpd-proxy/module-1.0/proxy_ftp.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- proxy_ftp.c 2001/06/07 19:50:58 1.1 +++ proxy_ftp.c 2001/06/08 07:39:07 1.2 @@ -461,9 +461,7 @@ BUFF *data = NULL; pool *p = r->pool; int one = 1; - const long int zero = 0L; NET_SIZE_T clen; - struct tbl_do_args tdo; void *sconf = r->server->module_config; proxy_server_conf *conf = @@ -1208,37 +1206,23 @@ ap_bpushfd(data, dsock, dsock); } - ap_hard_timeout("proxy receive", r); - /* send response */ - /* write status line */ - if (!r->assbackwards) - ap_rvputs(r, "HTTP/1.1 ", r->status_line, CRLF, NULL); - if (c != NULL && c->fp != NULL - && ap_bvputs(c->fp, "HTTP/1.1 ", r->status_line, CRLF, NULL) == -1) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, c->req, - "proxy: error writing CRLF to %s", c->tempfile); - c = ap_proxy_cache_error(c); - } - - /* we don't yet support keepalives */ - ap_rputs("Connection: close" CRLF, r); - - /* send headers */ - tdo.req = r; - tdo.cache = c; - ap_table_do(ap_proxy_send_hdr_line, &tdo, resp_hdrs, NULL); - - if (!r->assbackwards) - ap_rputs(CRLF, r); - if (c != NULL && c->fp != NULL && ap_bputs(CRLF, c->fp) == -1) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, c->req, - "proxy: error writing CRLF to %s", c->tempfile); - c = ap_proxy_cache_error(c); - } + /* write status line and headers to the cache file */ + ap_proxy_write_headers(c, ap_pstrcat(p, "HTTP/1.1 ", r->status_line, NULL), resp_hdrs); + + /* Setup the headers for our client from upstreams response-headers */ + ap_overlap_tables(r->headers_out, resp_hdrs, AP_OVERLAP_TABLES_SET); + /* Add X-Cache header */ + ap_table_setn(r->headers_out, "X-Cache", + ap_pstrcat(r->pool, "MISS from ", + ap_get_server_name(r), NULL)); + /* The Content-Type of this response is the upstream one. */ + r->content_type = ap_table_get (r->headers_out, "Content-Type"); + /* finally output the headers to the client */ + ap_send_http_header(r); + + ap_hard_timeout("proxy receive", r); - ap_bsetopt(r->connection->client, BO_BYTECT, &zero); - r->sent_bodyct = 1; /* send body */ if (!r->header_only) { if (parms[0] != 'd') { 1.2 +50 -34 httpd-proxy/module-1.0/proxy_http.c Index: proxy_http.c =================================================================== RCS file: /home/cvs/httpd-proxy/module-1.0/proxy_http.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- proxy_http.c 2001/06/07 19:50:58 1.1 +++ proxy_http.c 2001/06/08 07:39:08 1.2 @@ -152,9 +152,9 @@ char *strp2; const char *err, *desthost; int i, j, sock, len, backasswards; + table *req_hdrs, *resp_hdrs; array_header *reqhdrs_arr; - table *resp_hdrs; - table_entry *reqhdrs; + table_entry *reqhdrs_elts; struct sockaddr_in server; struct in_addr destaddr; struct hostent server_hp; @@ -162,12 +162,10 @@ char buffer[HUGE_STRING_LEN]; char portstr[32]; pool *p = r->pool; - const long int zero = 0L; int destport = 0; char *destportstr = NULL; const char *urlptr = NULL; const char *datestr, *urlstr; - struct tbl_do_args tdo; void *sconf = r->server->module_config; proxy_server_conf *conf = @@ -175,8 +173,9 @@ struct noproxy_entry *npent = (struct noproxy_entry *) conf->noproxies->elts; struct nocache_entry *ncent = (struct nocache_entry *) conf->nocaches->elts; int nocache = 0; - char *xcache = NULL; + if (conf->cache.root == NULL) nocache = 1; + memset(&server, '\0', sizeof(server)); server.sin_family = AF_INET; @@ -287,10 +286,14 @@ /* record request_time for HTTP/1.1 age calculation */ c->req_time = time(NULL); - - /* strip hop-by-hop headers from the request */ - ap_proxy_clear_connection(r->pool, r->headers_in); + /* build upstream-request headers by stripping r->headers_in from + * connection specific headers. + * We must not remove the Connection: header from r->headers_in, + * we still have to react to Connection: close + */ + req_hdrs = ap_copy_table(r->pool, r->headers_in); + ap_proxy_clear_connection(r->pool, req_hdrs); /* At this point, we start sending the HTTP/1.1 request to the * remote server (proxy or otherwise). @@ -301,6 +304,7 @@ ap_hard_timeout("proxy send", r); ap_bvputs(f, r->method, " ", proxyhost ? url : urlptr, " HTTP/1.0" CRLF, NULL); + /* Send Host: now, adding it to req_hdrs wouldn't be much better */ if (destportstr != NULL && destport != DEFAULT_HTTP_PORT) ap_bvputs(f, "Host: ", desthost, ":", destportstr, CRLF, NULL); else @@ -308,7 +312,7 @@ if (conf->viaopt == via_block) { /* Block all outgoing Via: headers */ - ap_table_unset(r->headers_in, "Via"); + ap_table_unset(req_hdrs, "Via"); } else if (conf->viaopt != via_off) { /* Create a "Via:" request header entry and merge it */ i = ap_get_server_port(r); @@ -318,7 +322,7 @@ ap_snprintf(portstr, sizeof portstr, ":%d", i); } /* Generate outgoing Via: header with/without server comment: */ - ap_table_mergen(r->headers_in, "Via", + ap_table_mergen(req_hdrs, "Via", (conf->viaopt == via_full) ? ap_psprintf(p, "%d.%d %s%s (%s)", HTTP_VERSION_MAJOR(r->proto_num), @@ -332,23 +336,27 @@ ); } + /* Add X-Forwarded-For: so that the upstream has a chance to + determine, where the original request came from. */ + ap_table_mergen(req_hdrs, "X-Forwarded-For", r->connection->remote_ip); + /* we don't yet support keepalives - but we will soon, I promise! */ - ap_bvputs(f, "Connection: close", CRLF, NULL); + ap_table_set(req_hdrs, "Connection", "close"); - reqhdrs_arr = ap_table_elts(r->headers_in); - reqhdrs = (table_entry *) reqhdrs_arr->elts; + reqhdrs_arr = ap_table_elts(req_hdrs); + reqhdrs_elts = (table_entry *) reqhdrs_arr->elts; for (i = 0; i < reqhdrs_arr->nelts; i++) { - if (reqhdrs[i].key == NULL || reqhdrs[i].val == NULL + if (reqhdrs_elts[i].key == NULL || reqhdrs_elts[i].val == NULL /* Clear out hop-by-hop request headers not to send: * RFC2616 13.5.1 says we should strip these headers: */ - || !strcasecmp(reqhdrs[i].key, "Host") /* Already sent */ - || !strcasecmp(reqhdrs[i].key, "Keep-Alive") - || !strcasecmp(reqhdrs[i].key, "TE") - || !strcasecmp(reqhdrs[i].key, "Trailer") - || !strcasecmp(reqhdrs[i].key, "Transfer-Encoding") - || !strcasecmp(reqhdrs[i].key, "Upgrade") + || !strcasecmp(reqhdrs_elts[i].key, "Host") /* Already sent */ + || !strcasecmp(reqhdrs_elts[i].key, "Keep-Alive") + || !strcasecmp(reqhdrs_elts[i].key, "TE") + || !strcasecmp(reqhdrs_elts[i].key, "Trailer") + || !strcasecmp(reqhdrs_elts[i].key, "Transfer-Encoding") + || !strcasecmp(reqhdrs_elts[i].key, "Upgrade") /* XXX: @@@ FIXME: "Proxy-Authorization" should *only* be * suppressed if THIS server requested the authentication, @@ -359,9 +367,9 @@ * code itself, not here. This saves us having to signal * somehow whether this request was authenticated or not. */ - || !strcasecmp(reqhdrs[i].key, "Proxy-Authorization")) + || !strcasecmp(reqhdrs_elts[i].key, "Proxy-Authorization")) continue; - ap_bvputs(f, reqhdrs[i].key, ": ", reqhdrs[i].val, CRLF, NULL); + ap_bvputs(f, reqhdrs_elts[i].key, ": ", reqhdrs_elts[i].val, CRLF, NULL); } /* the obligatory empty line to mark the end of the headers */ @@ -377,7 +385,6 @@ /* Right - now it's time to listen for a response. - * */ ap_hard_timeout("proxy receive", r); @@ -502,38 +509,47 @@ break; } } - } /* update the cache file, possibly even fulfilling the request if * it turns out a conditional allowed us to serve the object from the * cache... */ - i = ap_proxy_cache_update(c, resp_hdrs, !backasswards, nocache); if (i != DECLINED) { ap_bclose(f); return i; } - ap_hard_timeout("proxy receive", r); + /* write status line and headers to the cache file */ + ap_proxy_write_headers(c, ap_pstrcat(p, "HTTP/1.1 ", r->status_line, NULL), resp_hdrs); + } + + /* Setup the headers for our client from upstreams response-headers */ + ap_overlap_tables(r->headers_out, resp_hdrs, AP_OVERLAP_TABLES_SET); + /* Add X-Cache header */ + ap_table_setn(r->headers_out, "X-Cache", + ap_pstrcat(r->pool, "MISS from ", + ap_get_server_name(r), NULL)); + /* The Content-Type of this response is the upstream one. */ + r->content_type = ap_table_get (r->headers_out, "Content-Type"); + Explain1("Content-Type: %s", r->content_type); + /* finally output the headers to the client */ + ap_send_http_header(r); - /* write status line and headers */ - xcache = ap_pstrcat(r->pool, "MISS from ", ap_get_server_name(r), NULL); - ap_proxy_send_headers(r, c, ap_pstrcat(p, "HTTP/1.1 ", r->status_line, NULL), xcache, resp_hdrs); - - ap_bsetopt(r->connection->client, BO_BYTECT, &zero); - r->sent_bodyct = 1; - /* Is it an HTTP/0.9 respose? If so, send the extra data */ + /* Is it an HTTP/0.9 respose? If so, send the extra data we read + from upstream as the start of the reponse to client */ if (backasswards) { + ap_hard_timeout("proxy send assbackward", r); + ap_bwrite(r->connection->client, buffer, len); if (c != NULL && c->fp != NULL && ap_bwrite(c->fp, buffer, len) != len) { ap_log_rerror(APLOG_MARK, APLOG_ERR, c->req, "proxy: error writing extra data to %s", c->tempfile); c = ap_proxy_cache_error(c); } + ap_kill_timeout(r); } - ap_kill_timeout(r); #ifdef CHARSET_EBCDIC /* What we read/write after the header should not be modified 1.2 +25 -51 httpd-proxy/module-1.0/proxy_util.c Index: proxy_util.c =================================================================== RCS file: /home/cvs/httpd-proxy/module-1.0/proxy_util.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- proxy_util.c 2001/06/07 19:50:58 1.1 +++ proxy_util.c 2001/06/08 07:39:10 1.2 @@ -571,10 +571,10 @@ } break; } - total_bytes_rcvd += n; if (n == 0) break; /* EOF */ o = 0; + total_bytes_rcvd += n; /* Write to cache first. */ /*@@@ XXX FIXME: Assuming that writing the cache file won't time out?!!? */ @@ -638,50 +638,30 @@ } /* - * Sends response line and headers. Uses the client fd and the - * headers_out array from the passed request_rec to talk to the client - * and to properly set the headers it sends for things such as logging. - * - * If respline is NULL, no response line will be sent. - * If c is NULL, headers won't be written to cache. - * If r is NULL, headers won't be written to client. + * Writes response line and headers to the cache file. * - * A timeout should be set before calling this routine. + * If respline is NULL, no response line will be written. */ -void ap_proxy_send_headers(request_rec *r, cache_req *c, const char *respline, const char *xcache, table *t) +void ap_proxy_write_headers(cache_req *c, const char *respline, table *t) { - struct tbl_do_args tdo; - /* write status line */ - if (respline) { - if (r && !r->assbackwards) - ap_rvputs(r, respline, CRLF, NULL); - if (c && c->fp && ap_bvputs(c->fp, respline, CRLF, NULL) == -1) { + if (respline && c->fp != NULL && + ap_bvputs(c->fp, respline, CRLF, NULL) == -1) { ap_log_rerror(APLOG_MARK, APLOG_ERR, c->req, "proxy: error writing status line to %s", c->tempfile); c = ap_proxy_cache_error(c); + return; } - } - /* send response headers to client */ - tdo.req = r; - tdo.cache = c; - ap_table_do(ap_proxy_send_hdr_line, &tdo, t, NULL); - - /* send X-Cache to client */ - if (r && xcache) { - ap_rvputs(r, "X-Cache: ", xcache, CRLF, NULL); - } + /* write response headers to the cache file */ + ap_table_do(ap_proxy_send_hdr_line, c, t, NULL); - /* send terminating CRLF */ - if (r && !r->assbackwards) - ap_rputs(CRLF, r); - if (c != NULL && c->fp != NULL && ap_bputs(CRLF, c->fp) == -1) { + /* write terminating CRLF */ + if (c->fp != NULL && ap_bputs(CRLF, c->fp) == -1) { ap_log_rerror(APLOG_MARK, APLOG_ERR, c->req, "proxy: error writing CRLF to %s", c->tempfile); c = ap_proxy_cache_error(c); } - } @@ -1326,24 +1306,20 @@ /* This function is called by ap_table_do() for all header lines * (from proxy_http.c and proxy_ftp.c) - * It is passed a table_do_args struct pointer and a MIME field and value pair - * This function does not cache certain headers defined by RFC2616 */ + * It is passed a cache_req struct pointer and a MIME field and value pair + */ int ap_proxy_send_hdr_line(void *p, const char *key, const char *value) { - struct tbl_do_args *parm = (struct tbl_do_args *)p; + cache_req *c = (cache_req *)p; if (key == NULL || value == NULL || value[0] == '\0') return 1; - if (parm->req && !parm->req->assbackwards) { - ap_rvputs(parm->req, key, ": ", value, CRLF, NULL); -/* CHECKME: Do we need to create the headers_out table first? */ - ap_table_addn(parm->req->headers_out, key, value); - } - if (parm->cache != NULL && parm->cache->fp != NULL && - ap_bvputs(parm->cache->fp, key, ": ", value, CRLF, NULL) == -1) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, parm->cache->req, - "proxy: error writing header to %s", parm->cache->tempfile); - parm->cache = ap_proxy_cache_error(parm->cache); + if (c->fp != NULL && + ap_bvputs(c->fp, key, ": ", value, CRLF, NULL) == -1) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, c->req, + "proxy: error writing header to %s", c->tempfile); + c = ap_proxy_cache_error(c); + return 0; /* no need to continue, it failed already */ } return 1; /* tell ap_table_do() to continue calling us for more headers */ } @@ -1421,7 +1397,7 @@ return cachefp; } -/* Clear all connection-based headers from the incoming headers table */ +/* Clear all connection-based headers from headers table */ void ap_proxy_clear_connection(pool *p, table *headers) { const char *name; @@ -1446,7 +1422,7 @@ /* XXX: if you tweak this you should look at is_empty_table() and table_elts() * in ap_alloc.h - * + * * NOTE: this private definition is a duplicate of the one in alloc.c * It's here for ap_proxy_table_replace() to avoid breaking binary compat */ @@ -1460,12 +1436,10 @@ #ifdef MAKE_TABLE_PROFILE void *creator; #endif -}; +}; -/* - * overlay one table on another - * keys in base will be replaced by keys in overlay - */ +/* overlay one table on another - keys in base will be replaced by keys in overl +ay */ int ap_proxy_table_replace(table *base, table *overlay) { table_entry *elts = (table_entry *) overlay->a.elts;