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 (-65 / +191 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
    {
254
        int flush = flushall;
255
256
        if (!APR_BRIGADE_EMPTY(input_brigade)) {
252
        char chunk_hdr[20];  /* must be here due to transient bucket. */
257
        char chunk_hdr[20];  /* must be here due to transient bucket. */
253
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 518-525 static int spool_reqbody_cl(apr_pool_t *p, Link Here
518
544
519
    limit = ap_get_limit_req_body(r);
545
    limit = ap_get_limit_req_body(r);
520
546
521
    while (!APR_BUCKET_IS_EOS(APR_BRIGADE_FIRST(input_brigade)))
547
    while (APR_BRIGADE_EMPTY(input_brigade) ||
548
            !APR_BUCKET_IS_EOS(APR_BRIGADE_FIRST(input_brigade)))
522
    {
549
    {
550
        if (!APR_BRIGADE_EMPTY(input_brigade)) {
523
        /* If this brigade contains EOS, either stop or remove it. */
551
        /* If this brigade contains EOS, either stop or remove it. */
524
        if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) {
552
        if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) {
525
            seen_eos = 1;
553
            seen_eos = 1;
Lines 612-617 static int spool_reqbody_cl(apr_pool_t *p, Link Here
612
        if (seen_eos) {
640
        if (seen_eos) {
613
            break;
641
            break;
614
        }
642
        }
643
        }
615
644
616
        status = ap_get_brigade(r->input_filters, input_brigade,
645
        status = ap_get_brigade(r->input_filters, input_brigade,
617
                                AP_MODE_READBYTES, APR_BLOCK_READ,
646
                                AP_MODE_READBYTES, APR_BLOCK_READ,
Lines 694-721 static apr_status_t proxy_buckets_lifetime_transfo Link Here
694
    return rv;
723
    return rv;
695
}
724
}
696
725
697
static
726
enum rb_methods {
698
int ap_proxy_http_request(apr_pool_t *p, request_rec *r,
727
    RB_INIT,
699
                                   proxy_conn_rec *p_conn, proxy_worker *worker,
728
    RB_STREAM_CL,
700
                                   proxy_server_conf *conf,
729
    RB_STREAM_CHUNKED,
701
                                   apr_uri_t *uri,
730
    RB_SPOOL_CL
702
                                   char *url, char *server_portstr)
731
};
732
733
static int ap_proxy_http_prefetch(apr_pool_t *p, request_rec *r,
734
                                  proxy_conn_rec *p_conn, proxy_worker *worker,
735
                                  proxy_server_conf *conf,
736
                                  apr_uri_t *uri,
737
                                  char *url, char *server_portstr,
738
                                  apr_bucket_brigade *header_brigade,
739
                                  apr_bucket_brigade *input_brigade,
740
                                  char **old_cl_val, char **old_te_val,
741
                                  enum rb_methods *rb_method, int flushall)
703
{
742
{
704
    conn_rec *c = r->connection;
743
    conn_rec *c = r->connection;
705
    apr_bucket_alloc_t *bucket_alloc = c->bucket_alloc;
744
    apr_bucket_alloc_t *bucket_alloc = c->bucket_alloc;
706
    apr_bucket_brigade *header_brigade;
707
    apr_bucket_brigade *input_brigade;
708
    apr_bucket_brigade *temp_brigade;
745
    apr_bucket_brigade *temp_brigade;
709
    apr_bucket *e;
746
    apr_bucket *e;
710
    char *buf;
747
    char *buf;
711
    apr_status_t status;
748
    apr_status_t status;
712
    enum rb_methods {RB_INIT, RB_STREAM_CL, RB_STREAM_CHUNKED, RB_SPOOL_CL};
713
    enum rb_methods rb_method = RB_INIT;
714
    char *old_cl_val = NULL;
715
    char *old_te_val = NULL;
716
    apr_off_t bytes_read = 0;
749
    apr_off_t bytes_read = 0;
717
    apr_off_t bytes;
750
    apr_off_t bytes;
718
    int force10, rv;
751
    int force10, rv;
752
    apr_read_type_e block;
719
    conn_rec *origin = p_conn->connection;
753
    conn_rec *origin = p_conn->connection;
720
754
721
    if (apr_table_get(r->subprocess_env, "force-proxy-request-1.0")) {
755
    if (apr_table_get(r->subprocess_env, "force-proxy-request-1.0")) {
Lines 727-743 static apr_status_t proxy_buckets_lifetime_transfo Link Here
727
        force10 = 0;
761
        force10 = 0;
728
    }
762
    }
729
763
730
    header_brigade = apr_brigade_create(p, bucket_alloc);
731
    rv = ap_proxy_create_hdrbrgd(p, header_brigade, r, p_conn,
764
    rv = ap_proxy_create_hdrbrgd(p, header_brigade, r, p_conn,
732
                                 worker, conf, uri, url, server_portstr,
765
                                 worker, conf, uri, url, server_portstr,
733
                                 &old_cl_val, &old_te_val);
766
                                 old_cl_val, old_te_val);
734
    if (rv != OK) {
767
    if (rv != OK) {
735
        return rv;
768
        return rv;
736
    }
769
    }
737
770
738
    /* We have headers, let's figure out our request body... */
739
    input_brigade = apr_brigade_create(p, bucket_alloc);
740
741
    /* sub-requests never use keepalives, and mustn't pass request bodies.
771
    /* sub-requests never use keepalives, and mustn't pass request bodies.
742
     * Because the new logic looks at input_brigade, we will self-terminate
772
     * Because the new logic looks at input_brigade, we will self-terminate
743
     * input_brigade and jump past all of the request body logic...
773
     * input_brigade and jump past all of the request body logic...
Lines 750-758 static apr_status_t proxy_buckets_lifetime_transfo Link Here
750
    if (!r->kept_body && r->main) {
780
    if (!r->kept_body && r->main) {
751
        /* XXX: Why DON'T sub-requests use keepalives? */
781
        /* XXX: Why DON'T sub-requests use keepalives? */
752
        p_conn->close = 1;
782
        p_conn->close = 1;
753
        old_cl_val = NULL;
783
        *old_cl_val = NULL;
754
        old_te_val = NULL;
784
        *old_te_val = NULL;
755
        rb_method = RB_STREAM_CL;
785
        *rb_method = RB_STREAM_CL;
756
        e = apr_bucket_eos_create(input_brigade->bucket_alloc);
786
        e = apr_bucket_eos_create(input_brigade->bucket_alloc);
757
        APR_BRIGADE_INSERT_TAIL(input_brigade, e);
787
        APR_BRIGADE_INSERT_TAIL(input_brigade, e);
758
        goto skip_body;
788
        goto skip_body;
Lines 766-783 static apr_status_t proxy_buckets_lifetime_transfo Link Here
766
     * encoding has been done by the extensions' handler, and
796
     * encoding has been done by the extensions' handler, and
767
     * do not modify add_te_chunked's logic
797
     * do not modify add_te_chunked's logic
768
     */
798
     */
769
    if (old_te_val && strcasecmp(old_te_val, "chunked") != 0) {
799
    if (*old_te_val && strcasecmp(*old_te_val, "chunked") != 0) {
770
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01093)
800
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01093)
771
                      "%s Transfer-Encoding is not supported", old_te_val);
801
                      "%s Transfer-Encoding is not supported", *old_te_val);
772
        return HTTP_INTERNAL_SERVER_ERROR;
802
        return HTTP_INTERNAL_SERVER_ERROR;
773
    }
803
    }
774
804
775
    if (old_cl_val && old_te_val) {
805
    if (*old_cl_val && *old_te_val) {
776
        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01094)
806
        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01094)
777
                      "client %s (%s) requested Transfer-Encoding "
807
                      "client %s (%s) requested Transfer-Encoding "
778
                      "chunked body with Content-Length (C-L ignored)",
808
                      "chunked body with Content-Length (C-L ignored)",
779
                      c->client_ip, c->remote_host ? c->remote_host: "");
809
                      c->client_ip, c->remote_host ? c->remote_host: "");
780
        old_cl_val = NULL;
810
        *old_cl_val = NULL;
781
        origin->keepalive = AP_CONN_CLOSE;
811
        origin->keepalive = AP_CONN_CLOSE;
782
        p_conn->close = 1;
812
        p_conn->close = 1;
783
    }
813
    }
Lines 791-800 static apr_status_t proxy_buckets_lifetime_transfo Link Here
791
     * reasonable size.
821
     * reasonable size.
792
     */
822
     */
793
    temp_brigade = apr_brigade_create(p, bucket_alloc);
823
    temp_brigade = apr_brigade_create(p, bucket_alloc);
824
    block = (flushall) ? APR_NONBLOCK_READ : APR_BLOCK_READ;
794
    do {
825
    do {
795
        status = ap_get_brigade(r->input_filters, temp_brigade,
826
        status = ap_get_brigade(r->input_filters, temp_brigade,
796
                                AP_MODE_READBYTES, APR_BLOCK_READ,
827
                                AP_MODE_READBYTES, block,
797
                                MAX_MEM_SPOOL - bytes_read);
828
                                MAX_MEM_SPOOL - bytes_read);
829
        /* ap_get_brigade will return success with an empty brigade
830
         * for a non-blocking read which would block
831
         */
832
        if (block == APR_NONBLOCK_READ
833
            && (APR_STATUS_IS_EAGAIN(rv)
834
                || (rv == APR_SUCCESS && APR_BRIGADE_EMPTY(temp_brigade)))) {
835
            status = APR_SUCCESS;
836
            break;
837
        }
798
        if (status != APR_SUCCESS) {
838
        if (status != APR_SUCCESS) {
799
            ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(01095)
839
            ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(01095)
800
                          "prefetch request body failed to %pI (%s)"
840
                          "prefetch request body failed to %pI (%s)"
Lines 869-875 static apr_status_t proxy_buckets_lifetime_transfo Link Here
869
     * is absent, and the filters are unchanged (the body won't
909
     * is absent, and the filters are unchanged (the body won't
870
     * be resized by another content filter).
910
     * be resized by another content filter).
871
     */
911
     */
872
    if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) {
912
    if (!APR_BRIGADE_EMPTY(input_brigade) &&
913
            APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) {
873
        /* The whole thing fit, so our decision is trivial, use
914
        /* The whole thing fit, so our decision is trivial, use
874
         * the filtered bytes read from the client for the request
915
         * the filtered bytes read from the client for the request
875
         * body Content-Length.
916
         * body Content-Length.
Lines 877-918 static apr_status_t proxy_buckets_lifetime_transfo Link Here
877
         * If we expected no body, and read no body, do not set
918
         * If we expected no body, and read no body, do not set
878
         * the Content-Length.
919
         * the Content-Length.
879
         */
920
         */
880
        if (old_cl_val || old_te_val || bytes_read) {
921
        if (*old_cl_val || *old_te_val || bytes_read) {
881
            old_cl_val = apr_off_t_toa(r->pool, bytes_read);
922
            *old_cl_val = apr_off_t_toa(r->pool, bytes_read);
882
        }
923
        }
883
        rb_method = RB_STREAM_CL;
924
        *rb_method = RB_STREAM_CL;
884
    }
925
    }
885
    else if (old_te_val) {
926
    else if (*old_te_val) {
886
        if (force10
927
        if (force10
887
             || (apr_table_get(r->subprocess_env, "proxy-sendcl")
928
             || (!flushall
888
                  && !apr_table_get(r->subprocess_env, "proxy-sendchunks")
929
                 && apr_table_get(r->subprocess_env, "proxy-sendcl")
889
                  && !apr_table_get(r->subprocess_env, "proxy-sendchunked"))) {
930
                 && !apr_table_get(r->subprocess_env, "proxy-sendchunks")
890
            rb_method = RB_SPOOL_CL;
931
                 && !apr_table_get(r->subprocess_env, "proxy-sendchunked"))) {
932
            *rb_method = RB_SPOOL_CL;
891
        }
933
        }
892
        else {
934
        else {
893
            rb_method = RB_STREAM_CHUNKED;
935
            *rb_method = RB_STREAM_CHUNKED;
894
        }
936
        }
895
    }
937
    }
896
    else if (old_cl_val) {
938
    else if (*old_cl_val) {
897
        if (r->input_filters == r->proto_input_filters) {
939
        if (r->input_filters == r->proto_input_filters) {
898
            rb_method = RB_STREAM_CL;
940
            *rb_method = RB_STREAM_CL;
899
        }
941
        }
900
        else if (!force10
942
        else if (!force10
901
                  && (apr_table_get(r->subprocess_env, "proxy-sendchunks")
943
                  && (flushall
944
                      || apr_table_get(r->subprocess_env, "proxy-sendchunks")
902
                      || apr_table_get(r->subprocess_env, "proxy-sendchunked"))
945
                      || apr_table_get(r->subprocess_env, "proxy-sendchunked"))
903
                  && !apr_table_get(r->subprocess_env, "proxy-sendcl")) {
946
                  && !apr_table_get(r->subprocess_env, "proxy-sendcl")) {
904
            rb_method = RB_STREAM_CHUNKED;
947
            *rb_method = RB_STREAM_CHUNKED;
905
        }
948
        }
906
        else {
949
        else {
907
            rb_method = RB_SPOOL_CL;
950
            *rb_method = RB_SPOOL_CL;
908
        }
951
        }
909
    }
952
    }
910
    else {
953
    else {
911
        /* This is an appropriate default; very efficient for no-body
954
        /* This is an appropriate default; very efficient for no-body
912
         * requests, and has the behavior that it will not add any C-L
955
         * requests, and has the behavior that it will not add any C-L
913
         * when the old_cl_val is NULL.
956
         * when the *old_cl_val is NULL.
914
         */
957
         */
915
        rb_method = RB_SPOOL_CL;
958
        *rb_method = RB_SPOOL_CL;
916
    }
959
    }
917
960
918
/* Yes I hate gotos.  This is the subrequest shortcut */
961
/* Yes I hate gotos.  This is the subrequest shortcut */
Lines 934-950 skip_body: Link Here
934
        APR_BRIGADE_INSERT_TAIL(header_brigade, e);
977
        APR_BRIGADE_INSERT_TAIL(header_brigade, e);
935
    }
978
    }
936
979
980
    return OK;
981
}
982
983
static
984
int ap_proxy_http_request(apr_pool_t *p, request_rec *r,
985
                                   proxy_conn_rec *p_conn,
986
                                   apr_bucket_brigade *header_brigade,
987
                                   apr_bucket_brigade *input_brigade,
988
                                   char *old_cl_val, char *old_te_val,
989
                                   enum rb_methods rb_method, int flushall)
990
{
991
    int rv;
992
    apr_off_t bytes_read = 0;
993
    conn_rec *origin = p_conn->connection;
994
937
    /* send the request body, if any. */
995
    /* send the request body, if any. */
938
    switch(rb_method) {
996
    switch(rb_method) {
939
    case RB_STREAM_CHUNKED:
997
    case RB_STREAM_CHUNKED:
940
        rv = stream_reqbody_chunked(p, r, p_conn, origin, header_brigade,
998
        rv = stream_reqbody_chunked(p, r, p_conn, origin, header_brigade,
941
                                        input_brigade);
999
                                        input_brigade, flushall);
942
        break;
1000
        break;
943
    case RB_STREAM_CL:
1001
    case RB_STREAM_CL:
944
        rv = stream_reqbody_cl(p, r, p_conn, origin, header_brigade,
1002
        rv = stream_reqbody_cl(p, r, p_conn, origin, header_brigade,
945
                                   input_brigade, old_cl_val);
1003
                                   input_brigade, old_cl_val, flushall);
946
        break;
1004
        break;
947
    case RB_SPOOL_CL:
1005
    case RB_SPOOL_CL:
1006
        apr_brigade_length(input_brigade, 1, &bytes_read);
948
        rv = spool_reqbody_cl(p, r, p_conn, origin, header_brigade,
1007
        rv = spool_reqbody_cl(p, r, p_conn, origin, header_brigade,
949
                                  input_brigade, (old_cl_val != NULL)
1008
                                  input_brigade, (old_cl_val != NULL)
950
                                              || (old_te_val != NULL)
1009
                                              || (old_te_val != NULL)
Lines 957-962 skip_body: Link Here
957
    }
1016
    }
958
1017
959
    if (rv != OK) {
1018
    if (rv != OK) {
1019
        conn_rec *c = r->connection;
960
        /* apr_status_t value has been logged in lower level method */
1020
        /* apr_status_t value has been logged in lower level method */
961
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01097)
1021
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01097)
962
                      "pass request body failed to %pI (%s) from %s (%s)",
1022
                      "pass request body failed to %pI (%s) from %s (%s)",
Lines 1881-1890 static int proxy_http_handler(request_rec *r, prox Link Here
1881
    char *scheme;
1941
    char *scheme;
1882
    const char *proxy_function;
1942
    const char *proxy_function;
1883
    const char *u;
1943
    const char *u;
1944
    apr_bucket_brigade *header_brigade, *header_bb;
1945
    apr_bucket_brigade *input_brigade, *input_bb;
1884
    proxy_conn_rec *backend = NULL;
1946
    proxy_conn_rec *backend = NULL;
1885
    int is_ssl = 0;
1947
    int is_ssl = 0;
1886
    conn_rec *c = r->connection;
1948
    conn_rec *c = r->connection;
1887
    int retry = 0;
1949
    int retry = 0;
1950
    char *old_cl_val = NULL, *old_te_val = NULL;
1951
    enum rb_methods rb_method = RB_INIT;
1952
    char *locurl = url;
1953
    int flushall = 0;
1954
    int toclose = 0;
1888
    /*
1955
    /*
1889
     * Use a shorter-lived pool to reduce memory usage
1956
     * Use a shorter-lived pool to reduce memory usage
1890
     * and avoid a memory leak
1957
     * and avoid a memory leak
Lines 1951-1966 static int proxy_http_handler(request_rec *r, prox Link Here
1951
        backend->close = 1;
2018
        backend->close = 1;
1952
    }
2019
    }
1953
2020
2021
    if (apr_table_get(r->subprocess_env, "proxy-flushall")) {
2022
        flushall = 1;
2023
    }
2024
2025
    /* Step One: Determine Who To Connect To */
2026
    if ((status = ap_proxy_determine_connection(p, r, conf, worker, backend,
2027
                                            uri, &locurl, proxyname,
2028
                                            proxyport, server_portstr,
2029
                                            sizeof(server_portstr))) != OK)
2030
        goto cleanup;
2031
2032
    /* Step Once: Prefetch (partially) the request body so to increase the
2033
     * chances to get whole (or enough) body and determine Content-Length vs
2034
     * chunked or spool. By doing this before connecting or reusing a backend
2035
     * connection, minimize the delay between checking whether this connection
2036
     * is still alive and the first packet sent, should the link be slow or
2037
     * some input filter retain the data.
2038
     */
2039
    input_brigade = apr_brigade_create(p, c->bucket_alloc);
2040
    header_brigade = apr_brigade_create(p, c->bucket_alloc);
2041
    if ((status = ap_proxy_http_prefetch(p, r, backend, worker, conf, uri,
2042
                    locurl, server_portstr, header_brigade, input_brigade,
2043
                    &old_cl_val, &old_te_val, &rb_method, flushall)) != OK) {
2044
        goto cleanup;
2045
    }
2046
2047
    /* XXX: Reset backend->close now, since ap_proxy_http_prefetch() sets it to
2048
     * disable the reuse of the connection after this request (no keep-alive),
2049
     * not to close any reusable connection before this request. However assure
2050
     * what is expected later by using a local flag and do the right thing when
2051
     * ap_proxy_connect_backend (below) provides the connection to close.
2052
     */
2053
    toclose = backend->close;
2054
    backend->close = 0;
2055
1954
    while (retry < 2) {
2056
    while (retry < 2) {
1955
        char *locurl = url;
2057
        conn_rec *backconn;
1956
2058
1957
        /* Step One: Determine Who To Connect To */
2059
        if (retry) {
1958
        if ((status = ap_proxy_determine_connection(p, r, conf, worker, backend,
2060
            char *newurl = url;
1959
                                                uri, &locurl, proxyname,
1960
                                                proxyport, server_portstr,
1961
                                                sizeof(server_portstr))) != OK)
1962
            break;
1963
2061
2062
            /* Step One-Retry: Redetermine Who To Connect To */
2063
            if ((status = ap_proxy_determine_connection(p, r, conf, worker,
2064
                            backend, uri, &newurl, proxyname, proxyport,
2065
                            server_portstr, sizeof(server_portstr))) != OK)
2066
                break;
2067
2068
            /* XXX: the code assumes locurl is not changed during the loop,
2069
             * or ap_proxy_http_prefetch() would have to be called every time,
2070
             * and header_brigade be changed accordingly...
2071
             */
2072
            AP_DEBUG_ASSERT(strcmp(newurl, locurl) == 0);
2073
        }
2074
1964
        /* Step Two: Make the Connection */
2075
        /* Step Two: Make the Connection */
1965
        if (ap_proxy_connect_backend(proxy_function, backend, worker, r->server)) {
2076
        if (ap_proxy_connect_backend(proxy_function, backend, worker, r->server)) {
1966
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01114)
2077
            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01114)
Lines 1971-1980 static int proxy_http_handler(request_rec *r, prox Link Here
1971
        }
2082
        }
1972
2083
1973
        /* Step Three: Create conn_rec */
2084
        /* Step Three: Create conn_rec */
1974
        if (!backend->connection) {
2085
        backconn = backend->connection;
2086
        if (!backconn) {
1975
            if ((status = ap_proxy_connection_create(proxy_function, backend,
2087
            if ((status = ap_proxy_connection_create(proxy_function, backend,
1976
                                                     c, r->server)) != OK)
2088
                                                     c, r->server)) != OK)
1977
                break;
2089
                break;
2090
            backconn = backend->connection;
2091
1978
            /*
2092
            /*
1979
             * On SSL connections set a note on the connection what CN is
2093
             * On SSL connections set a note on the connection what CN is
1980
             * requested, such that mod_ssl can check if it is requested to do
2094
             * requested, such that mod_ssl can check if it is requested to do
Lines 2002-2013 static int proxy_http_handler(request_rec *r, prox Link Here
2002
            }
2116
            }
2003
        }
2117
        }
2004
2118
2119
        /* Don't recycle the connection if prefetch (above) told not to do so */
2120
        if (toclose) {
2121
            backend->close = 1;
2122
            backconn->keepalive = AP_CONN_CLOSE;
2123
        }
2124
2125
        /* Preserve the header/input brigades since they may be retried. */
2126
        header_bb = apr_brigade_create(p, backconn->bucket_alloc);
2127
        proxy_buckets_lifetime_transform(r, header_brigade, header_bb);
2128
        input_bb = apr_brigade_create(p, backconn->bucket_alloc);
2129
        proxy_buckets_lifetime_transform(r, input_brigade, input_bb);
2130
2005
        /* Step Four: Send the Request
2131
        /* Step Four: Send the Request
2006
         * On the off-chance that we forced a 100-Continue as a
2132
         * On the off-chance that we forced a 100-Continue as a
2007
         * kinda HTTP ping test, allow for retries
2133
         * kinda HTTP ping test, allow for retries
2008
         */
2134
         */
2009
        if ((status = ap_proxy_http_request(p, r, backend, worker,
2135
        if ((status = ap_proxy_http_request(p, r, backend, header_bb, input_bb,
2010
                                        conf, uri, locurl, server_portstr)) != OK) {
2136
                                            old_cl_val, old_te_val, rb_method,
2137
                                            flushall)) != OK) {
2011
            proxy_run_detach_backend(r, backend);
2138
            proxy_run_detach_backend(r, backend);
2012
            if ((status == HTTP_SERVICE_UNAVAILABLE) &&
2139
            if ((status == HTTP_SERVICE_UNAVAILABLE) &&
2013
                 worker->s->ping_timeout_set &&
2140
                 worker->s->ping_timeout_set &&
Lines 2021-2027 static int proxy_http_handler(request_rec *r, prox Link Here
2021
            } else {
2148
            } else {
2022
                break;
2149
                break;
2023
            }
2150
            }
2024
2025
        }
2151
        }
2026
2152
2027
        /* Step Five: Receive the Response... Fall thru to cleanup */
2153
        /* Step Five: Receive the Response... Fall thru to cleanup */

Return to bug 56541