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

(-)modules/proxy/proxy_util.c (-1 / +3 lines)
Lines 3235-3241 PROXY_DECLARE(int) ap_proxy_create_hdrbrgd(apr_poo Link Here
3235
        buf = apr_pstrcat(p, r->method, " ", url, " HTTP/1.1" CRLF, NULL);
3235
        buf = apr_pstrcat(p, r->method, " ", url, " HTTP/1.1" CRLF, NULL);
3236
    }
3236
    }
3237
    if (apr_table_get(r->subprocess_env, "proxy-nokeepalive")) {
3237
    if (apr_table_get(r->subprocess_env, "proxy-nokeepalive")) {
3238
        origin->keepalive = AP_CONN_CLOSE;
3238
        if (origin) {
3239
            origin->keepalive = AP_CONN_CLOSE;
3240
        }
3239
        p_conn->close = 1;
3241
        p_conn->close = 1;
3240
    }
3242
    }
3241
    ap_xlate_proto_to_ascii(buf, strlen(buf));
3243
    ap_xlate_proto_to_ascii(buf, strlen(buf));
(-)modules/proxy/mod_proxy_http.c (-83 / +242 lines)
Lines 234-240 static int stream_reqbody_chunked(apr_pool_t *p, Link Here
234
                                           proxy_conn_rec *p_conn,
234
                                           proxy_conn_rec *p_conn,
235
                                           conn_rec *origin,
235
                                           conn_rec *origin,
236
                                           apr_bucket_brigade *header_brigade,
236
                                           apr_bucket_brigade *header_brigade,
237
                                           apr_bucket_brigade *input_brigade)
237
                                           apr_bucket_brigade *input_brigade,
238
                                           int flushall)
