You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by mi...@apache.org on 2002/04/07 20:57:37 UTC

cvs commit: apache-1.3/src/modules/proxy mod_proxy.h proxy_cache.c proxy_ftp.c proxy_http.c proxy_util.c

minfrin     02/04/07 11:57:37

  Modified:    src      CHANGES
               src/modules/proxy mod_proxy.h proxy_cache.c proxy_ftp.c
                        proxy_http.c proxy_util.c
  Log:
  Add support for dechunking chunked responses in proxy.
  PR: 7513
  
  Revision  Changes    Path
  1.1805    +3 -0      apache-1.3/src/CHANGES
  
  Index: CHANGES
  ===================================================================
  RCS file: /home/cvs/apache-1.3/src/CHANGES,v
  retrieving revision 1.1804
  retrieving revision 1.1805
  diff -u -r1.1804 -r1.1805
  --- CHANGES	1 Apr 2002 04:24:48 -0000	1.1804
  +++ CHANGES	7 Apr 2002 18:57:34 -0000	1.1805
  @@ -1,5 +1,8 @@
   Changes with Apache 1.3.25
   
  +  *) Add support for dechunking chunked responses in proxy.
  +     [Graham Leggett]
  +
     *) Made AB's use of the Host: header rfc2616 compliant
        by Taisuke Yamada <ta...@iij.ad.jp> [Dirl-Willem van Gulik].
        
  
  
  
  1.58      +1 -1      apache-1.3/src/modules/proxy/mod_proxy.h
  
  Index: mod_proxy.h
  ===================================================================
  RCS file: /home/cvs/apache-1.3/src/modules/proxy/mod_proxy.h,v
  retrieving revision 1.57
  retrieving revision 1.58
  diff -u -r1.57 -r1.58
  --- mod_proxy.h	13 Mar 2002 21:05:32 -0000	1.57
  +++ mod_proxy.h	7 Apr 2002 18:57:36 -0000	1.58
  @@ -297,7 +297,7 @@
                            char **passwordp, char **hostp, int *port);
   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, size_t recv_buffer_size);
  +long int ap_proxy_send_fb(BUFF *f, request_rec *r, cache_req *c, off_t len, int nowrite, int chunked, size_t recv_buffer_size);
   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);
  
  
  
  1.84      +5 -5      apache-1.3/src/modules/proxy/proxy_cache.c
  
  Index: proxy_cache.c
  ===================================================================
  RCS file: /home/cvs/apache-1.3/src/modules/proxy/proxy_cache.c,v
  retrieving revision 1.83
  retrieving revision 1.84
  diff -u -r1.83 -r1.84
  --- proxy_cache.c	6 Apr 2002 13:20:48 -0000	1.83
  +++ proxy_cache.c	7 Apr 2002 18:57:36 -0000	1.84
  @@ -719,7 +719,7 @@
    *
    * We don't yet understand If-Range, but we will...
    */
  -    int ap_proxy_cache_conditional(request_rec *r, cache_req *c, BUFF *cachefp){
  +    int ap_proxy_cache_conditional(request_rec *r, cache_req *c, BUFF *cachefp) {
           const char *etag, *wetag = NULL;
   
           /* get etag */
  @@ -784,7 +784,7 @@
               /* if cache file is being updated */
               if (c->origfp) {
                   ap_proxy_write_headers(c, c->resp_line, c->hdrs);
  -                ap_proxy_send_fb(c->origfp, r, c, c->len, 1, IOBUFSIZE);
  +                ap_proxy_send_fb(c->origfp, r, c, c->len, 1, 0, IOBUFSIZE);
                   ap_proxy_cache_tidy(c);
               }
               else
  @@ -855,7 +855,7 @@
               /* are we updating the cache file? */
               if (c->origfp) {
                   ap_proxy_write_headers(c, c->resp_line, c->hdrs);
  -                ap_proxy_send_fb(c->origfp, r, c, c->len, 1, IOBUFSIZE);
  +                ap_proxy_send_fb(c->origfp, r, c, c->len, 1, 0, IOBUFSIZE);
                   ap_proxy_cache_tidy(c);
               }
               else
  @@ -884,14 +884,14 @@
           /* are we rewriting the cache file? */
           if (c->origfp) {
               ap_proxy_write_headers(c, c->resp_line, c->hdrs);
  -            ap_proxy_send_fb(c->origfp, r, c, c->len, r->header_only, IOBUFSIZE);
  +            ap_proxy_send_fb(c->origfp, r, c, c->len, r->header_only, 0, IOBUFSIZE);
               ap_proxy_cache_tidy(c);
               return OK;
           }
   
           /* no, we not */
           if (!r->header_only) {
  -            ap_proxy_send_fb(cachefp, r, NULL, c->len, 0, IOBUFSIZE);
  +            ap_proxy_send_fb(cachefp, r, NULL, c->len, 0, 0, IOBUFSIZE);
           }
           else {
               ap_pclosef(r->pool, ap_bfileno(cachefp, B_WR));
  
  
  
  1.98      +1 -1      apache-1.3/src/modules/proxy/proxy_ftp.c
  
  Index: proxy_ftp.c
  ===================================================================
  RCS file: /home/cvs/apache-1.3/src/modules/proxy/proxy_ftp.c,v
  retrieving revision 1.97
  retrieving revision 1.98
  diff -u -r1.97 -r1.98
  --- proxy_ftp.c	25 Mar 2002 09:21:58 -0000	1.97
  +++ proxy_ftp.c	7 Apr 2002 18:57:36 -0000	1.98
  @@ -1355,7 +1355,7 @@
   /* we need to set this for ap_proxy_send_fb()... */
               if (c != NULL)
                   c->cache_completion = 0;
  -            ap_proxy_send_fb(data, r, c, -1, 0, conf->io_buffer_size);
  +            ap_proxy_send_fb(data, r, c, -1, 0, 0, conf->io_buffer_size);
           }
           else {
               send_dir(data, r, c, cwd);
  
  
  
  1.91      +8 -2      apache-1.3/src/modules/proxy/proxy_http.c
  
  Index: proxy_http.c
  ===================================================================
  RCS file: /home/cvs/apache-1.3/src/modules/proxy/proxy_http.c,v
  retrieving revision 1.90
  retrieving revision 1.91
  diff -u -r1.90 -r1.91
  --- proxy_http.c	25 Mar 2002 22:33:13 -0000	1.90
  +++ proxy_http.c	7 Apr 2002 18:57:36 -0000	1.91
  @@ -164,6 +164,7 @@
       char portstr[32];
       pool *p = r->pool;
       int destport = 0;
  +    int chunked = 0;
       char *destportstr = NULL;
       const char *urlptr = NULL;
       const char *datestr, *urlstr;
  @@ -476,7 +477,12 @@
                   );
           }
   
  -        /* strip hop-by-hop headers defined by Connection */
  +        /* is this content chunked? */
  +        chunked = ap_find_last_token(r->pool,
  +                                     ap_table_get(resp_hdrs, "Transfer-Encoding"),
  +                                     "chunked");
  +
  +        /* strip hop-by-hop headers defined by Connection and RFC2616 */
           ap_proxy_clear_connection(p, resp_hdrs);
           /* Now add out bound headers set by other modules */
           resp_hdrs = ap_overlay_tables(r->pool, r->err_headers_out, resp_hdrs);
  @@ -595,7 +601,7 @@
    * content length is not known. We need to make 100% sure c->len is always
    * set correctly before we get here to correctly do keepalive.
    */
  -        ap_proxy_send_fb(f, r, c, c->len, 0, conf->io_buffer_size);
  +        ap_proxy_send_fb(f, r, c, c->len, 0, chunked, conf->io_buffer_size);
       }
   
       /* ap_proxy_send_fb() closes the socket f for us */
  
  
  
  1.113     +75 -65    apache-1.3/src/modules/proxy/proxy_util.c
  
  Index: proxy_util.c
  ===================================================================
  RCS file: /home/cvs/apache-1.3/src/modules/proxy/proxy_util.c,v
  retrieving revision 1.112
  retrieving revision 1.113
  diff -u -r1.112 -r1.113
  --- proxy_util.c	6 Apr 2002 13:20:48 -0000	1.112
  +++ proxy_util.c	7 Apr 2002 18:57:36 -0000	1.113
  @@ -366,64 +366,6 @@
   }
   
   
  -/* 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)
  -{
  -    char *pos, next;
  -    int retval;
  -    int total = 0;
  -
  -    pos = s;
  -
  -    do {
  -        retval = ap_bgets(pos, n, in);  /* retval == -1 if error, 0 if EOF */
  -
  -        if (retval <= 0)
  -            return ((retval < 0) && (total == 0)) ? -1 : total;
  -
  -        /* retval is the number of characters read, not including NUL      */
  -
  -        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               */
  -
  -        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)
  -             && (ap_blookc(&next, in) == 1)
  -             && ((next == ' ') || (next == '\t')));
  -
  -    return total;
  -}
  -
  -
   /*
    * Reads headers from a buffer and returns an array of headers.
    * Returns NULL on file error
  @@ -447,7 +389,7 @@
        * 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, f, 1)) > 0) {
   
           if (!(value = strchr(buffer, ':'))) {   /* Find the colon separator */
   
  @@ -488,7 +430,7 @@
   
           /* 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, f, 1))
                      >= MAX_STRING_LEN - 1) {
                   /* soak up the extra data */
               }
  @@ -504,11 +446,12 @@
    * - r->connection->client, if nowrite == 0
    */
   
  -long int ap_proxy_send_fb(BUFF *f, request_rec *r, cache_req *c, off_t len, int nowrite, size_t recv_buffer_size)
  +long int ap_proxy_send_fb(BUFF *f, request_rec *r, cache_req *c, off_t len, int nowrite, int chunked, size_t recv_buffer_size)
   {
       int ok;
       char *buf;
       size_t buf_size;
  +    size_t remaining = 0;
       long total_bytes_rcvd;
       register int n, o, w;
       conn_rec *con = r->connection;
  @@ -572,14 +515,68 @@
           if (alternate_timeouts)
               ap_hard_timeout("proxy recv body from upstream server", r);
   
  -        /* Read block from server */
  -        if (-1 == len) {
  -            n = ap_bread(f, buf, buf_size);
  +
  +        /* read a chunked block */
  +        if (chunked) {
  +            long chunk_start = 0;
  +            n = 0;
  +
  +            /* start of a new chunk */
  +            if (remaining == 0) {
  +                /* get the chunk size from the stream */
  +                chunk_start = ap_getline(buf, buf_size, f, 0);
  +                if ((chunk_start <= 0) || (chunk_start >= (buf_size - 1)) || !ap_isxdigit(*buf)) {
  +                    n = -1;
  +                }
  +                /* parse the chunk size */
  +                else {
  +                    remaining = ap_get_chunk_size(buf);
  +                    if (remaining == 0) { /* Last chunk indicated, get footers */
  +                        /* as we are a proxy, we discard the footers, as the headers
  +                         * have already been sent at this point.
  +                         */
  +                        if (NULL == ap_proxy_read_headers(r, buf, buf_size, f)) {
  +                            n = -1;
  +                        }
  +                    }
  +                }
  +            }
  +
  +            /* read the chunk */
  +            if (remaining > 0) {
  +                n = ap_bread(f, buf, MIN((off_t)buf_size, remaining));
  +                if (n > -1) {
  +                    remaining -= n;
  +                }
  +            }
  +
  +            /* soak up trailing CRLF */
  +            if (0 == remaining) {
  +                char ch;
  +/****/
  +/* XXXX FIXME: Does this little "soak CRLF" work with EBCDIC???? */
  +/****/
  +                if ((ch = ap_bgetc(f)) == CR) {
  +                    ch = ap_bgetc(f);
  +                }
  +                if (ch != LF) {
  +                    n = -1;
  +                }
  +            }
           }
  +
  +
  +        /* otherwise read block normally */
           else {
  -            n = ap_bread(f, buf, MIN((off_t)buf_size, len - total_bytes_rcvd));
  +            if (-1 == len) {
  +                n = ap_bread(f, buf, buf_size);
  +            }
  +            else {
  +                n = ap_bread(f, buf, MIN((off_t)buf_size, len - total_bytes_rcvd));
  +            }
           }
   
  +
           if (alternate_timeouts)
               ap_kill_timeout(r);
           else
  @@ -1475,6 +1472,19 @@
           ap_table_unset(headers, name);
       }
       ap_table_unset(headers, "Connection");
  +
  +    /* unset hop-by-hop headers defined in RFC2616 13.5.1 */
  +    ap_table_unset(headers,"Keep-Alive");
  +    ap_table_unset(headers,"Proxy-Authenticate");
  +    ap_table_unset(headers,"TE");
  +    ap_table_unset(headers,"Trailer");
  +    /* it is safe to just chop the transfer-encoding header
  +     * here, because proxy doesn't support any other encodings
  +     * to the backend other than chunked.
  +     */
  +    ap_table_unset(headers,"Transfer-Encoding");
  +    ap_table_unset(headers,"Upgrade");
  +
   }
   
   /* overlay one table on another