You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by rb...@apache.org on 2001/08/11 07:10:23 UTC
cvs commit: httpd-proxy/module-2.0 CHANGES proxy_http.c
rbb 01/08/10 22:10:23
Modified: module-2.0 CHANGES proxy_http.c
Log:
Fix the proxy when the origin server sends back a 100
Continue response. [John Barbee <ba...@veribox.net>]
Revision Changes Path
1.9 +5 -1 httpd-proxy/module-2.0/CHANGES
Index: CHANGES
===================================================================
RCS file: /home/cvs/httpd-proxy/module-2.0/CHANGES,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- CHANGES 2001/08/07 21:46:47 1.8
+++ CHANGES 2001/08/11 05:10:23 1.9
@@ -1,6 +1,10 @@
mod_proxy changes for httpd 2.0.23-dev
+
+ *) Fix the proxy when the origin server sends back a 100
+ Continue response. [John Barbee <ba...@veribox.net>]
+
*) Change 'readbytes' from apr_size_t to apr_off_t due to change
- in ap_get_brigade's parameters [Barbee barbee@veribox.nbet]
+ in ap_get_brigade's parameters [John Barbee <ba...@veribox.net>]
mod_proxy changes for httpd 2.0.20-dev
*) Timeout added for backend connections.
1.86 +192 -180 httpd-proxy/module-2.0/proxy_http.c
Index: proxy_http.c
===================================================================
RCS file: /home/cvs/httpd-proxy/module-2.0/proxy_http.c,v
retrieving revision 1.85
retrieving revision 1.86
diff -u -r1.85 -r1.86
--- proxy_http.c 2001/08/07 21:46:47 1.85
+++ proxy_http.c 2001/08/11 05:10:23 1.86
@@ -207,6 +207,11 @@
conn_rec *origin = NULL;
apr_uri_components uri;
proxy_conn_rec *backend;
+ int received_continue = 1; /* flag to indicate if we should
+ * loop over response parsing logic
+ * in the case that the origin told us
+ * to HTTP_CONTINUE
+ */
/* Note: Memory pool allocation.
* A downstream keepalive connection is always connected to the existence
@@ -619,191 +624,198 @@
apr_brigade_cleanup(bb);
- if (APR_SUCCESS != (rv = ap_proxy_string_read(origin, bb, buffer, sizeof(buffer), &eos))) {
- apr_socket_close(sock);
- backend->connection = NULL;
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
- "proxy: error reading status line from remote server %s",
- connectname);
- return ap_proxyerror(r, HTTP_BAD_GATEWAY,
- "Error reading from remote server");
- }
- len = strlen(buffer);
-
- /* Is it an HTTP/1 response? This is buggy if we ever see an HTTP/1.10 */
- if (apr_date_checkmask(buffer, "HTTP/#.# ###*")) {
- int major, minor;
-
- if (2 != sscanf(buffer, "HTTP/%u.%u", &major, &minor)) {
- major = 1;
- minor = 1;
- }
-
- /* If not an HTTP/1 message or if the status line was > 8192 bytes */
- else if ((buffer[5] != '1') || (len >= sizeof(buffer)-1)) {
- apr_socket_close(sock);
- backend->connection = NULL;
- return ap_proxyerror(r, HTTP_BAD_GATEWAY,
- apr_pstrcat(p, "Corrupt status line returned by remote server: ", buffer, NULL));
- }
- 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. */
-
- r->headers_out = ap_proxy_read_headers(r, rp, buffer, sizeof(buffer), origin);
- if (r->headers_out == 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);
- close += 1;
- }
- else
+ while (received_continue) {
+ if (APR_SUCCESS != (rv = ap_proxy_string_read(origin, bb, buffer, sizeof(buffer), &eos))) {
+ apr_socket_close(sock);
+ backend->connection = NULL;
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
+ "proxy: error reading status line from remote server %s",
+ connectname);
+ return ap_proxyerror(r, HTTP_BAD_GATEWAY,
+ "Error reading from remote server");
+ }
+ len = strlen(buffer);
+
+ /* Is it an HTTP/1 response? This is buggy if we ever see an HTTP/1.10 */
+ if (apr_date_checkmask(buffer, "HTTP/#.# ###*")) {
+ int major, minor;
+
+ if (2 != sscanf(buffer, "HTTP/%u.%u", &major, &minor)) {
+ major = 1;
+ minor = 1;
+ }
+
+ /* If not an HTTP/1 message or if the status line was > 8192 bytes */
+ else if ((buffer[5] != '1') || (len >= sizeof(buffer)-1)) {
+ apr_socket_close(sock);
+ backend->connection = NULL;
+ return ap_proxyerror(r, HTTP_BAD_GATEWAY,
+ apr_pstrcat(p, "Corrupt status line returned by remote server: ", buffer, NULL));
+ }
+ 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. */
+
+ r->headers_out = ap_proxy_read_headers(r, rp, buffer, sizeof(buffer), origin);
+ if (r->headers_out == 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);
+ close += 1;
+ }
+ else
+ {
+ /* strip connection listed hop-by-hop headers from response */
+ const char *buf;
+ close += ap_proxy_liststr(apr_table_get(r->headers_out, "Connection"), "close");
+ ap_proxy_clear_connection(p, r->headers_out);
+ if ((buf = apr_table_get(r->headers_out, "Content-Type"))) {
+ r->content_type = apr_pstrdup(p, buf);
+ }
+ }
+
+ /* handle Via header in response */
+ if (conf->viaopt != via_off && conf->viaopt != via_block) {
+ /* create a "Via:" response header entry and merge it */
+ ap_table_mergen(r->headers_out, "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), server_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), server_portstr)
+ );
+ }
+
+ /* cancel keepalive if HTTP/1.0 or less */
+ if ((major < 1) || (minor < 1)) {
+ close += 1;
+ origin->keepalive = 0;
+ }
+ }
+ else {
+ /* an http/0.9 response */
+ backasswards = 1;
+ r->status = 200;
+ r->status_line = "200 OK";
+ close += 1;
+ }
+
+ if ( r->status != HTTP_CONTINUE ) {
+ received_continue = 0;
+ } else {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, 0, NULL,
+ "proxy: HTTP: received 100 CONTINUE");
+ }
+ /* we must accept 3 kinds of date, but generate only 1 kind of date */
{
- /* strip connection listed hop-by-hop headers from response */
- const char *buf;
- close += ap_proxy_liststr(apr_table_get(r->headers_out, "Connection"), "close");
- ap_proxy_clear_connection(p, r->headers_out);
- if ((buf = apr_table_get(r->headers_out, "Content-Type"))) {
- r->content_type = apr_pstrdup(p, buf);
+ const char *buf;
+ if ((buf = apr_table_get(r->headers_out, "Date")) != NULL) {
+ apr_table_set(r->headers_out, "Date", ap_proxy_date_canon(p, buf));
+ }
+ if ((buf = apr_table_get(r->headers_out, "Expires")) != NULL) {
+ apr_table_set(r->headers_out, "Expires", ap_proxy_date_canon(p, buf));
+ }
+ if ((buf = apr_table_get(r->headers_out, "Last-Modified")) != NULL) {
+ apr_table_set(r->headers_out, "Last-Modified", ap_proxy_date_canon(p, buf));
}
}
-
- /* handle Via header in response */
- if (conf->viaopt != via_off && conf->viaopt != via_block) {
- /* create a "Via:" response header entry and merge it */
- ap_table_mergen(r->headers_out, "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), server_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), server_portstr)
- );
- }
-
- /* cancel keepalive if HTTP/1.0 or less */
- if ((major < 1) || (minor < 1)) {
- close += 1;
- origin->keepalive = 0;
- }
- }
- else {
- /* an http/0.9 response */
- backasswards = 1;
- r->status = 200;
- r->status_line = "200 OK";
- close += 1;
- }
-
- /* we must accept 3 kinds of date, but generate only 1 kind of date */
- {
- const char *buf;
- if ((buf = apr_table_get(r->headers_out, "Date")) != NULL) {
- apr_table_set(r->headers_out, "Date", ap_proxy_date_canon(p, buf));
- }
- if ((buf = apr_table_get(r->headers_out, "Expires")) != NULL) {
- apr_table_set(r->headers_out, "Expires", ap_proxy_date_canon(p, buf));
- }
- if ((buf = apr_table_get(r->headers_out, "Last-Modified")) != NULL) {
- apr_table_set(r->headers_out, "Last-Modified", ap_proxy_date_canon(p, buf));
- }
- }
-
- /* munge the Location and URI response headers according to ProxyPassReverse */
- {
- const char *buf;
- if ((buf = apr_table_get(r->headers_out, "Location")) != NULL) {
- apr_table_set(r->headers_out, "Location", ap_proxy_location_reverse_map(r, conf, buf));
- }
- if ((buf = apr_table_get(r->headers_out, "Content-Location")) != NULL) {
- apr_table_set(r->headers_out, "Content-Location", ap_proxy_location_reverse_map(r, conf, buf));
- }
- if ((buf = apr_table_get(r->headers_out, "URI")) != NULL) {
- apr_table_set(r->headers_out, "URI", ap_proxy_location_reverse_map(r, conf, buf));
- }
- }
-
- r->sent_bodyct = 1;
- /* Is it an HTTP/0.9 response? If so, send the extra data */
- if (backasswards) {
- apr_ssize_t cntr = len;
- e = apr_bucket_heap_create(buffer, cntr, 0, NULL);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- }
-
- /* send body - but only if a body is expected */
- if ((!r->header_only) && /* not HEAD request */
- (r->status > 199) && /* not any 1xx response */
- (r->status != HTTP_NO_CONTENT) && /* not 204 */
- (r->status != HTTP_RESET_CONTENT) && /* not 205 */
- (r->status != HTTP_NOT_MODIFIED)) { /* not 304 */
-
- const char *buf;
- apr_off_t readbytes;
-
- /* if chunked - insert DECHUNK filter */
- if (ap_proxy_liststr((buf = apr_table_get(r->headers_out, "Transfer-Encoding")), "chunked")) {
- rp->read_chunked = 1;
- apr_table_unset(r->headers_out, "Transfer-Encoding");
- if ((buf = ap_proxy_removestr(r->pool, buf, "chunked"))) {
- apr_table_set(r->headers_out, "Transfer-Encoding", buf);
- }
- ap_add_input_filter("DECHUNK", NULL, rp, origin);
- readbytes = -1;
- }
-
- /* if content length - set the length to read */
- else if ((buf = apr_table_get(r->headers_out, "Content-Length"))) {
- readbytes = atol(buf);
- }
-
- /* no chunked / no length therefore read till EOF and cancel keepalive */
- else {
- close += 1;
- }
-
- /* if keepalive cancelled, read to EOF */
- if (close) {
- readbytes = -1;
- }
-
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: start body send");
-
- /* read the body, pass it to the output filters */
- while (ap_get_brigade(rp->input_filters, bb, AP_MODE_BLOCKING, &readbytes) == APR_SUCCESS) {
- if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb))) {
- ap_pass_brigade(r->output_filters, bb);
- break;
- }
- if (ap_pass_brigade(r->output_filters, bb) != APR_SUCCESS) {
- /* Ack! Phbtt! Die! User aborted! */
- close = 1; /* this causes socket close below */
- break;
+
+ /* munge the Location and URI response headers according to ProxyPassReverse */
+ {
+ const char *buf;
+ if ((buf = apr_table_get(r->headers_out, "Location")) != NULL) {
+ apr_table_set(r->headers_out, "Location", ap_proxy_location_reverse_map(r, conf, buf));
}
- apr_brigade_cleanup(bb);
- }
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: end body send");
- }
- else {
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: header only");
+ if ((buf = apr_table_get(r->headers_out, "Content-Location")) != NULL) {
+ apr_table_set(r->headers_out, "Content-Location", ap_proxy_location_reverse_map(r, conf, buf));
+ }
+ if ((buf = apr_table_get(r->headers_out, "URI")) != NULL) {
+ apr_table_set(r->headers_out, "URI", ap_proxy_location_reverse_map(r, conf, buf));
+ }
+ }
+
+ r->sent_bodyct = 1;
+ /* Is it an HTTP/0.9 response? If so, send the extra data */
+ if (backasswards) {
+ apr_ssize_t cntr = len;
+ e = apr_bucket_heap_create(buffer, cntr, 0, NULL);
+ APR_BRIGADE_INSERT_TAIL(bb, e);
+ }
+
+ /* send body - but only if a body is expected */
+ if ((!r->header_only) && /* not HEAD request */
+ (r->status > 199) && /* not any 1xx response */
+ (r->status != HTTP_NO_CONTENT) && /* not 204 */
+ (r->status != HTTP_RESET_CONTENT) && /* not 205 */
+ (r->status != HTTP_NOT_MODIFIED)) { /* not 304 */
+
+ const char *buf;
+ apr_off_t readbytes;
+
+ /* if chunked - insert DECHUNK filter */
+ if (ap_proxy_liststr((buf = apr_table_get(r->headers_out, "Transfer-Encoding")), "chunked")) {
+ rp->read_chunked = 1;
+ apr_table_unset(r->headers_out, "Transfer-Encoding");
+ if ((buf = ap_proxy_removestr(r->pool, buf, "chunked"))) {
+ apr_table_set(r->headers_out, "Transfer-Encoding", buf);
+ }
+ ap_add_input_filter("DECHUNK", NULL, rp, origin);
+ readbytes = -1;
+ }
+
+ /* if content length - set the length to read */
+ else if ((buf = apr_table_get(r->headers_out, "Content-Length"))) {
+ readbytes = atol(buf);
+ }
+
+ /* no chunked / no length therefore read till EOF and cancel keepalive */
+ else {
+ close += 1;
+ }
+
+ /* if keepalive cancelled, read to EOF */
+ if (close) {
+ readbytes = -1;
+ }
+
+ ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
+ "proxy: start body send");
+
+ /* read the body, pass it to the output filters */
+ while (ap_get_brigade(rp->input_filters, bb, AP_MODE_BLOCKING, &readbytes) == APR_SUCCESS) {
+ if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb))) {
+ ap_pass_brigade(r->output_filters, bb);
+ break;
+ }
+ if (ap_pass_brigade(r->output_filters, bb) != APR_SUCCESS) {
+ /* Ack! Phbtt! Die! User aborted! */
+ close = 1; /* this causes socket close below */
+ break;
+ }
+ apr_brigade_cleanup(bb);
+ }
+ ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
+ "proxy: end body send");
+ }
+ else {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
+ "proxy: header only");
+ }
}
-
/*
* Step Five: Clean Up