238
{
239
{
239
    int seen_eos = 0, rv = OK;
240
    int seen_eos = 0, rv = OK;
240
    apr_size_t hdr_len;
241
    apr_size_t hdr_len;
Lines 247-260 static int stream_reqbody_chunked(apr_pool_t *p, Link Here
247
    add_te_chunked(p, bucket_alloc, header_brigade);
248
    add_te_chunked(p, bucket_alloc, header_brigade);
248
    terminate_headers(bucket_alloc, header_brigade);
249
    terminate_headers(bucket_alloc, header_brigade);
249
250
250
    while (!APR_BUCKET_IS_EOS(APR_BRIGADE_FIRST(input_brigade)))
251
    while (APR_BRIGADE_EMPTY(input_brigade) ||
252
            !APR_BUCKET_IS_EOS(APR_BRIGADE_FIRST(input_brigade)))
251
    {
253
    {
252
        char chunk_hdr[20];  /* must be here due to transient bucket. */
254
        char chunk_hdr[20];  /* must be here due to transient bucket. */
255
        int flush = flushall;
253
256
257
        if (!APR_BRIGADE_EMPTY(input_brigade)) {
258
254
        /* If this brigade contains EOS, either stop or remove it. */
259
        /* If this brigade contains EOS, either stop or remove it. */
255
        if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) {
260
        if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) {
256
            seen_eos = 1;
261
            seen_eos = 1;
257
262
263
            /* The request is flushed below this loop with the EOS chunk */
264
            flush = 0;
265
258
            /* We can't pass this EOS to the output_filters. */
266
            /* We can't pass this EOS to the output_filters. */
259
            e = APR_BRIGADE_LAST(input_brigade);
267
            e = APR_BRIGADE_LAST(input_brigade);
260
            apr_bucket_delete(e);
268
            apr_bucket_delete(e);
Lines 276-281 static int stream_reqbody_chunked(apr_pool_t *p, Link Here
276
         */
284
         */
277
        e = apr_bucket_immortal_create(ASCII_CRLF, 2, bucket_alloc);
285
        e = apr_bucket_immortal_create(ASCII_CRLF, 2, bucket_alloc);
278
        APR_BRIGADE_INSERT_TAIL(input_brigade, e);
286
        APR_BRIGADE_INSERT_TAIL(input_brigade, e);
287
        }
279
288
280
        if (header_brigade) {
289
        if (header_brigade) {
281
            /* we never sent the header brigade, so go ahead and
290
            /* we never sent the header brigade, so go ahead and
Lines 283-288 static int stream_reqbody_chunked(apr_pool_t *p, Link Here
283
             */
292
             */
284
            bb = header_brigade;
293
            bb = header_brigade;
285
294
295
            /* Flush the prefeched data now to minimize the delay between
296
             * connect (or ap_proxy_is_socket_connected) and the first bytes
297
             * sent, unless it is done below this loop with the EOS chunk.
298
             */
299
            flush = !seen_eos;
300
286
            /*
301
            /*
287
             * Save input_brigade in bb brigade. (At least) in the SSL case
302
             * Save input_brigade in bb brigade. (At least) in the SSL case
288
             * input_brigade contains transient buckets whose data would get
303
             * input_brigade contains transient buckets whose data would get
Lines 303-310 static int stream_reqbody_chunked(apr_pool_t *p, Link Here
303
            bb = input_brigade;
318
            bb = input_brigade;
304
        }
319
        }
305
320
306
        /* The request is flushed below this loop with chunk EOS header */
321
        rv = ap_proxy_pass_brigade(bucket_alloc, r, p_conn, origin, bb, flush);
307
        rv = ap_proxy_pass_brigade(bucket_alloc, r, p_conn, origin, bb, 0);
308
        if (rv != OK) {
322
        if (rv != OK) {
309
            return rv;
323
            return rv;
310
        }
324
        }
Lines 366-372 static int stream_reqbody_cl(apr_pool_t *p, Link Here
366
                                      conn_rec *origin,
380
                                      conn_rec *origin,
367
                                      apr_bucket_brigade *header_brigade,
381
                                      apr_bucket_brigade *header_brigade,
368
                                      apr_bucket_brigade *input_brigade,
382
                                      apr_bucket_brigade *input_brigade,
369
                                      char *old_cl_val)
383
                                      char *old_cl_val, int flushall)
370
{
384
{
371
    int seen_eos = 0, rv = 0;
385
    int seen_eos = 0, rv = 0;
372
    apr_status_t status = APR_SUCCESS;
386
    apr_status_t status = APR_SUCCESS;
Lines 392-399 static int stream_reqbody_cl(apr_pool_t *p, Link Here
392
    }
406
    }
393
    terminate_headers(bucket_alloc, header_brigade);
407
    terminate_headers(bucket_alloc, header_brigade);
394
408
395
    while (!APR_BUCKET_IS_EOS(APR_BRIGADE_FIRST(input_brigade)))
409
    while (APR_BRIGADE_EMPTY(input_brigade) ||
410
            !APR_BUCKET_IS_EOS(APR_BRIGADE_FIRST(input_brigade)))
396
    {
411
    {
412
        int flush = flushall;
413
414
        if (!APR_BRIGADE_EMPTY(input_brigade)) {
397
        apr_brigade_length(input_brigade, 1, &bytes);
415
        apr_brigade_length(input_brigade, 1, &bytes);
398
        bytes_streamed += bytes;
416
        bytes_streamed += bytes;
399
417
Lines 401-406 static int stream_reqbody_cl(apr_pool_t *p, Link Here
401
        if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) {
419
        if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) {
402
            seen_eos = 1;
420
            seen_eos = 1;
403
421
422
            /* Once we hit EOS, we are ready to flush. */
423
            flush = 1;
424
404
            /* We can't pass this EOS to the output_filters. */
425
            /* We can't pass this EOS to the output_filters. */
405
            e = APR_BRIGADE_LAST(input_brigade);
426
            e = APR_BRIGADE_LAST(input_brigade);
406
            apr_bucket_delete(e);
427
            apr_bucket_delete(e);
Lines 427-432 static int stream_reqbody_cl(apr_pool_t *p, Link Here
427
                          bytes_streamed, cl_val);
448
                          bytes_streamed, cl_val);
428
            return HTTP_INTERNAL_SERVER_ERROR;
449
            return HTTP_INTERNAL_SERVER_ERROR;
429
        }
450
        }
451
        }
430
452
431
        if (header_brigade) {
453
        if (header_brigade) {
432
            /* we never sent the header brigade, so go ahead and
454
            /* we never sent the header brigade, so go ahead and
Lines 434-439 static int stream_reqbody_cl(apr_pool_t *p, Link Here
434
             */
456
             */
435
            bb = header_brigade;
457
            bb = header_brigade;
436
458
459
            /* Flush prefeched data now to minimize the delay between connect,
460
             * or ap_proxy_is_socket_connected, and the first bytes sent.
461
             */
462
            flush = 1;
463
437
            /*
464
            /*
438
             * Save input_brigade in bb brigade. (At least) in the SSL case
465
             * Save input_brigade in bb brigade. (At least) in the SSL case
439
             * input_brigade contains transient buckets whose data would get
466
             * input_brigade contains transient buckets whose data would get
Lines 454-463 static int stream_reqbody_cl(apr_pool_t *p, Link Here
454
            bb = input_brigade;
481
            bb = input_brigade;
455
        }
482
        }
456
483
457
        /* Once we hit EOS, we are ready to flush. */
484
        rv = ap_proxy_pass_brigade(bucket_alloc, r, p_conn, origin, bb, flush);
458
        rv = ap_proxy_pass_brigade(bucket_alloc, r, p_conn, origin, bb, seen_eos);
459
        if (rv != OK) {
485
        if (rv != OK) {
460
            return rv ;
486
            return rv;
461
        }
487
        }
462
488
463
        if (seen_eos) {
489
        if (seen_eos) {
Lines 499-506 static int stream_reqbody_cl(apr_pool_t *p, Link Here
499
525
500
static int spool_reqbody_cl(apr_pool_t *p,
526
static int spool_reqbody_cl(apr_pool_t *p,
501
                                     request_rec *r,
527
                                     request_rec *r,
502
                                     proxy_conn_rec *p_conn,
503
                                     conn_rec *origin,
504
                                     apr_bucket_brigade *header_brigade,
528
                                     apr_bucket_brigade *header_brigade,
505
                                     apr_bucket_brigade *input_brigade,
529
                                     apr_bucket_brigade *input_brigade,
506
                                     int force_cl)
530
                                     int force_cl)
Lines 518-525 static int spool_reqbody_cl(apr_pool_t *p, Link Here
518
542
519
    limit = ap_get_limit_req_body(r);
543
    limit = ap_get_limit_req_body(r);
520
544
521
    while (!APR_BUCKET_IS_EOS(APR_BRIGADE_FIRST(input_brigade)))
545
    while (APR_BRIGADE_EMPTY(input_brigade) ||
546
            !APR_BUCKET_IS_EOS(APR_BRIGADE_FIRST(input_brigade)))
522
    {
547
    {
548
        if (!APR_BRIGADE_EMPTY(input_brigade)) {
523
        /* If this brigade contains EOS, either stop or remove it. */
549
        /* If this brigade contains EOS, either stop or remove it. */
524
        if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) {
550
        if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) {
525
            seen_eos = 1;
551
            seen_eos = 1;
Lines 612-617 static int spool_reqbody_cl(apr_pool_t *p, Link Here
612
        if (seen_eos) {
638
        if (seen_eos) {
613
            break;
639
            break;
614
        }
640
        }
641
        }
615
642
616
        status = ap_get_brigade(r->input_filters, input_brigade,
643
        status = ap_get_brigade(r->input_filters, input_brigade,
617
                                AP_MODE_READBYTES, APR_BLOCK_READ,
644
                                AP_MODE_READBYTES, APR_BLOCK_READ,
Lines 620-628 static int spool_reqbody_cl(apr_pool_t *p, Link Here
620
        if (status != APR_SUCCESS) {
647
        if (status != APR_SUCCESS) {
621
            conn_rec *c = r->connection;
648
            conn_rec *c = r->connection;
622
            ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(02610)
649
            ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(02610)
623
                          "read request body failed to %pI (%s)"
650
                          "read request body failed from %s (%s)",
624
                          " from %s (%s)", p_conn->addr,
625
                          p_conn->hostname ? p_conn->hostname: "",
626
                          c->client_ip, c->remote_host ? c->remote_host: "");
651
                          c->client_ip, c->remote_host ? c->remote_host: "");
627
            return HTTP_BAD_REQUEST;
652
            return HTTP_BAD_REQUEST;
628
        }
653
        }
Lines 640-647 static int spool_reqbody_cl(apr_pool_t *p, Link Here
640
        e = apr_bucket_immortal_create(ASCII_CRLF, 2, bucket_alloc);
665
        e = apr_bucket_immortal_create(ASCII_CRLF, 2, bucket_alloc);
641
        APR_BRIGADE_INSERT_TAIL(header_brigade, e);
666
        APR_BRIGADE_INSERT_TAIL(header_brigade, e);
642
    }
667
    }
643
    /* This is all a single brigade, pass with flush flagged */
668
    return OK;
644
    return(ap_proxy_pass_brigade(bucket_alloc, r, p_conn, origin, header_brigade, 1));
645
}
669
}
646
670
647
/*
671
/*
Lines 654-661 static int spool_reqbody_cl(apr_pool_t *p, Link Here
654
 * FLUSH
678
 * FLUSH
655
 * EOS
679
 * EOS
656
 *
680
 *
657
 * If an other bucket type is found its type is logged as a debug message
681
 * If an other bucket type is found its type is logged as an error message
658
 * and APR_EGENERAL is returned.
682
 * and APR_INCOMPLETE is returned.
659
 */
683
 */
660
static apr_status_t proxy_buckets_lifetime_transform(request_rec *r,
684
static apr_status_t proxy_buckets_lifetime_transform(request_rec *r,
661
        apr_bucket_brigade *from, apr_bucket_brigade *to)
685
        apr_bucket_brigade *from, apr_bucket_brigade *to)
Lines 664-720 static apr_status_t proxy_buckets_lifetime_transfo Link Here
664
    apr_bucket *new;
688
    apr_bucket *new;
665
    const char *data;
689
    const char *data;
666
    apr_size_t bytes;
690
    apr_size_t bytes;
667
    apr_status_t rv = APR_SUCCESS;
691
    apr_status_t status, rv = APR_SUCCESS;
692
    int to_ancestor = apr_pool_is_ancestor(to->p, from->p);
668
693
669
    apr_brigade_cleanup(to);
694
    apr_brigade_cleanup(to);
670
    for (e = APR_BRIGADE_FIRST(from);
695
    for (e = APR_BRIGADE_FIRST(from);
671
         e != APR_BRIGADE_SENTINEL(from);
696
         e != APR_BRIGADE_SENTINEL(from);
672
         e = APR_BUCKET_NEXT(e)) {
697
         e = APR_BUCKET_NEXT(e)) {
673
        if (!APR_BUCKET_IS_METADATA(e)) {
698
        if (!APR_BUCKET_IS_METADATA(e)) {
674
            apr_bucket_read(e, &data, &bytes, APR_BLOCK_READ);
699
            if (to_ancestor && e->list == to->bucket_alloc) {
675
            new = apr_bucket_transient_create(data, bytes, r->connection->bucket_alloc);
700
                status = apr_bucket_copy(e, &new);
701
                if (status != APR_SUCCESS) {
702
                    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO()
703
                                  "Can't copy bucket of type %s in"
704
                                  " proxy_buckets_lifetime_transform",
705
                                  e->type->name);
706
                    return status;
707
                }
708
            }
709
            else {
710
                status = apr_bucket_read(e, &data, &bytes, APR_BLOCK_READ);
711
                if (status != APR_SUCCESS) {
712
                    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO()
713
                                  "Can't read bucket of type %s in"
714
                                  " proxy_buckets_lifetime_transform",
715
                                  e->type->name);
716
                    return status;
717
                }
718
                new = apr_bucket_transient_create(data, bytes,
719
                                                  to->bucket_alloc);
720
            }
676
            APR_BRIGADE_INSERT_TAIL(to, new);
721
            APR_BRIGADE_INSERT_TAIL(to, new);
677
        }
722
        }
678
        else if (APR_BUCKET_IS_FLUSH(e)) {
723
        else if (APR_BUCKET_IS_FLUSH(e)) {
679
            new = apr_bucket_flush_create(r->connection->bucket_alloc);
724
            new = apr_bucket_flush_create(to->bucket_alloc);
680
            APR_BRIGADE_INSERT_TAIL(to, new);
725
            APR_BRIGADE_INSERT_TAIL(to, new);
681
        }
726
        }
682
        else if (APR_BUCKET_IS_EOS(e)) {
727
        else if (APR_BUCKET_IS_EOS(e)) {
683
            new = apr_bucket_eos_create(r->connection->bucket_alloc);
728
            new = apr_bucket_eos_create(to->bucket_alloc);
684
            APR_BRIGADE_INSERT_TAIL(to, new);
729
            APR_BRIGADE_INSERT_TAIL(to, new);
685
        }
730
        }
686
        else {
731
        else {
687
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00964)
732
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00964)
688
                          "Unhandled bucket type of type %s in"
733
                          "Unhandled bucket of type %s in"
689
                          " proxy_buckets_lifetime_transform", e->type->name);
734
                          " proxy_buckets_lifetime_transform",
690
            rv = APR_EGENERAL;
735
                          e->type->name);
736
            rv = APR_INCOMPLETE;
691
        }
737
        }
692
    }
738
    }
693
    return rv;
739
    return rv;
694
}
740
}
695
741
696
static
742
enum rb_methods {
697
int ap_proxy_http_request(apr_pool_t *p, request_rec *r,
743
    RB_INIT,
698
                                   proxy_conn_rec *p_conn, proxy_worker *worker,
744
    RB_STREAM_CL,
699
                                   proxy_server_conf *conf,
745
    RB_STREAM_CHUNKED,
700
                                   apr_uri_t *uri,
746
    RB_SPOOL_CL
701
                                   char *url, char *server_portstr)
747
};
748
749
static int ap_proxy_http_prefetch(apr_pool_t *p, request_rec *r,
750
                                  proxy_conn_rec *p_conn, proxy_worker *worker,
751
                                  proxy_server_conf *conf,
752
                                  apr_uri_t *uri,
753
                                  char *url, char *server_portstr,
754
                                  apr_bucket_brigade *header_brigade,
755
                                  apr_bucket_brigade *input_brigade,
756
                                  char **old_cl_val, char **old_te_val,
757
                                  enum rb_methods *rb_method, int flushall)
702
{
758
{
703
    conn_rec *c = r->connection;
759
    conn_rec *c = r->connection;
704
    apr_bucket_alloc_t *bucket_alloc = c->bucket_alloc;
760
    apr_bucket_alloc_t *bucket_alloc = c->bucket_alloc;
705
    apr_bucket_brigade *header_brigade;
706
    apr_bucket_brigade *input_brigade;
707
    apr_bucket_brigade *temp_brigade;
761
    apr_bucket_brigade *temp_brigade;
708
    apr_bucket *e;
762
    apr_bucket *e;
709
    char *buf;
763
    char *buf;
710
    apr_status_t status;
764
    apr_status_t status;
711
    enum rb_methods {RB_INIT, RB_STREAM_CL, RB_STREAM_CHUNKED, RB_SPOOL_CL};
712
    enum rb_methods rb_method = RB_INIT;
713
    char *old_cl_val = NULL;
714
    char *old_te_val = NULL;
715
    apr_off_t bytes_read = 0;
765
    apr_off_t bytes_read = 0;
716
    apr_off_t bytes;
766
    apr_off_t bytes;
717
    int force10, rv;
767
    int force10, rv;
768
    apr_read_type_e block;
718
    conn_rec *origin = p_conn->connection;
769
    conn_rec *origin = p_conn->connection;
719
770
720
    if (apr_table_get(r->subprocess_env, "force-proxy-request-1.0")) {
771
    if (apr_table_get(r->subprocess_env, "force-proxy-request-1.0")) {
Lines 726-742 static apr_status_t proxy_buckets_lifetime_transfo Link Here
726
        force10 = 0;
777
        force10 = 0;
727
    }
778
    }
728
779
729
    header_brigade = apr_brigade_create(p, bucket_alloc);
730
    rv = ap_proxy_create_hdrbrgd(p, header_brigade, r, p_conn,
780
    rv = ap_proxy_create_hdrbrgd(p, header_brigade, r, p_conn,
731
                                 worker, conf, uri, url, server_portstr,
781
                                 worker, conf, uri, url, server_portstr,
732
                                 &old_cl_val, &old_te_val);
782
                                 old_cl_val, old_te_val);
733
    if (rv != OK) {
783
    if (rv != OK) {
734
        return rv;
784
        return rv;
735
    }
785
    }
736
786
737
    /* We have headers, let's figure out our request body... */
738
    input_brigade = apr_brigade_create(p, bucket_alloc);
739
740
    /* sub-requests never use keepalives, and mustn't pass request bodies.
787
    /* sub-requests never use keepalives, and mustn't pass request bodies.
741
     * Because the new logic looks at input_brigade, we will self-terminate
788
     * Because the new logic looks at input_brigade, we will self-terminate
742
     * input_brigade and jump past all of the request body logic...
789
     * input_brigade and jump past all of the request body logic...
Lines 749-757 static apr_status_t proxy_buckets_lifetime_transfo Link Here
749
    if (!r->kept_body && r->main) {
796
    if (!r->kept_body && r->main) {
750
        /* XXX: Why DON'T sub-requests use keepalives? */
797
        /* XXX: Why DON'T sub-requests use keepalives? */
751
        p_conn->close = 1;
798
        p_conn->close = 1;
752
        old_cl_val = NULL;
799
        *old_cl_val = NULL;
753
        old_te_val = NULL;
800
        *old_te_val = NULL;
754
        rb_method = RB_STREAM_CL;
801
        *rb_method = RB_STREAM_CL;
755
        e = apr_bucket_eos_create(input_brigade->bucket_alloc);
802
        e = apr_bucket_eos_create(input_brigade->bucket_alloc);
756
        APR_BRIGADE_INSERT_TAIL(input_brigade, e);
803
        APR_BRIGADE_INSERT_TAIL(input_brigade, e);
757
        goto skip_body;
804
        goto skip_body;
Lines 765-782 static apr_status_t proxy_buckets_lifetime_transfo Link Here
765
     * encoding has been done by the extensions' handler, and
812
     * encoding has been done by the extensions' handler, and
766
     * do not modify add_te_chunked's logic
813
     * do not modify add_te_chunked's logic
767
     */
814
     */
768
    if (old_te_val && strcasecmp(old_te_val, "chunked") != 0) {
815
    if (*old_te_val && strcasecmp(*old_te_val, "chunked") != 0) {
769
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01093)
816
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01093)
770
                      "%s Transfer-Encoding is not supported", old_te_val);
817
                      "%s Transfer-Encoding is not supported", *old_te_val);
771
        return HTTP_INTERNAL_SERVER_ERROR;
818
        return HTTP_INTERNAL_SERVER_ERROR;
772
    }
819
    }
773
820
774
    if (old_cl_val && old_te_val) {
821
    if (*old_cl_val && *old_te_val) {
775
        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01094)
822
        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01094)
776
                      "client %s (%s) requested Transfer-Encoding "
823
                      "client %s (%s) requested Transfer-Encoding "
777
                      "chunked body with Content-Length (C-L ignored)",
824
                      "chunked body with Content-Length (C-L ignored)",
778
                      c->client_ip, c->remote_host ? c->remote_host: "");
825
                      c->client_ip, c->remote_host ? c->remote_host: "");
779
        old_cl_val = NULL;
826
        *old_cl_val = NULL;
780
        origin->keepalive = AP_CONN_CLOSE;
827
        origin->keepalive = AP_CONN_CLOSE;
781
        p_conn->close = 1;
828
        p_conn->close = 1;
782
    }
829
    }
Lines 790-799 static apr_status_t proxy_buckets_lifetime_transfo Link Here
790
     * reasonable size.
837
     * reasonable size.
791
     */
838
     */
792
    temp_brigade = apr_brigade_create(p, bucket_alloc);
839
    temp_brigade = apr_brigade_create(p, bucket_alloc);
840
    block = (flushall) ? APR_NONBLOCK_READ : APR_BLOCK_READ;
793
    do {
841
    do {
794
        status = ap_get_brigade(r->input_filters, temp_brigade,
842
        status = ap_get_brigade(r->input_filters, temp_brigade,
795
                                AP_MODE_READBYTES, APR_BLOCK_READ,
843
                                AP_MODE_READBYTES, block,
796
                                MAX_MEM_SPOOL - bytes_read);
844
                                MAX_MEM_SPOOL - bytes_read);
845
        /* ap_get_brigade will return success with an empty brigade
846
         * for a non-blocking read which would block
847
         */
848
        if (block == APR_NONBLOCK_READ
849
            && (APR_STATUS_IS_EAGAIN(status)
850
                || (status == APR_SUCCESS && APR_BRIGADE_EMPTY(temp_brigade)))) {
851
            break;
852
        }
797
        if (status != APR_SUCCESS) {
853
        if (status != APR_SUCCESS) {
798
            ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(01095)
854
            ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(01095)
799
                          "prefetch request body failed to %pI (%s)"
855
                          "prefetch request body failed to %pI (%s)"
Lines 831-837 static apr_status_t proxy_buckets_lifetime_transfo Link Here
831
     * (an arbitrary value.)
887
     * (an arbitrary value.)
832
     */
888
     */
833
    } while ((bytes_read < MAX_MEM_SPOOL - 80)
889
    } while ((bytes_read < MAX_MEM_SPOOL - 80)
834
              && !APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade)));
890
              && !APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))
