Return-Path: Delivered-To: apmail-apache-cvs-archive@apache.org Received: (qmail 23923 invoked by uid 500); 11 Nov 2000 11:06:16 -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 23898 invoked by uid 500); 11 Nov 2000 11:06:15 -0000 Delivered-To: apmail-apache-2.0-cvs@apache.org Date: 11 Nov 2000 11:06:15 -0000 Message-ID: <20001111110615.23894.qmail@locus.apache.org> From: chuck@locus.apache.org To: apache-2.0-cvs@apache.org Subject: cvs commit: apache-2.0/src/modules/proxy proxy_http.c chuck 00/11/11 03:06:13 Modified: src/modules/proxy proxy_http.c Log: This is the 1.3.x current proxy into 2.0 - first stage Obtained from: Sam Magnuson Submitted by: Chuck Murcko Revision Changes Path 1.17 +171 -166 apache-2.0/src/modules/proxy/proxy_http.c Index: proxy_http.c =================================================================== RCS file: /home/cvs/apache-2.0/src/modules/proxy/proxy_http.c,v retrieving revision 1.16 retrieving revision 1.17 diff -u -r1.16 -r1.17 --- proxy_http.c 2000/10/08 03:23:05 1.16 +++ proxy_http.c 2000/11/11 11:06:12 1.17 @@ -58,7 +58,6 @@ /* HTTP routines for Apache proxy */ -#include "apr_strings.h" #include "mod_proxy.h" #include "http_log.h" #include "http_main.h" @@ -83,7 +82,7 @@ port = def_port; err = ap_proxy_canon_netloc(r->pool, &url, NULL, NULL, &host, &port); if (err) - return HTTP_BAD_REQUEST; + return HTTP_BAD_REQUEST; /* now parse path/search args, according to rfc1738 */ /* N.B. if this isn't a true proxy request, then the URL _path_ @@ -91,25 +90,25 @@ * == r->unparsed_uri, and no others have that property. */ if (r->uri == r->unparsed_uri) { - search = strchr(url, '?'); - if (search != NULL) - *(search++) = '\0'; + search = strchr(url, '?'); + if (search != NULL) + *(search++) = '\0'; } else - search = r->args; + search = r->args; /* process path */ path = ap_proxy_canonenc(r->pool, url, strlen(url), enc_path, r->proxyreq); if (path == NULL) - return HTTP_BAD_REQUEST; + return HTTP_BAD_REQUEST; if (port != def_port) - apr_snprintf(sport, sizeof(sport), ":%d", port); + apr_snprintf(sport, sizeof(sport), ":%d", port); else - sport[0] = '\0'; + sport[0] = '\0'; r->filename = apr_pstrcat(r->pool, "proxy:", scheme, "://", host, sport, "/", - path, (search) ? "?" : "", (search) ? search : "", NULL); + path, (search) ? "?" : "", (search) ? search : "", NULL); return OK; } @@ -135,7 +134,7 @@ return url; } -/* Clear all connection-based headers from the incoming headers apr_table_t */ +/* Clear all connection-based headers from the incoming headers table */ static void clear_connection(apr_pool_t *p, apr_table_t *headers) { const char *name; @@ -143,17 +142,17 @@ apr_table_unset(headers, "Proxy-Connection"); if (!next) - return; + return; while (*next) { - name = next; - while (*next && !apr_isspace(*next) && (*next != ',')) - ++next; - while (*next && (apr_isspace(*next) || (*next == ','))) { - *next = '\0'; - ++next; - } - apr_table_unset(headers, name); + name = next; + while (*next && !apr_isspace(*next) && (*next != ',')) + ++next; + while (*next && (apr_isspace(*next) || (*next == ','))) { + *next = '\0'; + ++next; + } + apr_table_unset(headers, name); } apr_table_unset(headers, "Connection"); } @@ -167,34 +166,34 @@ * we return DECLINED so that we can try another proxy. (Or the direct * route.) */ -int ap_proxy_http_handler(request_rec *r, ap_cache_el *c, char *url, - const char *proxyhost, int proxyport) +int ap_proxy_http_handler(request_rec *r, ap_cache_el *c, char *url, + const char *proxyhost, int proxyport) { const char *strp; char *strp2; char *desthost; apr_socket_t *sock; - int i, len, backasswards, content_length=-1; + int i, len, backasswards, content_length = -1; apr_array_header_t *reqhdrs_arr; - apr_table_t *resp_hdrs=NULL; + apr_table_t *resp_hdrs = NULL; apr_table_entry_t *reqhdrs; struct sockaddr_in server; struct in_addr destaddr; BUFF *f; - apr_file_t *cachefp=NULL; char buffer[HUGE_STRING_LEN]; char portstr[32]; apr_pool_t *p = r->pool; const long int zero = 0L; int destport = 0; - apr_ssize_t cntr; char *destportstr = NULL; const char *urlptr = NULL; char *datestr, *clen; + apr_ssize_t cntr; + apr_file_t *cachefp = NULL; void *sconf = r->server->module_config; proxy_server_conf *conf = - (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module); + (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module); struct noproxy_entry *npent = (struct noproxy_entry *) conf->noproxies->elts; struct nocache_entry *ncent = (struct nocache_entry *) conf->nocaches->elts; int nocache = 0; @@ -206,38 +205,40 @@ urlptr = strstr(url, "://"); if (urlptr == NULL) - return HTTP_BAD_REQUEST; + return HTTP_BAD_REQUEST; urlptr += 3; destport = DEFAULT_HTTP_PORT; strp = ap_strchr_c(urlptr, '/'); if (strp == NULL) { - desthost = apr_pstrdup(p, urlptr); - urlptr = "/"; + desthost = apr_pstrdup(p, urlptr); + urlptr = "/"; } else { - char *q = apr_palloc(p, strp - urlptr + 1); - memcpy(q, urlptr, strp - urlptr); - q[strp - urlptr] = '\0'; - urlptr = strp; - desthost = q; + char *q = apr_palloc(p, strp - urlptr + 1); + memcpy(q, urlptr, strp - urlptr); + q[strp - urlptr] = '\0'; + urlptr = strp; + desthost = q; } strp2 = ap_strchr(desthost, ':'); if (strp2 != NULL) { - *(strp2++) = '\0'; - if (apr_isdigit(*strp2)) { - destport = atoi(strp2); - destportstr = strp2; - } + *(strp2++) = '\0'; + if (apr_isdigit(*strp2)) { + destport = atoi(strp2); + destportstr = strp2; + } } /* check if ProxyBlock directive on this host */ destaddr.s_addr = apr_inet_addr(desthost); for (i = 0; i < conf->noproxies->nelts; i++) { - if ((npent[i].name != NULL && ap_strstr_c(desthost, npent[i].name) != NULL) - || destaddr.s_addr == npent[i].addr.s_addr || npent[i].name[0] == '*') - return ap_proxyerror(r, HTTP_FORBIDDEN, - "Connect to remote machine blocked"); + if ((npent[i].name != NULL + && ap_strstr_c(desthost, npent[i].name) != NULL) + || destaddr.s_addr == npent[i].addr.s_addr + || npent[i].name[0] == '*') + return ap_proxyerror(r, HTTP_FORBIDDEN, + "Connect to remote machine blocked"); } if ((apr_create_tcp_socket(&sock, r->pool)) != APR_SUCCESS) { @@ -246,11 +247,14 @@ return HTTP_INTERNAL_SERVER_ERROR; } - if (conf->recv_buffer_size > 0 && apr_setsocketopt(sock, APR_SO_RCVBUF,conf->recv_buffer_size)) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, - "setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default"); +#if !defined(TPF) && !defined(BEOS) + if (conf->recv_buffer_size > 0 && apr_setsocketopt(sock, APR_SO_RCVBUF, + conf->recv_buffer_size)) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default"); } - +#endif + if (proxyhost != NULL) { i = ap_proxy_doconnect(sock, (char *)proxyhost, proxyport, r); } @@ -259,147 +263,148 @@ } if (i == -1) { - if (proxyhost != NULL) - return DECLINED; /* try again another way */ - else - return ap_proxyerror(r, HTTP_BAD_GATEWAY, - apr_pstrcat(r->pool, "Could not connect to remote machine: ", - strerror(errno), NULL)); + if (proxyhost != NULL) + return DECLINED; /* try again another way */ + else + return ap_proxyerror(r, HTTP_BAD_GATEWAY, apr_pstrcat(r->pool, + "Could not connect to remote machine: ", + strerror(errno), NULL)); } - clear_connection(r->pool, r->headers_in); /* Strip connection-based headers */ + clear_connection(r->pool, r->headers_in); /* Strip connection-based headers */ f = ap_bcreate(p, B_RDWR); ap_bpush_socket(f, sock); ap_bvputs(f, r->method, " ", proxyhost ? url : urlptr, " HTTP/1.0" CRLF, - NULL); + NULL); if (destportstr != NULL && destport != DEFAULT_HTTP_PORT) - ap_bvputs(f, "Host: ", desthost, ":", destportstr, CRLF, NULL); + ap_bvputs(f, "Host: ", desthost, ":", destportstr, CRLF, NULL); else - ap_bvputs(f, "Host: ", desthost, CRLF, NULL); + ap_bvputs(f, "Host: ", desthost, CRLF, NULL); if (conf->viaopt == via_block) { - /* Block all outgoing Via: headers */ - apr_table_unset(r->headers_in, "Via"); + /* Block all outgoing Via: headers */ + apr_table_unset(r->headers_in, "Via"); } else if (conf->viaopt != via_off) { - /* Create a "Via:" request header entry and merge it */ - i = ap_get_server_port(r); - if (ap_is_default_port(i,r)) { - strcpy(portstr,""); - } else { - apr_snprintf(portstr, sizeof portstr, ":%d", i); - } - /* Generate outgoing Via: header with/without server comment: */ - apr_table_mergen(r->headers_in, "Via", - (conf->viaopt == via_full) - ? apr_psprintf(p, "%d.%d %s%s (%s)", - HTTP_VERSION_MAJOR(r->proto_num), - HTTP_VERSION_MINOR(r->proto_num), - ap_get_server_name(r), portstr, - AP_SERVER_BASEVERSION) - : apr_psprintf(p, "%d.%d %s%s", - HTTP_VERSION_MAJOR(r->proto_num), - HTTP_VERSION_MINOR(r->proto_num), - ap_get_server_name(r), portstr) - ); + /* Create a "Via:" request header entry and merge it */ + i = ap_get_server_port(r); + if (ap_is_default_port(i,r)) { + strcpy(portstr,""); + } else { + apr_snprintf(portstr, sizeof portstr, ":%d", i); + } + /* Generate outgoing Via: header with/without server comment: */ + ap_table_mergen(r->headers_in, "Via", + (conf->viaopt == via_full) + ? apr_psprintf(p, "%d.%d %s%s (%s)", + HTTP_VERSION_MAJOR(r->proto_num), + HTTP_VERSION_MINOR(r->proto_num), + ap_get_server_name(r), portstr, + AP_SERVER_BASEVERSION) + : apr_psprintf(p, "%d.%d %s%s", + HTTP_VERSION_MAJOR(r->proto_num), + HTTP_VERSION_MINOR(r->proto_num), + ap_get_server_name(r), portstr) + ); } reqhdrs_arr = apr_table_elts(r->headers_in); reqhdrs = (apr_table_entry_t *) reqhdrs_arr->elts; for (i = 0; i < reqhdrs_arr->nelts; i++) { - if (reqhdrs[i].key == NULL || reqhdrs[i].val == NULL - /* Clear out headers not to send */ - || !strcasecmp(reqhdrs[i].key, "Host") /* Already sent */ - /* XXX: @@@ FIXME: "Proxy-Authorization" should *only* be - * suppressed if THIS server requested the authentication, - * not when a frontend proxy requested it! - */ - || !strcasecmp(reqhdrs[i].key, "Proxy-Authorization")) - continue; - ap_bvputs(f, reqhdrs[i].key, ": ", reqhdrs[i].val, CRLF, NULL); + if (reqhdrs[i].key == NULL || reqhdrs[i].val == NULL + /* Clear out headers not to send */ + || !strcasecmp(reqhdrs[i].key, "Host") /* Already sent */ + /* XXX: @@@ FIXME: "Proxy-Authorization" should *only* be + * suppressed if THIS server requested the authentication, + * not when a frontend proxy requested it! + */ + || !strcasecmp(reqhdrs[i].key, "Proxy-Authorization")) + continue; + ap_bvputs(f, reqhdrs[i].key, ": ", reqhdrs[i].val, CRLF, NULL); } ap_bputs(CRLF, f); /* send the request data, if any. */ if (ap_should_client_block(r)) { - while ((i = ap_get_client_block(r, buffer, sizeof buffer)) > 0) - ap_bwrite(f, buffer, i, &cntr); + while ((i = ap_get_client_block(r, buffer, sizeof buffer)) > 0) + ap_bwrite(f, buffer, i, &cntr); } ap_bflush(f); len = ap_bgets(buffer, sizeof buffer - 1, f); if (len == -1) { - ap_bclose(f); - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, - "ap_bgets() - proxy receive - Error reading from remote server %s (length %d)", - proxyhost ? proxyhost : desthost, len); - return ap_proxyerror(r, HTTP_BAD_GATEWAY, - "Error reading from remote server"); + ap_bclose(f); + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "ap_bgets() - proxy receive - Error reading from remote server %s (length %d)", + proxyhost ? proxyhost : desthost, len); + return ap_proxyerror(r, HTTP_BAD_GATEWAY, + "Error reading from remote server"); } else if (len == 0) { - ap_bclose(f); - return ap_proxyerror(r, HTTP_BAD_GATEWAY, - "Document contains no data"); + ap_bclose(f); + return ap_proxyerror(r, HTTP_BAD_GATEWAY, + "Document contains no data"); } /* Is it an HTTP/1 response? This is buggy if we ever see an HTTP/1.10 */ if (ap_checkmask(buffer, "HTTP/#.# ###*")) { - int major, minor; - if (2 != sscanf(buffer, "HTTP/%u.%u", &major, &minor)) { - major = 1; - minor = 0; - } + int major, minor; + if (2 != sscanf(buffer, "HTTP/%u.%u", &major, &minor)) { + major = 1; + minor = 0; + } /* If not an HTTP/1 message or if the status line was > 8192 bytes */ - if (buffer[5] != '1' || buffer[len - 1] != '\n') { - ap_bclose(f); - return HTTP_BAD_GATEWAY; - } - backasswards = 0; - buffer[--len] = '\0'; - - buffer[12] = '\0'; - r->status = atoi(&buffer[9]); - buffer[12] = ' '; - r->status_line = apr_pstrdup(p, &buffer[9]); + if (buffer[5] != '1' || buffer[len - 1] != '\n') { + ap_bclose(f); + return HTTP_BAD_GATEWAY; + } + backasswards = 0; + buffer[--len] = '\0'; + + buffer[12] = '\0'; + r->status = atoi(&buffer[9]); + buffer[12] = ' '; + r->status_line = apr_pstrdup(p, &buffer[9]); /* read the headers. */ /* N.B. for HTTP/1.0 clients, we have to fold line-wrapped headers */ /* Also, take care with headers with multiple occurences. */ - resp_hdrs = ap_proxy_read_headers(r, buffer, HUGE_STRING_LEN, f); - if (resp_hdrs == NULL) { - ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r->server, - "proxy: Bad HTTP/%d.%d header returned by %s (%s)", - major, minor, r->uri, r->method); - nocache = 1; /* do not cache this broken file */ - } + + resp_hdrs = ap_proxy_read_headers(r, buffer, HUGE_STRING_LEN, f); + if (resp_hdrs == NULL) { + ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r->server, + "proxy: Bad HTTP/%d.%d header returned by %s (%s)", + major, minor, r->uri, r->method); + nocache = 1; /* do not cache this broken file */ + } else { clear_connection(p, resp_hdrs); /* Strip Connection hdrs */ ap_cache_el_header_merge(c, resp_hdrs); } - - if (conf->viaopt != via_off && conf->viaopt != via_block) { - /* Create a "Via:" response header entry and merge it */ - i = ap_get_server_port(r); - if (ap_is_default_port(i,r)) { - strcpy(portstr,""); - } else { - apr_snprintf(portstr, sizeof portstr, ":%d", i); - } + + if (conf->viaopt != via_off && conf->viaopt != via_block) { + /* Create a "Via:" response header entry and merge it */ + i = ap_get_server_port(r); + if (ap_is_default_port(i,r)) { + strcpy(portstr,""); + } else { + apr_snprintf(portstr, sizeof portstr, ":%d", i); + } ap_cache_el_header_add(c, "Via", (conf->viaopt == via_full) - ? apr_psprintf(p, "%d.%d %s%s (%s)", major, minor, - ap_get_server_name(r), portstr, AP_SERVER_BASEVERSION) - : apr_psprintf(p, "%d.%d %s%s", major, minor, ap_get_server_name(r), portstr) - ); - } + ? apr_psprintf(p, "%d.%d %s%s (%s)", major, minor, + ap_get_server_name(r), portstr, AP_SERVER_BASEVERSION) + : apr_psprintf(p, "%d.%d %s%s", major, minor, + ap_get_server_name(r), portstr)); + } } else { /* an http/0.9 response */ - backasswards = 1; - r->status = 200; - r->status_line = "200 OK"; + backasswards = 1; + r->status = 200; + r->status_line = "200 OK"; } /* @@ -423,44 +428,44 @@ content_length = atoi(clen ? clen : "-1"); for (i = 0; i < conf->nocaches->nelts; i++) { - if ((ncent[i].name != NULL && ap_strstr_c(desthost, ncent[i].name) != NULL) - || destaddr.s_addr == ncent[i].addr.s_addr || ncent[i].name[0] == '*') - nocache = 1; + if ((ncent[i].name != NULL && ap_strstr_c(desthost, ncent[i].name) != NULL) + || destaddr.s_addr == ncent[i].addr.s_addr || ncent[i].name[0] == '*') + nocache = 1; } if(nocache || !ap_proxy_cache_should_cache(r, resp_hdrs, !backasswards)) ap_proxy_cache_error(&c); else ap_cache_el_data(c, &cachefp); - + /* write status line */ if (!r->assbackwards) - ap_rvputs(r, "HTTP/1.0 ", r->status_line, CRLF, NULL); - if (cachefp && apr_puts(apr_pstrcat(r->pool, "HTTP/1.0 ", r->status_line, CRLF, NULL), cachefp) != APR_SUCCESS) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, - "proxy: error writing status line to cache"); - ap_proxy_cache_error(&c); - cachefp = NULL; + ap_rvputs(r, "HTTP/1.0 ", r->status_line, CRLF, NULL); + if (cachefp && apr_puts(apr_pstrcat(r->pool, "HTTP/1.0 ", + r->status_line, CRLF, NULL), cachefp) != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "proxy: error writing status line to cache"); + ap_proxy_cache_error(&c); + cachefp = NULL; } /* send headers */ ap_cache_el_header_walk(c, ap_proxy_send_hdr_line, r, NULL); if (!r->assbackwards) - ap_rputs(CRLF, r); + ap_rputs(CRLF, r); 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 response? If so, send the extra data */ if (backasswards) { - ap_bwrite(r->connection->client, buffer, len, &cntr); + ap_bwrite(r->connection->client, buffer, len, &cntr); cntr = len; if (cachefp && apr_write(cachefp, buffer, &cntr) != APR_SUCCESS) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, - "proxy: error writing extra data to cache %ld", - (long)cachefp); - ap_proxy_cache_error(&c); - } + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "proxy: error writing extra data to cache"); + ap_proxy_cache_error(&c); + } } #ifdef CHARSET_EBCDIC @@ -471,14 +476,14 @@ ap_bsetflag(r->connection->client, B_ASCII2EBCDIC|B_EBCDIC2ASCII, 0); #endif - /* send body */ - /* if header only, then cache will be NULL */ - /* HTTP/1.0 tells us to read to EOF, rather than content-length bytes */ + /* send body */ + /* if header only, then cache will be NULL */ + /* HTTP/1.0 tells us to read to EOF, rather than content-length bytes */ if (!r->header_only) { - proxy_completion pc; - pc.content_length = content_length; - pc.cache_completion = conf->cache_completion; - ap_proxy_send_fb(&pc, f, r, c); + proxy_completion pc; + pc.content_length = content_length; + pc.cache_completion = conf->cache_completion; + ap_proxy_send_fb(&pc, f, r, c); } ap_bclose(f);