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) {

Reply via email to