891
              && !flushall);
835
892
836
    /* Use chunked request body encoding or send a content-length body?
893
    /* Use chunked request body encoding or send a content-length body?
837
     *
894
     *
Lines 868-874 static apr_status_t proxy_buckets_lifetime_transfo Link Here
868
     * is absent, and the filters are unchanged (the body won't
925
     * is absent, and the filters are unchanged (the body won't
869
     * be resized by another content filter).
926
     * be resized by another content filter).
870
     */
927
     */
871
    if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) {
928
    if (!APR_BRIGADE_EMPTY(input_brigade) &&
929
            APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) {
872
        /* The whole thing fit, so our decision is trivial, use
930
        /* The whole thing fit, so our decision is trivial, use
873
         * the filtered bytes read from the client for the request
931
         * the filtered bytes read from the client for the request
874
         * body Content-Length.
932
         * body Content-Length.
Lines 876-919 static apr_status_t proxy_buckets_lifetime_transfo Link Here
876
         * If we expected no body, and read no body, do not set
934
         * If we expected no body, and read no body, do not set
877
         * the Content-Length.
935
         * the Content-Length.
878
         */
936
         */
879
        if (old_cl_val || old_te_val || bytes_read) {
937
        if (*old_cl_val || *old_te_val || bytes_read) {
880
            old_cl_val = apr_off_t_toa(r->pool, bytes_read);
938
            *old_cl_val = apr_off_t_toa(r->pool, bytes_read);
881
        }
939
        }
882
        rb_method = RB_STREAM_CL;
940
        *rb_method = RB_STREAM_CL;
883
    }
941
    }
