On 12/03/2007 06:52 PM, Pavel Stano wrote:
> Ruediger Pluem wrote:
>> On 12/03/2007 05:54 PM, Pavel Stano wrote:
>>> Plüm wrote:
>>>>> -----Ursprüngliche Nachricht-----
>>>>> Von: Pavel Stano
>>>>> Gesendet: Montag, 3. Dezember 2007 09:53
>>>>> An: [email protected]
>>>>> Betreff: apache 2.2 mod_proxy_http disable buffering
>>>>>
>>>>>
>>>>> hello,
>>>>>
>>>>> it is possible to disable buffering in mod_proxy_http ?
>>>>> or something like flush after each received data (i want this
>>>> At least with 2.2.6 (possibly earlier 2.2.x versions) it has autoflushing.
>>>> This means once there is no more data available for reading in the response
>>>> stream from the backend it flushes what it got so far. So if your php
>>>> script
>>>> on the backend generates its response in blocks with pause times between
>>>> them
>>>> each of them will be send to the client immediately.
>>>>
>>>> Regards
>>>>
>>>> Rüdiger
>>> i have 2.2.6, but it dont work, proxy send me data after end of request
>>>
>>> i have very simple php script (or .cgi, i try it too)
>>> <?php
>>> echo 'A';
>>> echo 'B';
>>> sleep(5);
>>> echo 'C';
>>> ?>
>>> php buffering is configured ok, when i connect with telnet to backend
>>> server a request a.php, it work as expected
>>> it show immedietaly headers and AB and after 5 second it show C and
>>> close connection
>>>
>>> when i connect to reverse proxy and request a.php, 5 second is silent
>>> and after that it send me response
>>>
>>> maybe a bug in mod_proxy_http ? (or not a bug but broken feature :))
You are correct. This is only fixed in trunk so far. You are affected by
PR41056 (https://issues.apache.org/bugzilla/show_bug.cgi?id=41056).
I just proposed the patch from trunk for backport. Please find the
patch attached for your convenience.
Regards
Rüdiger
Index: modules/http/http_filters.c
===================================================================
--- modules/http/http_filters.c (Revision 600596)
+++ modules/http/http_filters.c (Arbeitskopie)
@@ -64,7 +64,8 @@
enum {
BODY_NONE,
BODY_LENGTH,
- BODY_CHUNK
+ BODY_CHUNK,
+ BODY_CHUNK_PART
} state;
int eos_sent;
} http_ctx_t;
@@ -212,8 +213,15 @@
bb = apr_brigade_create(f->r->pool, f->c->bucket_alloc);
rv = ap_get_brigade(f->next, bb, AP_MODE_GETLINE,
- APR_BLOCK_READ, 0);
+ block, 0);
+ /* for timeout */
+ if (block == APR_NONBLOCK_READ &&
+ ( (rv == APR_SUCCESS && APR_BRIGADE_EMPTY(bb)) ||
+ (APR_STATUS_IS_EAGAIN(rv)) )) {
+ return APR_EAGAIN;
+ }
+
if (rv == APR_SUCCESS) {
/* We have to check the length of the brigade we got back.
* We will not accept partial or blank lines.
@@ -274,7 +282,7 @@
APR_BRIGADE_INSERT_TAIL(b, e);
ctx->eos_sent = 1;
return APR_SUCCESS;
- case BODY_CHUNK:
+ case BODY_CHUNK: case BODY_CHUNK_PART:
{
char line[30];
apr_bucket_brigade *bb;
@@ -284,14 +292,30 @@
bb = apr_brigade_create(f->r->pool, f->c->bucket_alloc);
/* We need to read the CRLF after the chunk. */
- rv = ap_get_brigade(f->next, bb, AP_MODE_GETLINE,
- APR_BLOCK_READ, 0);
- apr_brigade_cleanup(bb);
+ if (ctx->state == BODY_CHUNK) {
+ rv = ap_get_brigade(f->next, bb, AP_MODE_GETLINE,
+ block, 0);
+ apr_brigade_cleanup(bb);
+ if (block == APR_NONBLOCK_READ &&
+ (APR_STATUS_IS_EAGAIN(rv))) {
+ return APR_EAGAIN;
+ }
+ } else {
+ rv = APR_SUCCESS;
+ }
if (rv == APR_SUCCESS) {
/* Read the real chunk line. */
rv = ap_get_brigade(f->next, bb, AP_MODE_GETLINE,
- APR_BLOCK_READ, 0);
+ block, 0);
+ /* Test timeout */
+ if (block == APR_NONBLOCK_READ &&
+ ( (rv == APR_SUCCESS && APR_BRIGADE_EMPTY(bb)) ||
+ (APR_STATUS_IS_EAGAIN(rv)) )) {
+ ctx->state = BODY_CHUNK_PART;
+ return APR_EAGAIN;
+ }
+ ctx->state = BODY_CHUNK;
if (rv == APR_SUCCESS) {
rv = apr_brigade_flatten(bb, line, &len);
if (rv == APR_SUCCESS) {