]> granicus.if.org Git - apache/commitdiff
This removes all BUFF's from the HTTP proxy. This code is relatively
authorRyan Bloom <rbb@apache.org>
Fri, 17 Nov 2000 00:19:30 +0000 (00:19 +0000)
committerRyan Bloom <rbb@apache.org>
Fri, 17 Nov 2000 00:19:30 +0000 (00:19 +0000)
ugly, but it does proxy pages.  This even fixes the content-type bug
that I introduced yesterday sometime.  As soon as BUFF is removed from
the FTP proxy, the buff.c and buff.h files need to go away.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@86988 13f79535-47bb-0310-9956-ffa450edef68

include/http_protocol.h
modules/http/http_protocol.c
modules/proxy/mod_proxy.h
modules/proxy/proxy_http.c
modules/proxy/proxy_util.c

index b56c8225e7695bb07b4299350c271206f807df4b..b7a33d97c01a04f7a6756ade1f77a24a8b851d3c 100644 (file)
@@ -496,6 +496,8 @@ void ap_finalize_sub_req_protocol(request_rec *sub_r);
  */
 AP_CORE_DECLARE(void) ap_parse_uri(request_rec *r, const char *uri);
 
+AP_CORE_DECLARE(int) ap_getline(char *s, int n, request_rec *r, int fold);
+
 /**
  * Get the method number associated with the given string, assumed to
  * contain an HTTP method.  Returns M_INVALID if not recognized.
index 9b359b6e3a224c8b6ebdb2abe443898060918b23..e7f1d357282133755627c42cfe1ec902986b96dc 100644 (file)
@@ -818,7 +818,6 @@ struct dechunk_ctx {
 };
 
 static long get_chunk_size(char *);
-static int getline(char *s, int n, request_rec *r, int fold);
 
 apr_status_t ap_dechunk_filter(ap_filter_t *f, ap_bucket_brigade *bb,
                                ap_input_mode_t mode)
@@ -841,7 +840,7 @@ apr_status_t ap_dechunk_filter(ap_filter_t *f, ap_bucket_brigade *bb,
              */
             char line[30];
             