884
    else if (old_te_val) {
942
    else if (*old_te_val) {
885
        if (force10
943
        if (force10
886
             || (apr_table_get(r->subprocess_env, "proxy-sendcl")
944
             || (apr_table_get(r->subprocess_env, "proxy-sendcl")
887
                  && !apr_table_get(r->subprocess_env, "proxy-sendchunks")
945
                  && !apr_table_get(r->subprocess_env, "proxy-sendchunks")
888
                  && !apr_table_get(r->subprocess_env, "proxy-sendchunked"))) {
946
                  && !apr_table_get(r->subprocess_env, "proxy-sendchunked"))) {
889
            rb_method = RB_SPOOL_CL;
947
            *rb_method = RB_SPOOL_CL;
890
        }
948
        }
891
        else {
949
        else {
892
            rb_method = RB_STREAM_CHUNKED;
950
            *rb_method = RB_STREAM_CHUNKED;
893
        }
951
        }
894
    }
952
    }
895
    else if (old_cl_val) {
953
    else if (*old_cl_val) {
896
        if (r->input_filters == r->proto_input_filters) {
954
        if (r->input_filters == r->proto_input_filters) {
897
            rb_method = RB_STREAM_CL;
955
            *rb_method = RB_STREAM_CL;
898
        }
956
        }
899
        else if (!force10
957
        else if (!force10
900
                  && (apr_table_get(r->subprocess_env, "proxy-sendchunks")
958
                  && (apr_table_get(r->subprocess_env, "proxy-sendchunks")
901
                      || apr_table_get(r->subprocess_env, "proxy-sendchunked"))
959
                      || apr_table_get(r->subprocess_env, "proxy-sendchunked"))
902
                  && !apr_table_get(r->subprocess_env, "proxy-sendcl")) {
960
                  && !apr_table_get(r->subprocess_env, "proxy-sendcl")) {
903
            rb_method = RB_STREAM_CHUNKED;
961
            *rb_method = RB_STREAM_CHUNKED;
904
        }
962
        }
905
        else {
963
        else {
906
            rb_method = RB_SPOOL_CL;
964
            *rb_method = RB_SPOOL_CL;
907
        }
965
        }
908
    }
966
    }
