Lines 299-305
static int stream_reqbody_chunked(apr_pool_t *p,
Link Here
|
299 |
proxy_conn_rec *p_conn, |
299 |
proxy_conn_rec *p_conn, |
300 |
conn_rec *origin, |
300 |
conn_rec *origin, |
301 |
apr_bucket_brigade *header_brigade, |
301 |
apr_bucket_brigade *header_brigade, |
302 |
apr_bucket_brigade *input_brigade) |
302 |
apr_bucket_brigade *input_brigade, |
|
|
303 |
int flushall) |
303 |
{ |
304 |
{ |
304 |
int seen_eos = 0, rv = OK; |
305 |
int seen_eos = 0, rv = OK; |
305 |
apr_size_t hdr_len; |
306 |
apr_size_t hdr_len; |
Lines 312-325
static int stream_reqbody_chunked(apr_pool_t *p,
Link Here
|
312 |
add_te_chunked(p, bucket_alloc, header_brigade); |
313 |
add_te_chunked(p, bucket_alloc, header_brigade); |
313 |
terminate_headers(bucket_alloc, header_brigade); |
314 |
terminate_headers(bucket_alloc, header_brigade); |
314 |
|
315 |
|
315 |
while (!APR_BUCKET_IS_EOS(APR_BRIGADE_FIRST(input_brigade))) |
316 |
while (APR_BRIGADE_EMPTY(input_brigade) |
|
|
317 |
|| !APR_BUCKET_IS_EOS(APR_BRIGADE_FIRST(input_brigade))) |
316 |
{ |
318 |
{ |
317 |
char chunk_hdr[20]; /* must be here due to transient bucket. */ |
319 |
char chunk_hdr[20]; /* must be here due to transient bucket. */ |
|
|
320 |
int flush = flushall; |
318 |
|
321 |
|
|
|
322 |
if (!APR_BRIGADE_EMPTY(input_brigade)) { |
319 |
/* If this brigade contains EOS, either stop or remove it. */ |
323 |
/* If this brigade contains EOS, either stop or remove it. */ |
320 |
if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) { |
324 |
if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) { |
321 |
seen_eos = 1; |
325 |
seen_eos = 1; |
322 |
|
326 |
|
|
|
327 |
/* The request is flushed below this loop with the EOS chunk */ |
328 |
flush = 0; |
329 |
|
323 |
/* We can't pass this EOS to the output_filters. */ |
330 |
/* We can't pass this EOS to the output_filters. */ |
324 |
e = APR_BRIGADE_LAST(input_brigade); |
331 |
e = APR_BRIGADE_LAST(input_brigade); |
325 |
apr_bucket_delete(e); |
332 |
apr_bucket_delete(e); |
Lines 341-346
static int stream_reqbody_chunked(apr_pool_t *p,
Link Here
|
341 |
*/ |
348 |
*/ |
342 |
e = apr_bucket_immortal_create(ASCII_CRLF, 2, bucket_alloc); |
349 |
e = apr_bucket_immortal_create(ASCII_CRLF, 2, bucket_alloc); |
343 |
APR_BRIGADE_INSERT_TAIL(input_brigade, e); |
350 |
APR_BRIGADE_INSERT_TAIL(input_brigade, e); |
|
|
351 |
} |
344 |
|
352 |
|
345 |
if (header_brigade) { |
353 |
if (header_brigade) { |
346 |
/* we never sent the header brigade, so go ahead and |
354 |
/* we never sent the header brigade, so go ahead and |
Lines 348-353
static int stream_reqbody_chunked(apr_pool_t *p,
Link Here
|
348 |
*/ |
356 |
*/ |
349 |
bb = header_brigade; |
357 |
bb = header_brigade; |
350 |
|
358 |
|
|
|
359 |
/* Flush now, unless it is done below this loop with the EOS chunk, |
360 |
* to minimize the delay between connect (or is_socket_connected) |
361 |
* and the first bytes sent. |
362 |
*/ |
363 |
flush = !seen_eos; |
364 |
|
351 |
/* |
365 |
/* |
352 |
* Save input_brigade in bb brigade. (At least) in the SSL case |
366 |
* Save input_brigade in bb brigade. (At least) in the SSL case |
353 |
* input_brigade contains transient buckets whose data would get |
367 |
* input_brigade contains transient buckets whose data would get |
Lines 369-375
static int stream_reqbody_chunked(apr_pool_t *p,
Link Here
|
369 |
} |
383 |
} |
370 |
|
384 |
|
371 |
/* The request is flushed below this loop with chunk EOS header */ |
385 |
/* The request is flushed below this loop with chunk EOS header */ |
372 |
rv = pass_brigade(bucket_alloc, r, p_conn, origin, bb, 0); |
386 |
rv = pass_brigade(bucket_alloc, r, p_conn, origin, bb, flush); |
373 |
if (rv != OK) { |
387 |
if (rv != OK) { |
374 |
return rv; |
388 |
return rv; |
375 |
} |
389 |
} |
Lines 420-426
static int stream_reqbody_cl(apr_pool_t *p,
Link Here
|
420 |
conn_rec *origin, |
434 |
conn_rec *origin, |
421 |
apr_bucket_brigade *header_brigade, |
435 |
apr_bucket_brigade *header_brigade, |
422 |
apr_bucket_brigade *input_brigade, |
436 |
apr_bucket_brigade *input_brigade, |
423 |
const char *old_cl_val) |
437 |
const char *old_cl_val, int flushall) |
424 |
{ |
438 |
{ |
425 |
int seen_eos = 0, rv = 0; |
439 |
int seen_eos = 0, rv = 0; |
426 |
apr_status_t status = APR_SUCCESS; |
440 |
apr_status_t status = APR_SUCCESS; |
Lines 446-453
static int stream_reqbody_cl(apr_pool_t *p,
Link Here
|
446 |
} |
460 |
} |
447 |
terminate_headers(bucket_alloc, header_brigade); |
461 |
terminate_headers(bucket_alloc, header_brigade); |
448 |
|
462 |
|
449 |
while (!APR_BUCKET_IS_EOS(APR_BRIGADE_FIRST(input_brigade))) |
463 |
while (APR_BRIGADE_EMPTY(input_brigade) |
|
|
464 |
|| !APR_BUCKET_IS_EOS(APR_BRIGADE_FIRST(input_brigade))) |
450 |
{ |
465 |
{ |
|
|
466 |
int flush = flushall; |
467 |
|
468 |
if (!APR_BRIGADE_EMPTY(input_brigade)) { |
451 |
apr_brigade_length(input_brigade, 1, &bytes); |
469 |
apr_brigade_length(input_brigade, 1, &bytes); |
452 |
bytes_streamed += bytes; |
470 |
bytes_streamed += bytes; |
453 |
|
471 |
|
Lines 455-460
static int stream_reqbody_cl(apr_pool_t *p,
Link Here
|
455 |
if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) { |
473 |
if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) { |
456 |
seen_eos = 1; |
474 |
seen_eos = 1; |
457 |
|
475 |
|
|
|
476 |
/* Once we hit EOS, we are ready to flush. */ |
477 |
flush = 1; |
478 |
|
458 |
/* We can't pass this EOS to the output_filters. */ |
479 |
/* We can't pass this EOS to the output_filters. */ |
459 |
e = APR_BRIGADE_LAST(input_brigade); |
480 |
e = APR_BRIGADE_LAST(input_brigade); |
460 |
apr_bucket_delete(e); |
481 |
apr_bucket_delete(e); |
Lines 476-481
static int stream_reqbody_cl(apr_pool_t *p,
Link Here
|
476 |
bytes_streamed, cl_val); |
497 |
bytes_streamed, cl_val); |
477 |
return HTTP_INTERNAL_SERVER_ERROR; |
498 |
return HTTP_INTERNAL_SERVER_ERROR; |
478 |
} |
499 |
} |
|
|
500 |
} |
479 |
|
501 |
|
480 |
if (header_brigade) { |
502 |
if (header_brigade) { |
481 |
/* we never sent the header brigade, so go ahead and |
503 |
/* we never sent the header brigade, so go ahead and |
Lines 483-488
static int stream_reqbody_cl(apr_pool_t *p,
Link Here
|
483 |
*/ |
505 |
*/ |
484 |
bb = header_brigade; |
506 |
bb = header_brigade; |
485 |
|
507 |
|
|
|
508 |
/* Flush now to minimize the delay between connect (or |
509 |
* is_socket_connected) and the first bytes sent. |
510 |
*/ |
511 |
flush = 1; |
512 |
|
486 |
/* |
513 |
/* |
487 |
* Save input_brigade in bb brigade. (At least) in the SSL case |
514 |
* Save input_brigade in bb brigade. (At least) in the SSL case |
488 |
* input_brigade contains transient buckets whose data would get |
515 |
* input_brigade contains transient buckets whose data would get |
Lines 503-510
static int stream_reqbody_cl(apr_pool_t *p,
Link Here
|
503 |
bb = input_brigade; |
530 |
bb = input_brigade; |
504 |
} |
531 |
} |
505 |
|
532 |
|
506 |
/* Once we hit EOS, we are ready to flush. */ |
533 |
rv = pass_brigade(bucket_alloc, r, p_conn, origin, bb, flush); |
507 |
rv = pass_brigade(bucket_alloc, r, p_conn, origin, bb, seen_eos); |
|
|
508 |
if (rv != OK) { |
534 |
if (rv != OK) { |
509 |
return rv ; |
535 |
return rv ; |
510 |
} |
536 |
} |
Lines 689-695
int ap_proxy_http_request(apr_pool_t *p, request_r
Link Here
|
689 |
proxy_conn_rec *p_conn, conn_rec *origin, |
715 |
proxy_conn_rec *p_conn, conn_rec *origin, |
690 |
proxy_server_conf *conf, |
716 |
proxy_server_conf *conf, |
691 |
apr_uri_t *uri, |
717 |
apr_uri_t *uri, |
692 |
char *url, char *server_portstr) |
718 |
char *url, char *server_portstr, |
|
|
719 |
int flushall) |
693 |
{ |
720 |
{ |
694 |
conn_rec *c = r->connection; |
721 |
conn_rec *c = r->connection; |
695 |
apr_bucket_alloc_t *bucket_alloc = c->bucket_alloc; |
722 |
apr_bucket_alloc_t *bucket_alloc = c->bucket_alloc; |
Lines 710-715
int ap_proxy_http_request(apr_pool_t *p, request_r
Link Here
|
710 |
apr_off_t bytes; |
737 |
apr_off_t bytes; |
711 |
int force10, rv; |
738 |
int force10, rv; |
712 |
apr_table_t *headers_in_copy; |
739 |
apr_table_t *headers_in_copy; |
|
|
740 |
apr_read_type_e block; |
713 |
|
741 |
|
714 |
header_brigade = apr_brigade_create(p, bucket_alloc); |
742 |
header_brigade = apr_brigade_create(p, bucket_alloc); |
715 |
|
743 |
|
Lines 990-999
int ap_proxy_http_request(apr_pool_t *p, request_r
Link Here
|
990 |
* reasonable size. |
1018 |
* reasonable size. |
991 |
*/ |
1019 |
*/ |
992 |
temp_brigade = apr_brigade_create(p, bucket_alloc); |
1020 |
temp_brigade = apr_brigade_create(p, bucket_alloc); |
|
|
1021 |
block = (flushall) ? APR_NONBLOCK_READ : APR_BLOCK_READ; |
993 |
do { |
1022 |
do { |
994 |
status = ap_get_brigade(r->input_filters, temp_brigade, |
1023 |
status = ap_get_brigade(r->input_filters, temp_brigade, |
995 |
AP_MODE_READBYTES, APR_BLOCK_READ, |
1024 |
AP_MODE_READBYTES, block, |
996 |
MAX_MEM_SPOOL - bytes_read); |
1025 |
MAX_MEM_SPOOL - bytes_read); |
|
|
1026 |
if (block == APR_NONBLOCK_READ |
1027 |
&& (APR_STATUS_IS_EAGAIN(status) |
1028 |
|| (status == APR_SUCCESS |
1029 |
&& APR_BRIGADE_EMPTY(temp_brigade)))) { |
1030 |
break; |
1031 |
} |
997 |
if (status != APR_SUCCESS) { |
1032 |
if (status != APR_SUCCESS) { |
998 |
ap_log_error(APLOG_MARK, APLOG_ERR, status, r->server, |
1033 |
ap_log_error(APLOG_MARK, APLOG_ERR, status, r->server, |
999 |
"proxy: prefetch request body failed to %pI (%s)" |
1034 |
"proxy: prefetch request body failed to %pI (%s)" |
Lines 1031-1037
int ap_proxy_http_request(apr_pool_t *p, request_r
Link Here
|
1031 |
* (an arbitrary value.) |
1066 |
* (an arbitrary value.) |
1032 |
*/ |
1067 |
*/ |
1033 |
} while ((bytes_read < MAX_MEM_SPOOL - 80) |
1068 |
} while ((bytes_read < MAX_MEM_SPOOL - 80) |
1034 |
&& !APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))); |
1069 |
&& !APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade)) |
|
|
1070 |
&& !flushall); |
1035 |
|
1071 |
|
1036 |
/* Use chunked request body encoding or send a content-length body? |
1072 |
/* Use chunked request body encoding or send a content-length body? |
1037 |
* |
1073 |
* |
Lines 1068-1074
int ap_proxy_http_request(apr_pool_t *p, request_r
Link Here
|
1068 |
* is absent, and the filters are unchanged (the body won't |
1104 |
* is absent, and the filters are unchanged (the body won't |
1069 |
* be resized by another content filter). |
1105 |
* be resized by another content filter). |
1070 |
*/ |
1106 |
*/ |
1071 |
if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) { |
1107 |
if (!APR_BRIGADE_EMPTY(input_brigade) |
|
|
1108 |
&& APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) { |
1072 |
/* The whole thing fit, so our decision is trivial, use |
1109 |
/* The whole thing fit, so our decision is trivial, use |
1073 |
* the filtered bytes read from the client for the request |
1110 |
* the filtered bytes read from the client for the request |
1074 |
* body Content-Length. |
1111 |
* body Content-Length. |
Lines 1137-1147
skip_body:
Link Here
|
1137 |
switch(rb_method) { |
1174 |
switch(rb_method) { |
1138 |
case RB_STREAM_CHUNKED: |
1175 |
case RB_STREAM_CHUNKED: |
1139 |
rv = stream_reqbody_chunked(p, r, p_conn, origin, header_brigade, |
1176 |
rv = stream_reqbody_chunked(p, r, p_conn, origin, header_brigade, |
1140 |
input_brigade); |
1177 |
input_brigade, flushall); |
1141 |
break; |
1178 |
break; |
1142 |
case RB_STREAM_CL: |
1179 |
case RB_STREAM_CL: |
1143 |
rv = stream_reqbody_cl(p, r, p_conn, origin, header_brigade, |
1180 |
rv = stream_reqbody_cl(p, r, p_conn, origin, header_brigade, |
1144 |
input_brigade, old_cl_val); |
1181 |
input_brigade, old_cl_val, flushall); |
1145 |
break; |
1182 |
break; |
1146 |
case RB_SPOOL_CL: |
1183 |
case RB_SPOOL_CL: |
1147 |
rv = spool_reqbody_cl(p, r, p_conn, origin, header_brigade, |
1184 |
rv = spool_reqbody_cl(p, r, p_conn, origin, header_brigade, |
Lines 1937-1943
static int proxy_http_handler(request_rec *r, prox
Link Here
|
1937 |
const char *proxy_function; |
1974 |
const char *proxy_function; |
1938 |
const char *u; |
1975 |
const char *u; |
1939 |
proxy_conn_rec *backend = NULL; |
1976 |
proxy_conn_rec *backend = NULL; |
1940 |
int is_ssl = 0; |
1977 |
int is_ssl = 0, flushall = 0; |
1941 |
conn_rec *c = r->connection; |
1978 |
conn_rec *c = r->connection; |
1942 |
/* |
1979 |
/* |
1943 |
* Use a shorter-lived pool to reduce memory usage |
1980 |
* Use a shorter-lived pool to reduce memory usage |
Lines 1992-1997
static int proxy_http_handler(request_rec *r, prox
Link Here
|
1992 |
ap_proxy_ssl_connection_cleanup(backend, r); |
2029 |
ap_proxy_ssl_connection_cleanup(backend, r); |
1993 |
} |
2030 |
} |
1994 |
|
2031 |
|
|
|
2032 |
if (apr_table_get(r->subprocess_env, "proxy-flushall")) { |
2033 |
flushall = 1; |
2034 |
} |
2035 |
|
1995 |
/* |
2036 |
/* |
1996 |
* In the case that we are handling a reverse proxy connection and this |
2037 |
* In the case that we are handling a reverse proxy connection and this |
1997 |
* is not a request that is coming over an already kept alive connection |
2038 |
* is not a request that is coming over an already kept alive connection |
Lines 2050-2056
static int proxy_http_handler(request_rec *r, prox
Link Here
|
2050 |
|
2091 |
|
2051 |
/* Step Four: Send the Request */ |
2092 |
/* Step Four: Send the Request */ |
2052 |
if ((status = ap_proxy_http_request(p, r, backend, backend->connection, |
2093 |
if ((status = ap_proxy_http_request(p, r, backend, backend->connection, |
2053 |
conf, uri, url, server_portstr)) != OK) |
2094 |
conf, uri, url, server_portstr, |
|
|
2095 |
flushall)) != OK) |
2054 |
goto cleanup; |
2096 |
goto cleanup; |
2055 |
|
2097 |
|
2056 |
/* Step Five: Receive the Response */ |
2098 |
/* Step Five: Receive the Response */ |