-            if ((rv = getline(line, sizeof(line), f->r, 0)) < 0) {
+            if ((rv = ap_getline(line, sizeof(line), f->r, 0)) < 0) {
                 return rv;
             }
             switch(ctx->state) {
@@ -1028,7 +1027,7 @@ apr_status_t ap_http_filter(ap_filter_t *f, ap_bucket_brigade *b, ap_input_mode_
  *        If no LF is detected on the last line due to a dropped connection 
  *        or a full buffer, that's considered an error.
  */
-static int getline(char *s, int n, request_rec *r, int fold)
+int ap_getline(char *s, int n, request_rec *r, int fold)
 {
     char *pos = s;
     char *last_char;
@@ -1224,7 +1223,7 @@ static int read_request_line(request_rec *r)
     ap_bsetflag(conn->client, B_SAFEREAD, 1); 
     ap_bflush(conn->client);
 #endif
-    while ((len = getline(l, sizeof(l), r, 0)) <= 0) {
+    while ((len = ap_getline(l, sizeof(l), r, 0)) <= 0) {
         if (len < 0) {             /* includes EOF */
 #if 0
     /* XXX: I am 99% sure that these are already taken care of, but I want to
@@ -1276,7 +1275,7 @@ static int read_request_line(request_rec *r)
 
     ap_parse_uri(r, uri);
 
-    /* getline returns (size of max buffer - 1) if it fills up the
+    /* ap_getline returns (size of max buffer - 1) if it fills up the
      * buffer before finding the end-of-line.  This is only going to
      * happen if it exceeds the configured limit for a request-line.
      */
@@ -1316,7 +1315,7 @@ static void get_mime_headers(request_rec *r)
      * Read header lines until we get the empty separator line, a read error,
      * the connection closes (EOF), reach the server limit, or we timeout.
      */
-    while ((len = getline(field, sizeof(field), r, 1)) > 0) {
+    while ((len = ap_getline(field, sizeof(field), r, 1)) > 0) {
 
         if (r->server->limit_req_fields &&
             (++fields_read > r->server->limit_req_fields)) {
@@ -1326,7 +1325,7 @@ static void get_mime_headers(request_rec *r)
                           "this server's limit.<P>\n");
             return;
         }
-        /* getline returns (size of max buffer - 1) if it fills up the
+        /* ap_getline returns (size of max buffer - 1) if it fills up the
          * buffer before finding the end-of-line.  This is only going to
          * happen if it exceeds the configured limit for a field size.
          */
@@ -2683,7 +2682,7 @@ AP_DECLARE(int) ap_setup_client_block(request_rec *r, int read_policy)
 
 #ifdef AP_DEBUG
     {
-        /* Make sure getline() didn't leave any droppings. */
+        /* Make sure ap_getline() didn't leave any droppings. */
         core_request_config *req_cfg = 
             (core_request_config *)ap_get_module_config(r->request_config,
                                                         &core_module);
index 5fde7e2bd04969f608e5c05fe1b9f0c99b15ec6a..a5de889595ab9223fb8d84b43058196f83ed8723 100644 (file)
@@ -255,7 +255,7 @@ char *ap_proxy_canonenc(apr_pool_t *p, const char *x, int len, enum enctype t,
 char *ap_proxy_canon_netloc(apr_pool_t *p, char **const urlp, char **userp,
                         char **passwordp, char **hostp, int *port);
 const char *ap_proxy_date_canon(apr_pool_t *p, const char *x);
-apr_table_t *ap_proxy_read_headers(request_rec *r, char *buffer, int size, BUFF *f);
+apr_table_t *ap_proxy_read_headers(request_rec *r, char *buffer, int size, conn_rec *c);
 long int ap_proxy_send_fb(proxy_completion *, BUFF *f, request_rec *r, ap_cache_el *c);
 void ap_proxy_send_headers(request_rec *r, const char *respline, apr_table_t *hdrs);
 int ap_proxy_liststr(const char *list, const char *val);
index c6a4481b2397b68f7bd396d3fe4d0bba657608d1..96652ea092b950449df397df83b4bd5b398f0c19 100644 (file)
 
 /* HTTP routines for Apache proxy */
 
+#define CORE_PRIVATE
+
 #include "mod_proxy.h"
 #include "http_log.h"
 #include "http_main.h"
 #include "http_core.h"
+#include "http_connection.h"
 #include "util_date.h"
 
 /*
@@ -180,11 +183,10 @@ int ap_proxy_http_handler(request_rec *r, ap_cache_el *c, char *url,
     apr_table_entry_t *reqhdrs;
     struct sockaddr_in server;
     struct in_addr destaddr;
-    BUFF *f;
     char buffer[HUGE_STRING_LEN];
+    char *buffer2;
     char portstr[32];
     apr_pool_t *p = r->pool;
-    const long int zero = 0L;
     int destport = 0;
     char *destportstr = NULL;
     const char *urlptr = NULL;
@@ -192,7 +194,9 @@ int ap_proxy_http_handler(request_rec *r, ap_cache_el *c, char *url,
     apr_ssize_t cntr;
     apr_file_t *cachefp = NULL;
     char *buf;
-    int rbb;
+    conn_rec *origin;
+    ap_bucket *e;
+    ap_bucket_brigade *bb = ap_brigade_create(r->pool);
 
     void *sconf = r->server->module_config;
     proxy_server_conf *conf =
@@ -274,24 +278,24 @@ int ap_proxy_http_handler(request_rec *r, ap_cache_el *c, char *url,
                                desthost, NULL));
     }
 
-    clear_connection(r->pool, r->headers_in);  /* Strip connection-based headers */
+    origin = ap_new_apr_connection(r->pool, r->server, sock, 0);
+    ap_add_output_filter("CORE", NULL, NULL, origin);
 
-    f = ap_bcreate(p, B_RDWR);
-    ap_bpush_socket(f, sock);
+    clear_connection(r->pool, r->headers_in);  /* Strip connection-based headers */
 
     buf = apr_pstrcat(r->pool, r->method, " ", proxyhost ? url : urlptr,
                       " HTTP/1.0" CRLF, NULL);
-    rbb = strlen(buf);
-    apr_send(sock, buf, &rbb);
+    e = ap_bucket_create_pool(buf, strlen(buf), r->pool);
+    AP_BRIGADE_INSERT_TAIL(bb, e);
     if (destportstr != NULL && destport != DEFAULT_HTTP_PORT) {
         buf = apr_pstrcat(r->pool, "Host: ", desthost, ":", destportstr, CRLF, NULL);
-        rbb = strlen(buf);
-        apr_send(sock, buf, &rbb);
+        e = ap_bucket_create_pool(buf, strlen(buf), r->pool);
+        AP_BRIGADE_INSERT_TAIL(bb, e);
     }
     else {
         buf = apr_pstrcat(r->pool, "Host: ", desthost, CRLF, NULL);
-        rbb = strlen(buf);
-        apr_send(sock, buf, &rbb);
+        e = ap_bucket_create_pool(buf, strlen(buf), r->pool);
+        AP_BRIGADE_INSERT_TAIL(bb, e);
     }
 
     if (conf->viaopt == via_block) {
@@ -333,67 +337,80 @@ int ap_proxy_http_handler(request_rec *r, ap_cache_el *c, char *url,
            || !strcasecmp(reqhdrs[i].key, "Proxy-Authorization"))
            continue;
         buf = apr_pstrcat(r->pool, reqhdrs[i].key, ": ", reqhdrs[i].val, CRLF, NULL);
-        rbb = strlen(buf);
-        apr_send(sock, buf, &rbb);
+        e = ap_bucket_create_pool(buf, strlen(buf), r->pool);
+        AP_BRIGADE_INSERT_TAIL(bb, e);
 
     }
 
-    rbb = strlen(CRLF);
-    apr_send(sock, CRLF, &rbb);
+    e = ap_bucket_create_pool(CRLF, strlen(CRLF), r->pool);
+    AP_BRIGADE_INSERT_TAIL(bb, e);
+    e = ap_bucket_create_flush();
+    AP_BRIGADE_INSERT_TAIL(bb, e);
+
+    ap_pass_brigade(origin->output_filters, bb);
 /* send the request data, if any. */
 
     if (ap_should_client_block(r)) {
        while ((i = ap_get_client_block(r, buffer, sizeof buffer)) > 0) {
-            cntr = i;
-            apr_send(sock, buffer, &cntr);
+            e = ap_bucket_create_pool(buffer, i, r->pool);
+            AP_BRIGADE_INSERT_TAIL(bb, e);
         }
     }
-#if 0  /* This doesn't make any sense until we convert the raw socket calls
-        * to filters.
-        */
-    ap_bflush(f);
-#endif
-
-    len = ap_bgets(buffer, sizeof buffer - 1, f);
+    /* Flush the data to the origin server */
+    e = ap_bucket_create_flush();
+    AP_BRIGADE_INSERT_TAIL(bb, e);
+    ap_pass_brigade(origin->output_filters, bb);
+
+    ap_add_input_filter("HTTP", NULL, NULL, origin);
+    ap_add_input_filter("CORE_IN", NULL, NULL, origin);
+
+    ap_brigade_destroy(bb);
+    bb = ap_brigade_create(r->pool);
+    
+    /* Tell http_filter to grab the data one line at a time. */
+    origin->remain = 0;
+
+    ap_get_brigade(origin->input_filters, bb, AP_MODE_BLOCKING);
+    ap_bucket_read(AP_BRIGADE_FIRST(bb), (const char **)&buffer2, &len, AP_BLOCK_READ);
     if (len == -1) {
-       ap_bclose(f);
+       apr_close_socket(sock);
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
-            "ap_bgets() - proxy receive - Error reading from remote server %s (length %d)",
+            "ap_get_brigade() - 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);
+       apr_close_socket(sock);
        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/#.# ###*")) {
+    if (ap_checkmask(buffer2, "HTTP/#.# ###*")) {
        int major, minor;
-       if (2 != sscanf(buffer, "HTTP/%u.%u", &major, &minor)) {
+       if (2 != sscanf(buffer2, "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);
+       if (buffer2[5] != '1' || buffer2[len - 1] != '\n') {
+           apr_close_socket(sock);
            return HTTP_BAD_GATEWAY;
        }
        backasswards = 0;
-       buffer[--len] = '\0';
+       buffer2[--len] = '\0';
 
-       buffer[12] = '\0';
-       r->status = atoi(&buffer[9]);
-       buffer[12] = ' ';
-       r->status_line = apr_pstrdup(p, &buffer[9]);
+       buffer2[12] = '\0';
+       r->status = atoi(&buffer2[9]);
+       buffer2[12] = ' ';
+       r->status_line = apr_pstrdup(p, &buffer2[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);
+       resp_hdrs = ap_proxy_read_headers(r, buffer, HUGE_STRING_LEN, origin);
        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)",
@@ -475,21 +492,17 @@ int ap_proxy_http_handler(request_rec *r, ap_cache_el *c, char *url,
 /* send headers */
     ap_cache_el_header_walk(c, ap_proxy_send_hdr_line, r, NULL);
 
-#if 0
     if (!r->assbackwards)
        ap_rputs(CRLF, r);
-#endif
 
-/* We don't set byte count this way anymore.  I think this can be removed
- * cleanly now.
-    ap_bsetopt(r->connection->client, BO_BYTECT, &zero);
-*/
     r->sent_bodyct = 1;
 /* Is it an HTTP/0.9 response? If so, send the extra data */
     if (backasswards) {
         cntr = len;
        apr_send(r->connection->client_socket, buffer, &cntr);
         cntr = len;
+        e = ap_bucket_create_heap(buffer, cntr, 0, NULL);
+        AP_BRIGADE_INSERT_TAIL(bb, e);
         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");
@@ -497,25 +510,25 @@ int ap_proxy_http_handler(request_rec *r, ap_cache_el *c, char *url,
        }
     }
 
-#ifdef CHARSET_EBCDIC
-    /* What we read/write after the header should not be modified
-     * (i.e., the cache copy is ASCII, not EBCDIC, even for text/html)
-     */
-    ap_bsetflag(f, B_ASCII2EBCDIC|B_EBCDIC2ASCII, 0);
-    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;
+        origin->remain = content_length;
+        while (ap_get_brigade(origin->input_filters, bb, AP_MODE_BLOCKING) == APR_SUCCESS) {
+            if (AP_BUCKET_IS_EOS(AP_BRIGADE_LAST(bb))) {
+                ap_pass_brigade(r->output_filters, bb);
+                break;
+            }
+            ap_pass_brigade(r->output_filters, bb);
+        }
     }
 
-    ap_bclose(f);
+    apr_close_socket(sock);
     if(c) ap_proxy_cache_update(c);
     return OK;
 }
index 8466251605563c8029300690e7c491c9e7da1984..f29fbc0c1c0a5fc53ad1f578a404495408cccdac 100644 (file)
  * University of Illinois, Urbana-Champaign.
  */
 
+#define CORE_PRIVATE
+
 /* Utility routines for Apache proxy */
 #include "mod_proxy.h"
+#include "http_core.h"
 #include "http_main.h"
 #include "http_log.h"
 #include "util_uri.h"
 #include "util_date.h" /* get ap_checkmask() decl. */
 #include "apr_md5.h"
+#include "apr_pools.h"
 
 static int proxy_match_ipaddr(struct dirconn_entry *This, request_rec *r);
 static int proxy_match_domainname(struct dirconn_entry *This, request_rec *r);
@@ -364,64 +368,33 @@ const char *
     return q;
 }
 
-
-/* NOTE: This routine is taken from http_protocol::getline()
- * because the old code found in the proxy module was too
- * difficult to understand and maintain.
- */
-/* Get a line of protocol input, including any continuation lines
- * caused by MIME folding (or broken clients) if fold != 0, and place it
- * in the buffer s, of size n bytes, without the ending newline.
- *
- * Returns -1 on error, or the length of s.
- *
- * Note: Because bgets uses 1 char for newline and 1 char for NUL,
- *       the most we can get is (n - 2) actual characters if it
- *       was ended by a newline, or (n - 1) characters if the line
- *       length exceeded (n - 1).  So, if the result == (n - 1),
- *       then the actual input line exceeded the buffer length,
- *       and it would be a good idea for the caller to puke 400 or 414.
- */
-static int proxy_getline(char *s, int n, BUFF *in, int fold)
+static request_rec *make_fake_req(conn_rec *c)
 {
-    char *pos, next;
-    int retval;
-    int total = 0;
-
-    pos = s;
+    request_rec *r = apr_pcalloc(c->pool, sizeof(*r));
+    core_request_config *req_cfg;
 
-    do {
-        retval = ap_bgets(pos, n, in);     /* retval == -1 if error, 0 if EOF */
+    r->pool            = c->pool;
+    r->status          = HTTP_OK;
 
-        if (retval <= 0)
-            return ((retval < 0) && (total == 0)) ? -1 : total;
+    r->headers_in      = apr_make_table(r->pool, 50);
+    r->subprocess_env  = apr_make_table(r->pool, 50);
+    r->headers_out     = apr_make_table(r->pool, 12);
+    r->err_headers_out = apr_make_table(r->pool, 5);
+    r->notes           = apr_make_table(r->pool, 5);
 
-        /* retval is the number of characters read, not including NUL      */
+    r->read_body       = REQUEST_NO_BODY;
+    r->connection      = c;
+    r->output_filters  = c->output_filters;
+    r->input_filters   = c->input_filters;
 
-        n -= retval;            /* Keep track of how much of s is full     */
-        pos += (retval - 1);    /* and where s ends                        */
-        total += retval;        /* and how long s has become               */
+    r->request_config  = ap_create_request_config(r->pool);
+    req_cfg = apr_pcalloc(r->pool, sizeof(core_request_config));
+    req_cfg->bb = ap_brigade_create(r->pool);
+    ap_set_module_config(r->request_config, &core_module, req_cfg);
 
-        if (*pos == '\n') {     /* Did we get a full line of input?        */
-            *pos = '\0';
-            --total;
-            ++n;
-        }
-        else
-            return total;       /* if not, input line exceeded buffer size */
-
-        /* Continue appending if line folding is desired and
-         * the last line was not empty and we have room in the buffer and
-         * the next line begins with a continuation character.
-         */
-    } while (fold && (retval != 1) && (n > 1)
-                  && (next = ap_blookc(in))
-                  && ((next == ' ') || (next == '\t')));
-
-    return total;
+    return r;
 }
 
-
 /*
  * Reads headers from a buffer and returns an array of headers.
  * Returns NULL on file error
@@ -429,12 +402,13 @@ static int proxy_getline(char *s, int n, BUFF *in, int fold)
  * @@@: XXX: FIXME: currently the headers are passed thru un-merged. 
  * Is that okay, or should they be collapsed where possible?
  */
-apr_table_t *ap_proxy_read_headers(request_rec *r, char *buffer, int size, BUFF *f)
+apr_table_t *ap_proxy_read_headers(request_rec *r, char *buffer, int size, conn_rec *c)
 {
     apr_table_t *resp_hdrs;
     int len;
     char *value, *end;
     char field[MAX_STRING_LEN];
+    request_rec *rr = make_fake_req(c);
 
     resp_hdrs = ap_make_table(r->pool, 20);
 
@@ -442,7 +416,7 @@ apr_table_t *ap_proxy_read_headers(request_rec *r, char *buffer, int size, BUFF
      * Read header lines until we get the empty separator line, a read error,
      * the connection closes (EOF), or we timeout.
      */
-    while ((len = proxy_getline(buffer, size, f, 1)) > 0) {
+    while ((len = ap_getline(buffer, size, rr, 1)) > 0) {
        
        if (!(value = strchr(buffer, ':'))) {     /* Find the colon separator */
 
@@ -479,7 +453,7 @@ apr_table_t *ap_proxy_read_headers(request_rec *r, char *buffer, int size, BUFF
 
        /* the header was too long; at the least we should skip extra data */
        if (len >= size - 1) { 
-           while ((len = proxy_getline(field, MAX_STRING_LEN, f, 1))
+           while ((len = ap_getline(field, MAX_STRING_LEN, r, 1))
                    >= MAX_STRING_LEN - 1) {
                /* soak up the extra data */
            }