909
    else {
967
    else {
910
        /* This is an appropriate default; very efficient for no-body
968
        /* This is an appropriate default; very efficient for no-body
911
         * requests, and has the behavior that it will not add any C-L
969
         * requests, and has the behavior that it will not add any C-L
912
         * when the old_cl_val is NULL.
970
         * when the *old_cl_val is NULL.
913
         */
971
         */
914
        rb_method = RB_SPOOL_CL;
972
        *rb_method = RB_SPOOL_CL;
915
    }
973
    }
916
974
975
    /* If we have to spool the body, do it now, before connecting/reusing
976
     * the backend connection, not in the connect/reuse-then-forward window.
977
     */
978
    if (*rb_method == RB_SPOOL_CL) {
979
        rv = spool_reqbody_cl(p, r, header_brigade, input_brigade,
980
                              (bytes_read > 0)
981
                              || (*old_cl_val != NULL)
982
                              || (*old_te_val != NULL));
983
        if (rv != OK) {
984
            return rv;
985
        }
986
    }
987
917
/* Yes I hate gotos.  This is the subrequest shortcut */
988
/* Yes I hate gotos.  This is the subrequest shortcut */
918
skip_body:
989
skip_body:
919
    /*
990
    /*
Lines 933-953 skip_body: Link Here
933
        APR_BRIGADE_INSERT_TAIL(header_brigade, e);
1004
        APR_BRIGADE_INSERT_TAIL(header_brigade, e);
934
    }
1005
    }
935
1006
1007
    return OK;
1008
}
1009
1010
static
1011
int ap_proxy_http_request(apr_pool_t *p, request_rec *r,
1012
                                   proxy_conn_rec *p_conn,
1013
                                   apr_bucket_brigade *header_brigade,
1014
                                   apr_bucket_brigade *input_brigade,
1015
                                   char *old_cl_val, char *old_te_val,
1016
                                   enum rb_methods rb_method, int flushall)
1017
{
1018
    int rv;
1019
    conn_rec *origin = p_conn->connection;
1020
936
    /* send the request body, if any. */
