You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by wr...@apache.org on 2005/08/08 03:22:22 UTC
svn commit: r230724 -
/httpd/httpd/branches/proxy-reqbody-2.0.x/modules/proxy/proxy_http.c
Author: wrowe
Date: Sun Aug 7 18:22:17 2005
New Revision: 230724
URL: http://svn.apache.org/viewcvs?rev=230724&view=rev
Log:
Backport the body pre-fetch code from trunk/, modifying the three
stream_te / stream_cl / spool_cl functions to presume an input_brigade
before fighting with fetching additional body content.
We will be using the bytes_read in a later commit to make a better
decision about choosing to send a C-L or chunked body to the backend.
Modified:
httpd/httpd/branches/proxy-reqbody-2.0.x/modules/proxy/proxy_http.c
Modified: httpd/httpd/branches/proxy-reqbody-2.0.x/modules/proxy/proxy_http.c
URL: http://svn.apache.org/viewcvs/httpd/httpd/branches/proxy-reqbody-2.0.x/modules/proxy/proxy_http.c?rev=230724&r1=230723&r2=230724&view=diff
==============================================================================
--- httpd/httpd/branches/proxy-reqbody-2.0.x/modules/proxy/proxy_http.c (original)
+++ httpd/httpd/branches/proxy-reqbody-2.0.x/modules/proxy/proxy_http.c Sun Aug 7 18:22:17 2005
@@ -469,28 +469,13 @@
add_te_chunked(p, bucket_alloc, header_brigade);
terminate_headers(bucket_alloc, header_brigade);
- do {
+ while (!APR_BUCKET_IS_EOS(APR_BRIGADE_FIRST(input_brigade)))
+ {
char chunk_hdr[20]; /* must be here due to transient bucket. */
- status = ap_get_brigade(r->input_filters, input_brigade,
- AP_MODE_READBYTES, APR_BLOCK_READ,
- HUGE_STRING_LEN);
-
- if (status != APR_SUCCESS) {
- return status;
- }
-
/* If this brigade contains EOS, either stop or remove it. */
if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) {
seen_eos = 1;
-
- /* As a shortcut, if this brigade is simply an EOS bucket,
- * don't send anything down the filter chain.
- */
- if (APR_BUCKET_IS_EOS(APR_BRIGADE_FIRST(input_brigade))) {
- break;
- }
-
/* We can't pass this EOS to the output_filters. */
e = APR_BRIGADE_LAST(input_brigade);
apr_bucket_delete(e);
@@ -529,7 +514,19 @@
if (status != APR_SUCCESS) {
return status;
}
- } while (!seen_eos);
+
+ if (seen_eos) {
+ break;
+ }
+
+ status = ap_get_brigade(r->input_filters, input_brigade,
+ AP_MODE_READBYTES, APR_BLOCK_READ,
+ HUGE_STRING_LEN);
+
+ if (status != APR_SUCCESS) {
+ return status;
+ }
+ }
if (header_brigade) {
/* we never sent the header brigade because there was no request body;
@@ -580,15 +577,8 @@
}
terminate_headers(bucket_alloc, header_brigade);
- do {
- status = ap_get_brigade(r->input_filters, input_brigade,
- AP_MODE_READBYTES, APR_BLOCK_READ,
- HUGE_STRING_LEN);
-
- if (status != APR_SUCCESS) {
- return status;
- }
-
+ while (!APR_BUCKET_IS_EOS(APR_BRIGADE_FIRST(input_brigade)))
+ {
apr_brigade_length(input_brigade, 1, &bytes);
bytes_streamed += bytes;
@@ -636,7 +626,19 @@
if (status != APR_SUCCESS) {
return status;
}
- } while (!seen_eos);
+
+ if (seen_eos) {
+ break;
+ }
+
+ status = ap_get_brigade(r->input_filters, input_brigade,
+ AP_MODE_READBYTES, APR_BLOCK_READ,
+ HUGE_STRING_LEN);
+
+ if (status != APR_SUCCESS) {
+ return status;
+ }
+ }
if (bytes_streamed != cl_val) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
@@ -679,26 +681,12 @@
body_brigade = apr_brigade_create(p, bucket_alloc);
- do {
- status = ap_get_brigade(r->input_filters, input_brigade,
- AP_MODE_READBYTES, APR_BLOCK_READ,
- HUGE_STRING_LEN);
-
- if (status != APR_SUCCESS) {
- return status;
- }
-
+ while (!APR_BUCKET_IS_EOS(APR_BRIGADE_FIRST(input_brigade)))
+ {
/* If this brigade contains EOS, either stop or remove it. */
if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) {
seen_eos = 1;
- /* As a shortcut, if this brigade is simply an EOS bucket,
- * don't send anything down the filter chain.
- */
- if (APR_BUCKET_IS_EOS(APR_BRIGADE_FIRST(input_brigade))) {
- break;
- }
-
/* We can't pass this EOS to the output_filters. */
e = APR_BRIGADE_LAST(input_brigade);
apr_bucket_delete(e);
@@ -759,7 +747,18 @@
bytes_spooled += bytes;
- } while (!seen_eos);
+ if (seen_eos) {
+ break;
+ }
+
+ status = ap_get_brigade(r->input_filters, input_brigade,
+ AP_MODE_READBYTES, APR_BLOCK_READ,
+ HUGE_STRING_LEN);
+
+ if (status != APR_SUCCESS) {
+ return status;
+ }
+ }
if (bytes_spooled || force_cl) {
add_cl(p, bucket_alloc, header_brigade, apr_off_t_toa(p, bytes_spooled));
@@ -804,6 +803,7 @@
conn_rec *c = r->connection;
apr_bucket_alloc_t *bucket_alloc = c->bucket_alloc;
apr_bucket_brigade *input_brigade;
+ apr_bucket_brigade *temp_brigade;
char *buf;
apr_bucket *e;
const apr_array_header_t *headers_in_array;
@@ -814,6 +814,8 @@
enum rb_methods rb_method = RB_INIT;
const char *old_cl_val = NULL;
const char *old_te_val = NULL;
+ apr_off_t bytes_read = 0;
+ apr_off_t bytes;
int cl_zero; /* client sent "Content-Length: 0", which we forward on to server */
int force10;
@@ -1030,6 +1032,40 @@
apr_table_unset(r->headers_in, "Transfer-Encoding");
}
}
+
+ /* Prefetch MAX_MEM_SPOOL bytes
+ *
+ * This helps us avoid any election of C-L v.s. T-E
+ * request bodies, since we are willing to keep in
+ * memory this much data, in any case. This gives
+ * us an instant C-L election if the body is of some
+ * reasonable size.
+ */
+ temp_brigade = apr_brigade_create(p, bucket_alloc);
+ do {
+ status = ap_get_brigade(r->input_filters, temp_brigade,
+ AP_MODE_READBYTES, APR_BLOCK_READ,
+ MAX_MEM_SPOOL - bytes_read);
+ if (status != APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, status, r->server,
+ "proxy: prefetch request body failed to %s"
+ " from %s (%s)",
+ p_conn->name ? p_conn->name: "",
+ c->remote_ip, c->remote_host ? c->remote_host: "");
+ return status;
+ }
+
+ apr_brigade_length(temp_brigade, 1, &bytes);
+ APR_BRIGADE_CONCAT(input_brigade, temp_brigade);
+ bytes_read += bytes;
+
+ /* Ensure we don't hit a wall where we have a buffer too small
+ * for ap_get_brigade's filters to fetch us another bucket,
+ * surrender once we hit 80 bytes less than MAX_MEM_SPOOL
+ * (an arbitrary value.)
+ */
+ } while ((bytes_read < MAX_MEM_SPOOL - 80)
+ && !APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade)));
/* send CL or use chunked encoding?
*