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