1021
    /* send the request body, if any. */
937
    switch(rb_method) {
1022
    switch(rb_method) {
938
    case RB_STREAM_CHUNKED:
1023
    case RB_STREAM_CHUNKED:
939
        rv = stream_reqbody_chunked(p, r, p_conn, origin, header_brigade,
1024
        rv = stream_reqbody_chunked(p, r, p_conn, origin, header_brigade,
940
                                        input_brigade);
1025
                                    input_brigade, flushall);
941
        break;
1026
        break;
942
    case RB_STREAM_CL:
1027
    case RB_STREAM_CL:
943
        rv = stream_reqbody_cl(p, r, p_conn, origin, header_brigade,
1028
        rv = stream_reqbody_cl(p, r, p_conn, origin, header_brigade,
944
                                   input_brigade, old_cl_val);
1029
                               input_brigade, old_cl_val, flushall);
945
        break;
1030
        break;
946
    case RB_SPOOL_CL:
1031
    case RB_SPOOL_CL:
947
        rv = spool_reqbody_cl(p, r, p_conn, origin, header_brigade,
1032
        /* This is all a single brigade, pass with flush flagged */
948
                                  input_brigade, (old_cl_val != NULL)
1033
        rv = ap_proxy_pass_brigade(r->connection->bucket_alloc,
949
                                              || (old_te_val != NULL)
1034
                                   r, p_conn, origin, header_brigade, 1);
950
                                              || (bytes_read > 0));
951
        break;
1035
        break;
952
    default:
1036
    default:
953
        /* shouldn't be possible */
1037
        /* shouldn't be possible */
Lines 956-961 skip_body: Link Here
956
    }
1040
    }
