View | Details | Raw Unified | Return to bug 56541
Collapse All | Expand All

(-)modules/proxy/mod_proxy_http.c (-15 / +57 lines)
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 */

Return to bug 56541