957
1041
958
    if (rv != OK) {
1042
    if (rv != OK) {
1043
        conn_rec *c = r->connection;
959
        /* apr_status_t value has been logged in lower level method */
1044
        /* apr_status_t value has been logged in lower level method */
960
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01097)
1045
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01097)
961
                      "pass request body failed to %pI (%s) from %s (%s)",
1046
                      "pass request body failed to %pI (%s) from %s (%s)",
Lines 1880-1889 static int proxy_http_handler(request_rec *r, prox Link Here
1880
    char *scheme;
1965
    char *scheme;
1881
    const char *proxy_function;
1966
    const char *proxy_function;
1882
    const char *u;
1967
    const char *u;
1968
    apr_bucket_brigade *header_brigade, *header_bb = NULL;
1969
    apr_bucket_brigade *input_brigade, *input_bb = NULL;
1883
    proxy_conn_rec *backend = NULL;
1970
    proxy_conn_rec *backend = NULL;
1884
    int is_ssl = 0;
1971
    int is_ssl = 0;
1885
    conn_rec *c = r->connection;
1972
    conn_rec *c = r->connection;
1886
    int retry = 0;
1973
    int retry = 0;
1974
    char *old_cl_val = NULL, *old_te_val = NULL;
1975
    enum rb_methods rb_method = RB_INIT;
1976
    char *locurl = url;
1977
    int flushall = 0;
1978
    int toclose = 0;
1887
    /*
1979
    /*
1888
     * Use a shorter-lived pool to reduce memory usage
1980
     * Use a shorter-lived pool to reduce memory usage
1889
     * and avoid a memory leak
1981
     * and avoid a memory leak
Lines 1950-1965 static int proxy_http_handler(request_rec *r, prox Link Here
1950
        backend->close = 1;
2042
        backend->close = 1;
1951
    }
2043
    }
1952
2044
2045
    if (apr_table_get(r->subprocess_env, "proxy-flushall")) {
2046
        flushall = 1;
2047
    }
2048
2049
    /* Step One: Determine Who To Connect To */
2050
    if ((status = ap_proxy_determine_connection(p, r, conf, worker, backend,
2051
                                            uri, &locurl, proxyname,
2052
                                            proxyport, server_portstr,
2053
                                            sizeof(server_portstr))) != OK)
2054
        goto cleanup;
2055
2056
    /* Step Once: Prefetch (partially) the request body so to increase the
2057
     * chances to get the whole (or enough) body and determine Content-Length
2058
     * vs chunked or spool. By doing this before connecting or reusing a
2059
     * backend connection, minimize the delay between checking whether this
2060
     * connection is still alive and the first packet sent, should the link be
2061
     * slow or some input filter retain the data.
2062
     */
2063
    input_brigade = apr_brigade_create(p, c->bucket_alloc);
2064
    header_brigade = apr_brigade_create(p, c->bucket_alloc);
2065
    if ((status = ap_proxy_http_prefetch(p, r, backend, worker, conf, uri,
2066
                                         locurl, server_portstr,
2067
                                         header_brigade, input_brigade,
2068
                                         &old_cl_val, &old_te_val, &rb_method,
2069
                                         flushall)) != OK) {
2070
        goto cleanup;
2071
    }
2072
2073
    /* XXX: Reset backend->close now, since ap_proxy_http_prefetch() sets it to
2074
     * disable the reuse of the connection after this request (no keep-alive),
2075
     * not to close any reusable connection before this request. However assure
2076
     * what is expected later by using a local flag and do the right thing when
2077
     * ap_proxy_connect_backend (below) provides the connection to close.
2078
     */
2079
    toclose = backend->close;
2080
    backend->close = 0;
2081
1953
    while (retry < 2) {
2082
    while (retry < 2) {
1954
        char *locurl = url;
2083
        conn_rec *backconn;
1955
2084
1956
        /* Step One: Determine Who To Connect To */
2085
        if (retry) {
1957
        if ((status = ap_proxy_determine_connection(p, r, conf, worker, backend,
2086
            char *newurl = url;
1958
                                                uri, &locurl, proxyname,
1959
                                                proxyport, server_portstr,
1960
                                                sizeof(server_portstr))) != OK)
1961
            break;
1962
2087
2088
            /* Step One-Retry: Redetermine Who To Connect To */
2089
            if ((status = ap_proxy_determine_connection(p, r, conf, worker,
2090
                            backend, uri, &newurl, proxyname, proxyport,
2091
                            server_portstr, sizeof(server_portstr))) != OK)
2092
                break;
2093
2094
            /* XXX: the code assumes locurl is not changed during the loop,
2095
             * or ap_proxy_http_prefetch() would have to be called every time,
2096
             * and header_brigade be changed accordingly...
2097
             */
2098
            AP_DEBUG_ASSERT(strcmp(newurl, locurl) == 0);
2099
        }
2100
1963
        /* Step Two: Make the Connection */
2101
        /* Step Two: Make the Connection */
1964
        if (ap_proxy_connect_backend(proxy_function, backend, worker, r->server)) {
2102
        if (ap_proxy_connect_backend(proxy_function, backend, worker, r->server)) {
1965
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01114)
2103
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01114)
Lines 1970-1979 static int proxy_http_handler(request_rec *r, prox Link Here
1970
        }
2108
        }
1971
2109
1972
        /* Step Three: Create conn_rec */
2110
        /* Step Three: Create conn_rec */
1973
        if (!backend->connection) {
2111
        backconn = backend->connection;
2112
        if (!backconn) {
1974
            if ((status = ap_proxy_connection_create(proxy_function, backend,
2113
            if ((status = ap_proxy_connection_create(proxy_function, backend,
1975
                                                     c, r->server)) != OK)
2114
                                                     c, r->server)) != OK)
1976
                break;
2115
                break;
2116
            backconn = backend->connection;
2117
1977
            /*
2118
            /*
1978
             * On SSL connections set a note on the connection what CN is
2119
             * On SSL connections set a note on the connection what CN is
1979
             * requested, such that mod_ssl can check if it is requested to do
2120
             * requested, such that mod_ssl can check if it is requested to do
Lines 2001-2012 static int proxy_http_handler(request_rec *r, prox Link Here
2001
            }
2142
            }
2002
        }
2143
        }
2003
2144
2145
        /* Don't recycle the connection if prefetch (above) told not to do so */
2146
        if (toclose) {
2147
            backend->close = 1;
2148
            backconn->keepalive = AP_CONN_CLOSE;
2149
        }
2150
2151
        /* Preserve the header/input brigades since they may be retried. */
2152
        if (header_bb == NULL) {
2153
            header_bb = apr_brigade_create(p, c->bucket_alloc);
2154
            input_bb = apr_brigade_create(p, c->bucket_alloc);
2155
        }
2156
        proxy_buckets_lifetime_transform(r, header_brigade, header_bb);
2157
        proxy_buckets_lifetime_transform(r, input_brigade, input_bb);
2158
2004
        /* Step Four: Send the Request
2159
        /* Step Four: Send the Request
2005
         * On the off-chance that we forced a 100-Continue as a
2160
         * On the off-chance that we forced a 100-Continue as a
2006
         * kinda HTTP ping test, allow for retries
2161
         * kinda HTTP ping test, allow for retries
2007
         */
2162
         */
2008
        if ((status = ap_proxy_http_request(p, r, backend, worker,
2163
        if ((status = ap_proxy_http_request(p, r, backend, header_bb, input_bb,
2009
                                        conf, uri, locurl, server_portstr)) != OK) {
2164
                                            old_cl_val, old_te_val, rb_method,
2165
                                            flushall)) != OK) {
2010
            proxy_run_detach_backend(r, backend);
2166
            proxy_run_detach_backend(r, backend);
2011
            if ((status == HTTP_SERVICE_UNAVAILABLE) &&
2167
            if ((status == HTTP_SERVICE_UNAVAILABLE) &&
2012
                 worker->s->ping_timeout_set &&
2168
                 worker->s->ping_timeout_set &&
Lines 2020-2026 static int proxy_http_handler(request_rec *r, prox Link Here
2020
            } else {
2176
            } else {
2021
                break;
2177
                break;
2022
            }
2178
            }
2023
2024
        }
2179
        }
2025
2180
2026
        /* Step Five: Receive the Response... Fall thru to cleanup */
2181
        /* Step Five: Receive the Response... Fall thru to cleanup */
Lines 2031-2036 static int proxy_http_handler(request_rec *r, prox Link Here
2031
    }
2186
    }
2032
2187
2033
    /* Step Six: Clean Up */
2188
    /* Step Six: Clean Up */
2189
    if (header_bb) {
2190
        apr_brigade_destroy(header_bb);
2191
        apr_brigade_destroy(input_bb);
2192
    }
2034
cleanup:
2193
cleanup:
2035
    if (backend) {
2194
    if (backend) {
2036
        if (status != OK)
2195
        if (status != OK)

Return to bug 56541