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

(-)modules/proxy/mod_proxy_http.c (-262 / +327 lines)
Lines 229-258 Link Here
229
229
230
#define MAX_MEM_SPOOL 16384
230
#define MAX_MEM_SPOOL 16384
231
231
232
static int stream_reqbody_chunked(apr_pool_t *p,
232
typedef enum {
233
                                           request_rec *r,
233
    RB_INIT = 0,
234
                                           proxy_conn_rec *p_conn,
234
    RB_STREAM_CL,
235
                                           conn_rec *origin,
235
    RB_STREAM_CHUNKED,
236
                                           apr_bucket_brigade *header_brigade,
236
    RB_SPOOL_CL
237
                                           apr_bucket_brigade *input_brigade,
237
} rb_methods;
238
                                           int flushall)
238
239
typedef struct {
240
    apr_pool_t *p;
241
    request_rec *r;
242
    proxy_worker *worker;
243
    proxy_server_conf *sconf;
244
245
    char server_portstr[32];
246
    proxy_conn_rec *backend;
247
    conn_rec *origin;
248
249
    rb_methods rb_method;
250
    apr_bucket_alloc_t *bucket_alloc;
251
    apr_bucket_brigade *header_brigade;
252
    apr_bucket_brigade *input_brigade;
253
    char *old_cl_val, *old_te_val;
254
    apr_off_t cl_val, bytes_spooled;
255
256
    int do_100_continue;
257
    int flushall;
258
} proxy_http_req_t;
259
260
static int stream_reqbody_chunked(proxy_http_req_t *req)
239
{
261
{
262
    request_rec *r = req->r;
240
    int seen_eos = 0, rv = OK;
263
    int seen_eos = 0, rv = OK;
241
    apr_size_t hdr_len;
264
    apr_size_t hdr_len;
242
    apr_off_t bytes;
265
    apr_off_t bytes;
243
    apr_status_t status;
266
    apr_status_t status;
244
    apr_bucket_alloc_t *bucket_alloc = r->connection->bucket_alloc;
267
    char chunk_hdr[20];  /* must be here due to transient bucket. */
268
    proxy_conn_rec *p_conn = req->backend;
269
    apr_bucket_alloc_t *bucket_alloc = req->bucket_alloc;
270
    apr_bucket_brigade *header_brigade = req->header_brigade;
271
    apr_bucket_brigade *input_brigade = req->input_brigade;
245
    apr_bucket_brigade *bb;
272
    apr_bucket_brigade *bb;
246
    apr_bucket *e;
273
    apr_bucket *e;
247
274
248
    add_te_chunked(p, bucket_alloc, header_brigade);
249
    terminate_headers(bucket_alloc, header_brigade);
250
251
    while (APR_BRIGADE_EMPTY(input_brigade)
275
    while (APR_BRIGADE_EMPTY(input_brigade)
252
           || !APR_BUCKET_IS_EOS(APR_BRIGADE_FIRST(input_brigade)))
276
           || !APR_BUCKET_IS_EOS(APR_BRIGADE_FIRST(input_brigade)))
253
    {
277
    {
254
        char chunk_hdr[20];  /* must be here due to transient bucket. */
278
        int flush = req->flushall;
255
        int flush = flushall;
256
279
257
        if (!APR_BRIGADE_EMPTY(input_brigade)) {
280
        if (!APR_BRIGADE_EMPTY(input_brigade)) {
258
            /* If this brigade contains EOS, either stop or remove it. */
281
            /* If this brigade contains EOS, either stop or remove it. */
Lines 259-267 Link Here
259
            if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) {
282
            if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) {
260
                seen_eos = 1;
283
                seen_eos = 1;
261
284
262
                /* The request is flushed below this loop with the EOS chunk */
263
                flush = 0;
264
265
                /* We can't pass this EOS to the output_filters. */
285
                /* We can't pass this EOS to the output_filters. */
266
                e = APR_BRIGADE_LAST(input_brigade);
286
                e = APR_BRIGADE_LAST(input_brigade);
267
                apr_bucket_delete(e);
287
                apr_bucket_delete(e);
Lines 269-274 Link Here
269
289
270
            apr_brigade_length(input_brigade, 1, &bytes);
290
            apr_brigade_length(input_brigade, 1, &bytes);
271
291
292
            /* Flush only if we did not get the requested #bytes. */
293
            if (bytes < HUGE_STRING_LEN) {
294
                flush = 0;
295
            }
296
272
            hdr_len = apr_snprintf(chunk_hdr, sizeof(chunk_hdr),
297
            hdr_len = apr_snprintf(chunk_hdr, sizeof(chunk_hdr),
273
                                   "%" APR_UINT64_T_HEX_FMT CRLF,
298
                                   "%" APR_UINT64_T_HEX_FMT CRLF,
274
                                   (apr_uint64_t)bytes);
299
                                   (apr_uint64_t)bytes);
Lines 285-323 Link Here
285
            APR_BRIGADE_INSERT_TAIL(input_brigade, e);
310
            APR_BRIGADE_INSERT_TAIL(input_brigade, e);
286
        }
311
        }
287
312
288
        if (header_brigade) {
313
        if (!APR_BRIGADE_EMPTY(header_brigade)) {
289
            /* we never sent the header brigade, so go ahead and
314
            /* we never sent the header brigade, so go ahead and
290
             * take care of that now
315
             * take care of that now
291
             */
316
             */
292
            bb = header_brigade;
317
            bb = header_brigade;
318
            APR_BRIGADE_CONCAT(bb, input_brigade);
293
319
294
            /* Flush now since we have the header and (enough of) the prefeched
320
            /* Flush now since we have the header and (enough of) the
295
             * body already, unless we are EOS since everything is to be
321
             * prefeched body, or racing KeepAliveTimeout on the backend
296
             * flushed below this loop with the EOS chunk.
322
             * side may kill our connection while we read more client data.
297
             */
323
             */
298
            flush = !seen_eos;
324
            flush = 1;
299
300
            /*
301
             * Save input_brigade in bb brigade. (At least) in the SSL case
302
             * input_brigade contains transient buckets whose data would get
303
             * overwritten during the next call of ap_get_brigade in the loop.
304
             * ap_save_brigade ensures these buckets to be set aside.
305
             * Calling ap_save_brigade with NULL as filter is OK, because
306
             * bb brigade already has been created and does not need to get
307
             * created by ap_save_brigade.
308
             */
309
            status = ap_save_brigade(NULL, &bb, &input_brigade, p);
310
            if (status != APR_SUCCESS) {
311
                return HTTP_INTERNAL_SERVER_ERROR;
312
            }
313
314
            header_brigade = NULL;
315
        }
325
        }
316
        else {
326
        else {
317
            bb = input_brigade;
327
            bb = input_brigade;
318
        }
328
        }
319
329
320
        rv = ap_proxy_pass_brigade(bucket_alloc, r, p_conn, origin, bb, flush);
330
        /* Once we hit EOS, flush below this loop with the EOS chunk. */
331
        rv = ap_proxy_pass_brigade(bucket_alloc, r, p_conn, req->origin,
332
                                   bb, flush && !seen_eos);
321
        if (rv != OK) {
333
        if (rv != OK) {
322
            return rv;
334
            return rv;
323
        }
335
        }
Lines 341-347 Link Here
341
        }
353
        }
342
    }
354
    }
343
355
344
    if (header_brigade) {
356
    if (!APR_BRIGADE_EMPTY(header_brigade)) {
345
        /* we never sent the header brigade because there was no request body;
357
        /* we never sent the header brigade because there was no request body;
346
         * send it now
358
         * send it now
347
         */
359
         */
Lines 369-426 Link Here
369
    }
381
    }
370
382
371
    /* Now we have headers-only, or the chunk EOS mark; flush it */
383
    /* Now we have headers-only, or the chunk EOS mark; flush it */
372
    rv = ap_proxy_pass_brigade(bucket_alloc, r, p_conn, origin, bb, 1);
384
    return ap_proxy_pass_brigade(bucket_alloc, r, p_conn, req->origin, bb, 1);
373
    return rv;
374
}
385
}
375
386
376
static int stream_reqbody_cl(apr_pool_t *p,
387
static int stream_reqbody_cl(proxy_http_req_t *req)
377
                                      request_rec *r,
378
                                      proxy_conn_rec *p_conn,
379
                                      conn_rec *origin,
380
                                      apr_bucket_brigade *header_brigade,
381
                                      apr_bucket_brigade *input_brigade,
382
                                      char *old_cl_val, int flushall)
383
{
388
{
389
    request_rec *r = req->r;
384
    int seen_eos = 0, rv = 0;
390
    int seen_eos = 0, rv = 0;
385
    apr_status_t status = APR_SUCCESS;
391
    apr_status_t status = APR_SUCCESS;
386
    apr_bucket_alloc_t *bucket_alloc = r->connection->bucket_alloc;
392
    proxy_conn_rec *p_conn = req->backend;
393
    apr_bucket_alloc_t *bucket_alloc = req->bucket_alloc;
394
    apr_bucket_brigade *header_brigade = req->header_brigade;
395
    apr_bucket_brigade *input_brigade = req->input_brigade;
387
    apr_bucket_brigade *bb;
396
    apr_bucket_brigade *bb;
388
    apr_bucket *e;
397
    apr_bucket *e;
389
    apr_off_t cl_val = 0;
390
    apr_off_t bytes;
398
    apr_off_t bytes;
391
    apr_off_t bytes_streamed = 0;
399
    apr_off_t bytes_streamed = 0;
392
400
393
    if (old_cl_val) {
394
        char *endstr;
395
396
        add_cl(p, bucket_alloc, header_brigade, old_cl_val);
397
        status = apr_strtoff(&cl_val, old_cl_val, &endstr, 10);
398
399
        if (status || *endstr || endstr == old_cl_val || cl_val < 0) {
400
            ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(01085)
401
                          "could not parse request Content-Length (%s)",
402
                          old_cl_val);
403
            return HTTP_BAD_REQUEST;
404
        }
405
    }
406
    terminate_headers(bucket_alloc, header_brigade);
407
408
    while (APR_BRIGADE_EMPTY(input_brigade)
401
    while (APR_BRIGADE_EMPTY(input_brigade)
409
           || !APR_BUCKET_IS_EOS(APR_BRIGADE_FIRST(input_brigade)))
402
           || !APR_BUCKET_IS_EOS(APR_BRIGADE_FIRST(input_brigade)))
410
    {
403
    {
411
        int flush = flushall;
404
        int flush = req->flushall;
412
405
413
        if (!APR_BRIGADE_EMPTY(input_brigade)) {
406
        if (!APR_BRIGADE_EMPTY(input_brigade)) {
414
            apr_brigade_length(input_brigade, 1, &bytes);
407
            apr_brigade_length(input_brigade, 1, &bytes);
415
            bytes_streamed += bytes;
408
            bytes_streamed += bytes;
416
409
410
            /* Flush only if we did not get the requested #bytes. */
411
            if (bytes < HUGE_STRING_LEN) {
412
                flush = 0;
413
            }
414
417
            /* If this brigade contains EOS, either stop or remove it. */
415
            /* If this brigade contains EOS, either stop or remove it. */
418
            if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) {
416
            if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) {
419
                seen_eos = 1;
417
                seen_eos = 1;
420
418
421
                /* Once we hit EOS, we are ready to flush. */
422
                flush = 1;
423
424
                /* We can't pass this EOS to the output_filters. */
419
                /* We can't pass this EOS to the output_filters. */
425
                e = APR_BRIGADE_LAST(input_brigade);
420
                e = APR_BRIGADE_LAST(input_brigade);
426
                apr_bucket_delete(e);
421
                apr_bucket_delete(e);
Lines 441-488 Link Here
441
             *
436
             *
442
             * Prevents HTTP Response Splitting.
437
             * Prevents HTTP Response Splitting.
443
             */
438
             */
444
            if (bytes_streamed > cl_val) {
439
            if (bytes_streamed > req->cl_val) {
445
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01086)
440
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01086)
446
                              "read more bytes of request body than expected "
441
                              "read more bytes of request body than expected "
447
                              "(got %" APR_OFF_T_FMT ", expected "
442
                              "(got %" APR_OFF_T_FMT ", expected "
448
                              "%" APR_OFF_T_FMT ")",
443
                              "%" APR_OFF_T_FMT ")",
449
                              bytes_streamed, cl_val);
444
                              bytes_streamed, req->cl_val);
450
                return HTTP_INTERNAL_SERVER_ERROR;
445
                return HTTP_INTERNAL_SERVER_ERROR;
451
            }
446
            }
452
        }
447
        }
453
448
454
        if (header_brigade) {
449
        if (!APR_BRIGADE_EMPTY(header_brigade)) {
455
            /* we never sent the header brigade, so go ahead and
450
            /* we never sent the header brigade, so go ahead and
456
             * take care of that now
451
             * take care of that now
457
             */
452
             */
458
            bb = header_brigade;
453
            bb = header_brigade;
454
            APR_BRIGADE_CONCAT(bb, input_brigade);
459
455
460
            /* Flush now since we have the header and (enough of) the prefeched
456
            /* Flush now since we have the header and (enough of) the
461
             * body already.
457
             * prefeched body, or racing KeepAliveTimeout on the backend
458
             * side may kill our connection while we read more client data.
462
             */
459
             */
463
            flush = 1;
460
            flush = 1;
464
465
            /*
466
             * Save input_brigade in bb brigade. (At least) in the SSL case
467
             * input_brigade contains transient buckets whose data would get
468
             * overwritten during the next call of ap_get_brigade in the loop.
469
             * ap_save_brigade ensures these buckets to be set aside.
470
             * Calling ap_save_brigade with NULL as filter is OK, because
471
             * bb brigade already has been created and does not need to get
472
             * created by ap_save_brigade.
473
             */
474
            status = ap_save_brigade(NULL, &bb, &input_brigade, p);
475
            if (status != APR_SUCCESS) {
476
                return HTTP_INTERNAL_SERVER_ERROR;
477
            }
478
479
            header_brigade = NULL;
480
        }
461
        }
481
        else {
462
        else {
482
            bb = input_brigade;
463
            bb = input_brigade;
483
        }
464
        }
484
465
485
        rv = ap_proxy_pass_brigade(bucket_alloc, r, p_conn, origin, bb, flush);
466
        /* Once we hit EOS, we are ready to flush. */
467
        rv = ap_proxy_pass_brigade(bucket_alloc, r, p_conn, req->origin,
468
                                   input_brigade, flush || seen_eos);
486
        if (rv != OK) {
469
        if (rv != OK) {
487
            return rv;
470
            return rv;
488
        }
471
        }
Lines 506-512 Link Here
506
        }
489
        }
507
    }
490
    }
508
491
509
    if (bytes_streamed != cl_val) {
492
    if (bytes_streamed != req->cl_val) {
510
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01087)
493
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01087)
511
                      "client %s given Content-Length did not match"
494
                      "client %s given Content-Length did not match"
512
                      " number of body bytes read", r->connection->client_ip);
495
                      " number of body bytes read", r->connection->client_ip);
Lines 513-541 Link Here
513
        return HTTP_BAD_REQUEST;
496
        return HTTP_BAD_REQUEST;
514
    }
497
    }
515
498
516
    if (header_brigade) {
499
    if (!APR_BRIGADE_EMPTY(header_brigade)) {
517
        /* we never sent the header brigade since there was no request
500
        /* we never sent the header brigade since there was no request
518
         * body; send it now with the flush flag
501
         * body; send it now with the flush flag
519
         */
502
         */
520
        bb = header_brigade;
503
        return ap_proxy_pass_brigade(bucket_alloc, r, p_conn, req->origin,
521
        return(ap_proxy_pass_brigade(bucket_alloc, r, p_conn, origin, bb, 1));
504
                                     header_brigade, 1);
522
    }
505
    }
523
506
524
    return OK;
507
    return OK;
525
}
508
}
526
509
527
static int spool_reqbody_cl(apr_pool_t *p,
510
static int spool_reqbody_cl(proxy_http_req_t *req)
528
                                     request_rec *r,
529
                                     apr_bucket_brigade *header_brigade,
530
                                     apr_bucket_brigade *input_brigade,
531
                                     int force_cl)
532
{
511
{
512
    apr_pool_t *p = req->p;
513
    request_rec *r = req->r;
533
    int seen_eos = 0;
514
    int seen_eos = 0;
534
    apr_status_t status = APR_SUCCESS;
515
    apr_status_t status = APR_SUCCESS;
535
    apr_bucket_alloc_t *bucket_alloc = r->connection->bucket_alloc;
516
    apr_bucket_alloc_t *bucket_alloc = req->bucket_alloc;
517
    apr_bucket_brigade *input_brigade = req->input_brigade;
536
    apr_bucket_brigade *body_brigade;
518
    apr_bucket_brigade *body_brigade;
537
    apr_bucket *e;
519
    apr_bucket *e;
538
    apr_off_t bytes, bytes_spooled = 0, fsize = 0;
520
    apr_off_t bytes, fsize = 0;
539
    apr_file_t *tmpfile = NULL;
521
    apr_file_t *tmpfile = NULL;
540
    apr_off_t limit;
522
    apr_off_t limit;
541
523
Lines 562-574 Link Here
562
544
563
        apr_brigade_length(input_brigade, 1, &bytes);
545
        apr_brigade_length(input_brigade, 1, &bytes);
564
546
565
        if (bytes_spooled + bytes > MAX_MEM_SPOOL) {
547
        if (req->bytes_spooled + bytes > MAX_MEM_SPOOL) {
566
            /*
548
            /*
567
             * LimitRequestBody does not affect Proxy requests (Should it?).
549
             * LimitRequestBody does not affect Proxy requests (Should it?).
568
             * Let it take effect if we decide to store the body in a
550
             * Let it take effect if we decide to store the body in a
569
             * temporary file on disk.
551
             * temporary file on disk.
570
             */
552
             */
571
            if (limit && (bytes_spooled + bytes > limit)) {
553
            if (limit && (req->bytes_spooled + bytes > limit)) {
572
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01088)
554
                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01088)
573
                              "Request body is larger than the configured "
555
                              "Request body is larger than the configured "
574
                              "limit of %" APR_OFF_T_FMT, limit);
556
                              "limit of %" APR_OFF_T_FMT, limit);
Lines 638-644 Link Here
638
620
639
        }
621
        }
640
622
641
        bytes_spooled += bytes;
623
        req->bytes_spooled += bytes;
642
624
643
        if (seen_eos) {
625
        if (seen_eos) {
644
            break;
626
            break;
Lines 656-695 Link Here
656
        return ap_map_http_request_error(status, HTTP_BAD_REQUEST);
638
        return ap_map_http_request_error(status, HTTP_BAD_REQUEST);
657
    }
639
    }
658
640
659
    if (bytes_spooled || force_cl) {
641
    APR_BRIGADE_CONCAT(input_brigade, body_brigade);
660
        add_cl(p, bucket_alloc, header_brigade, apr_off_t_toa(p, bytes_spooled));
661
    }
662
    terminate_headers(bucket_alloc, header_brigade);
663
    APR_BRIGADE_CONCAT(header_brigade, body_brigade);
664
    if (tmpfile) {
642
    if (tmpfile) {
665
        apr_brigade_insert_file(header_brigade, tmpfile, 0, fsize, p);
643
        apr_brigade_insert_file(input_brigade, tmpfile, 0, fsize, p);
666
    }
644
    }
667
    if (apr_table_get(r->subprocess_env, "proxy-sendextracrlf")) {
645
    if (apr_table_get(r->subprocess_env, "proxy-sendextracrlf")) {
668
        e = apr_bucket_immortal_create(CRLF_ASCII, 2, bucket_alloc);
646
        e = apr_bucket_immortal_create(CRLF_ASCII, 2, bucket_alloc);
669
        APR_BRIGADE_INSERT_TAIL(header_brigade, e);
647
        APR_BRIGADE_INSERT_TAIL(input_brigade, e);
670
    }
648
    }
671
    return OK;
649
    return OK;
672
}
650
}
673
651
674
enum rb_methods {
652
static int ap_proxy_http_prefetch(proxy_http_req_t *req,
675
    RB_INIT = 0,
653
                                  apr_uri_t *uri, char *url)
676
    RB_STREAM_CL,
677
    RB_STREAM_CHUNKED,
678
    RB_SPOOL_CL
679
};
680
681
static int ap_proxy_http_prefetch(apr_pool_t *p, request_rec *r,
682
                                  proxy_conn_rec *p_conn, proxy_worker *worker,
683
                                  proxy_server_conf *conf,
684
                                  apr_uri_t *uri,
685
                                  char *url, char *server_portstr,
686
                                  apr_bucket_brigade *header_brigade,
687
                                  apr_bucket_brigade *input_brigade,
688
                                  char **old_cl_val, char **old_te_val,
689
                                  enum rb_methods *rb_method, int flushall)
690
{
654
{
655
    apr_pool_t *p = req->p;
656
    request_rec *r = req->r;
691
    conn_rec *c = r->connection;
657
    conn_rec *c = r->connection;
692
    apr_bucket_alloc_t *bucket_alloc = c->bucket_alloc;
658
    proxy_conn_rec *p_conn = req->backend;
659
    apr_bucket_alloc_t *bucket_alloc = req->bucket_alloc;
660
    apr_bucket_brigade *header_brigade = req->header_brigade;
661
    apr_bucket_brigade *input_brigade = req->input_brigade;
693
    apr_bucket_brigade *temp_brigade;
662
    apr_bucket_brigade *temp_brigade;
694
    apr_bucket *e;
663
    apr_bucket *e;
695
    char *buf;
664
    char *buf;
Lines 709-716 Link Here
709
    }
678
    }
710
679
711
    rv = ap_proxy_create_hdrbrgd(p, header_brigade, r, p_conn,
680
    rv = ap_proxy_create_hdrbrgd(p, header_brigade, r, p_conn,
712
                                 worker, conf, uri, url, server_portstr,
681
                                 req->worker, req->sconf,
713
                                 old_cl_val, old_te_val);
682
                                 uri, url, req->server_portstr,
683
                                 &req->old_cl_val, &req->old_te_val);
714
    if (rv != OK) {
684
    if (rv != OK) {
715
        return rv;
685
        return rv;
716
    }
686
    }
Lines 727-735 Link Here
727
    if (!r->kept_body && r->main) {
697
    if (!r->kept_body && r->main) {
728
        /* XXX: Why DON'T sub-requests use keepalives? */
698
        /* XXX: Why DON'T sub-requests use keepalives? */
729
        p_conn->close = 1;
699
        p_conn->close = 1;
730
        *old_cl_val = NULL;
700
        req->old_te_val = NULL;
731
        *old_te_val = NULL;
701
        req->old_cl_val = NULL;
732
        *rb_method = RB_STREAM_CL;
702
        req->rb_method = RB_STREAM_CL;
733
        e = apr_bucket_eos_create(input_brigade->bucket_alloc);
703
        e = apr_bucket_eos_create(input_brigade->bucket_alloc);
734
        APR_BRIGADE_INSERT_TAIL(input_brigade, e);
704
        APR_BRIGADE_INSERT_TAIL(input_brigade, e);
735
        goto skip_body;
705
        goto skip_body;
Lines 743-760 Link Here
743
     * encoding has been done by the extensions' handler, and
713
     * encoding has been done by the extensions' handler, and
744
     * do not modify add_te_chunked's logic
714
     * do not modify add_te_chunked's logic
745
     */
715
     */
746
    if (*old_te_val && ap_cstr_casecmp(*old_te_val, "chunked") != 0) {
716
    if (req->old_te_val && ap_cstr_casecmp(req->old_te_val, "chunked") != 0) {
747
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01093)
717
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01093)
748
                      "%s Transfer-Encoding is not supported", *old_te_val);
718
                      "%s Transfer-Encoding is not supported",
719
                      req->old_te_val);
749
        return HTTP_INTERNAL_SERVER_ERROR;
720
        return HTTP_INTERNAL_SERVER_ERROR;
750
    }
721
    }
751
722
752
    if (*old_cl_val && *old_te_val) {
723
    if (req->old_cl_val && req->old_te_val) {
753
        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01094)
724
        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01094)
754
                      "client %s (%s) requested Transfer-Encoding "
725
                      "client %s (%s) requested Transfer-Encoding "
755
                      "chunked body with Content-Length (C-L ignored)",
726
                      "chunked body with Content-Length (C-L ignored)",
756
                      c->client_ip, c->remote_host ? c->remote_host: "");
727
                      c->client_ip, c->remote_host ? c->remote_host: "");
757
        *old_cl_val = NULL;
728
        req->old_cl_val = NULL;
758
        p_conn->close = 1;
729
        p_conn->close = 1;
759
    }
730
    }
760
731
Lines 767-773 Link Here
767
     * reasonable size.
738
     * reasonable size.
768
     */
739
     */
769
    temp_brigade = apr_brigade_create(p, bucket_alloc);
740
    temp_brigade = apr_brigade_create(p, bucket_alloc);
770
    block = (flushall) ? APR_NONBLOCK_READ : APR_BLOCK_READ;
741
    block = req->flushall ? APR_NONBLOCK_READ : APR_BLOCK_READ;
771
    do {
742
    do {
772
        status = ap_get_brigade(r->input_filters, temp_brigade,
743
        status = ap_get_brigade(r->input_filters, temp_brigade,
773
                                AP_MODE_READBYTES, block,
744
                                AP_MODE_READBYTES, block,
Lines 818-824 Link Here
818
     */
789
     */
819
    } while ((bytes_read < MAX_MEM_SPOOL - 80)
790
    } while ((bytes_read < MAX_MEM_SPOOL - 80)
820
              && !APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))
791
              && !APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))
821
              && block == APR_BLOCK_READ);
792
              && !req->flushall);
822
793
823
    /* Use chunked request body encoding or send a content-length body?
794
    /* Use chunked request body encoding or send a content-length body?
824
     *
795
     *
Lines 864-918 Link Here
864
         * If we expected no body, and read no body, do not set
835
         * If we expected no body, and read no body, do not set
865
         * the Content-Length.
836
         * the Content-Length.
866
         */
837
         */
867
        if (*old_cl_val || *old_te_val || bytes_read) {
838
        if (req->old_cl_val || req->old_te_val || bytes_read) {
868
            *old_cl_val = apr_off_t_toa(r->pool, bytes_read);
839
            req->old_cl_val = apr_off_t_toa(r->pool, bytes_read);
840
            req->cl_val = bytes_read;
869
        }
841
        }
870
        *rb_method = RB_STREAM_CL;
842
        req->rb_method = RB_STREAM_CL;
871
    }
843
    }
872
    else if (*old_te_val) {
844
    else if (req->old_te_val) {
873
        if (force10
845
        if (force10
874
             || (apr_table_get(r->subprocess_env, "proxy-sendcl")
846
             || (apr_table_get(r->subprocess_env, "proxy-sendcl")
875
                  && !apr_table_get(r->subprocess_env, "proxy-sendchunks")
847
                  && !apr_table_get(r->subprocess_env, "proxy-sendchunks")
876
                  && !apr_table_get(r->subprocess_env, "proxy-sendchunked"))) {
848
                  && !apr_table_get(r->subprocess_env, "proxy-sendchunked"))) {
877
            *rb_method = RB_SPOOL_CL;
849
            req->rb_method = RB_SPOOL_CL;
878
        }
850
        }
879
        else {
851
        else {
880
            *rb_method = RB_STREAM_CHUNKED;
852
            req->rb_method = RB_STREAM_CHUNKED;
881
        }
853
        }
882
    }
854
    }
883
    else if (*old_cl_val) {
855
    else if (req->old_cl_val) {
884
        if (r->input_filters == r->proto_input_filters) {
856
        if (r->input_filters == r->proto_input_filters) {
885
            *rb_method = RB_STREAM_CL;
857
            char *endstr;
858
            status = apr_strtoff(&req->cl_val, req->old_cl_val, &endstr, 10);
859
            if (status != APR_SUCCESS || *endstr || req->cl_val < 0) {
860
                ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(01085)
861
                              "could not parse request Content-Length (%s)",
862
                              req->old_cl_val);
863
                return HTTP_BAD_REQUEST;
864
            }
865
            req->rb_method = RB_STREAM_CL;
886
        }
866
        }
887
        else if (!force10
867
        else if (!force10
888
                  && (apr_table_get(r->subprocess_env, "proxy-sendchunks")
868
                  && (apr_table_get(r->subprocess_env, "proxy-sendchunks")
889
                      || apr_table_get(r->subprocess_env, "proxy-sendchunked"))
869
                      || apr_table_get(r->subprocess_env, "proxy-sendchunked"))
890
                  && !apr_table_get(r->subprocess_env, "proxy-sendcl")) {
870
                  && !apr_table_get(r->subprocess_env, "proxy-sendcl")) {
891
            *rb_method = RB_STREAM_CHUNKED;
871
            req->rb_method = RB_STREAM_CHUNKED;
892
        }
872
        }
893
        else {
873
        else {
894
            *rb_method = RB_SPOOL_CL;
874
            req->rb_method = RB_SPOOL_CL;
895
        }
875
        }
896
    }
876
    }
897
    else {
877
    else {
898
        /* This is an appropriate default; very efficient for no-body
878
        /* This is an appropriate default; very efficient for no-body
899
         * requests, and has the behavior that it will not add any C-L
879
         * requests, and has the behavior that it will not add any C-L
900
         * when the *old_cl_val is NULL.
880
         * when the old_cl_val is NULL.
901
         */
881
         */
902
        *rb_method = RB_SPOOL_CL;
882
        req->rb_method = RB_SPOOL_CL;
903
    }
883
    }
904
884
905
    /* If we have to spool the body, do it now, before connecting or
885
    switch (req->rb_method) {
906
     * reusing the backend connection.
886
    case RB_STREAM_CHUNKED:
907
     */
887
        add_te_chunked(req->p, bucket_alloc, header_brigade);
908
    if (*rb_method == RB_SPOOL_CL) {
888
        break;
909
        rv = spool_reqbody_cl(p, r, header_brigade, input_brigade,
889
910
                              (bytes_read > 0)
890
    case RB_STREAM_CL:
911
                              || (*old_cl_val != NULL)
891
        if (req->old_cl_val) {
912
                              || (*old_te_val != NULL));
892
            add_cl(req->p, bucket_alloc, header_brigade, req->old_cl_val);
893
        }
894
        break;
895
896
    default: /* => RB_SPOOL_CL */
897
        /* If we have to spool the body, do it now, before connecting or
898
         * reusing the backend connection.
899
         */
900
        rv = spool_reqbody_cl(req);
913
        if (rv != OK) {
901
        if (rv != OK) {
914
            return rv;
902
            return rv;
915
        }
903
        }
904
        if (bytes_read > 0
905
                || req->old_te_val
906
                || req->old_cl_val
907
                || req->bytes_spooled) {
908
            add_cl(p, bucket_alloc, header_brigade,
909
                   apr_off_t_toa(p, req->bytes_spooled));
910
        }
916
    }
911
    }
917
912
918
/* Yes I hate gotos.  This is the subrequest shortcut */
913
/* Yes I hate gotos.  This is the subrequest shortcut */
Lines 933-970 Link Here
933
        e = apr_bucket_pool_create(buf, strlen(buf), p, c->bucket_alloc);
928
        e = apr_bucket_pool_create(buf, strlen(buf), p, c->bucket_alloc);
934
        APR_BRIGADE_INSERT_TAIL(header_brigade, e);
929
        APR_BRIGADE_INSERT_TAIL(header_brigade, e);
935
    }
930
    }
931
    terminate_headers(bucket_alloc, header_brigade);
936
932
937
    return OK;
933
    return OK;
938
}
934
}
939
935
940
static
936
static int ap_proxy_http_request(proxy_http_req_t *req)
941
int ap_proxy_http_request(apr_pool_t *p, request_rec *r,
942
                                   proxy_conn_rec *p_conn,
943
                                   apr_bucket_brigade *header_brigade,
944
                                   apr_bucket_brigade *input_brigade,
945
                                   char *old_cl_val, char *old_te_val,
946
                                   enum rb_methods rb_method, int flushall)
947
{
937
{
948
    int rv;
938
    int rv;
949
    conn_rec *origin = p_conn->connection;
939
    request_rec *r = req->r;
940
    apr_bucket_alloc_t *bucket_alloc = req->bucket_alloc;
941
    apr_bucket_brigade *header_brigade = req->header_brigade;
942
    apr_bucket_brigade *input_brigade = req->input_brigade;
950
943
951
    /* send the request body, if any. */
944
    /* send the request header/body, if any. */
952
    switch(rb_method) {
945
    switch (req->rb_method) {
953
    case RB_STREAM_CHUNKED:
946
    case RB_STREAM_CHUNKED:
954
        rv = stream_reqbody_chunked(p, r, p_conn, origin, header_brigade,
947
        if (req->do_100_continue) {
955
                                    input_brigade, flushall);
948
            rv = ap_proxy_pass_brigade(bucket_alloc, r, req->backend,
949
                                       req->origin, header_brigade, 1);
950
        }
951
        else {
952
            rv = stream_reqbody_chunked(req);
953
        }
956
        break;
954
        break;
955
957
    case RB_STREAM_CL:
956
    case RB_STREAM_CL:
958
        rv = stream_reqbody_cl(p, r, p_conn, origin, header_brigade,
957
        if (req->do_100_continue) {
959
                               input_brigade, old_cl_val, flushall);
958
            rv = ap_proxy_pass_brigade(bucket_alloc, r, req->backend,
959
                                       req->origin, header_brigade, 1);
960
        }
961
        else {
962
            rv = stream_reqbody_cl(req);
963
        }
960
        break;
964
        break;
965
961
    case RB_SPOOL_CL:
966
    case RB_SPOOL_CL:
962
        /* Prefetch has spooled the whole body, simply forward it now.
967
        /* Prefetch has built the header and spooled the whole body;
963
         * This is all a single brigade, pass with flush flagged.
968
         * if we don't expect 100-continue we can flush both all at once,
969
         * otherwise flush the header only.
964
         */
970
         */
965
        rv = ap_proxy_pass_brigade(r->connection->bucket_alloc,
971
        if (!req->do_100_continue) {
966
                                   r, p_conn, origin, header_brigade, 1);
972
            APR_BRIGADE_CONCAT(header_brigade, input_brigade);
973
        }
974
        rv = ap_proxy_pass_brigade(bucket_alloc, r, req->backend,
975
                                   req->origin, header_brigade, 1);
967
        break;
976
        break;
977
968
    default:
978
    default:
969
        /* shouldn't be possible */
979
        /* shouldn't be possible */
970
        rv = HTTP_INTERNAL_SERVER_ERROR;
980
        rv = HTTP_INTERNAL_SERVER_ERROR;
Lines 976-982 Link Here
976
        /* apr_status_t value has been logged in lower level method */
986
        /* apr_status_t value has been logged in lower level method */
977
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01097)
987
        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01097)
978
                      "pass request body failed to %pI (%s) from %s (%s)",
988
                      "pass request body failed to %pI (%s) from %s (%s)",
979
                      p_conn->addr, p_conn->hostname ? p_conn->hostname: "",
989
                      req->backend->addr,
990
                      req->backend->hostname ? req->backend->hostname: "",
980
                      c->client_ip, c->remote_host ? c->remote_host: "");
991
                      c->client_ip, c->remote_host ? c->remote_host: "");
981
        return rv;
992
        return rv;
982
    }
993
    }
Lines 1252-1262 Link Here
1252
}
1263
}
1253
1264
1254
static
1265
static
1255
int ap_proxy_http_process_response(apr_pool_t * p, request_rec *r,
1266
int ap_proxy_http_process_response(proxy_http_req_t *req)
1256
        proxy_conn_rec **backend_ptr, proxy_worker *worker,
1257
        proxy_server_conf *conf, char *server_portstr)
1258
{
1267
{
1268
    apr_pool_t *p = req->p;
1269
    request_rec *r = req->r;
1259
    conn_rec *c = r->connection;
1270
    conn_rec *c = r->connection;
1271
    proxy_worker *worker = req->worker;
1272
    proxy_conn_rec *backend = req->backend;
1273
    conn_rec *origin = req->origin;
1274
    int do_100_continue = req->do_100_continue;
1275
1260
    char *buffer;
1276
    char *buffer;
1261
    char fixed_buffer[HUGE_STRING_LEN];
1277
    char fixed_buffer[HUGE_STRING_LEN];
1262
    const char *buf;
1278
    const char *buf;
Lines 1279-1294 Link Here
1279
    int proxy_status = OK;
1295
    int proxy_status = OK;
1280
    const char *original_status_line = r->status_line;
1296
    const char *original_status_line = r->status_line;
1281
    const char *proxy_status_line = NULL;
1297
    const char *proxy_status_line = NULL;
1282
    proxy_conn_rec *backend = *backend_ptr;
1283
    conn_rec *origin = backend->connection;
1284
    apr_interval_time_t old_timeout = 0;
1298
    apr_interval_time_t old_timeout = 0;
1285
    proxy_dir_conf *dconf;
1299
    proxy_dir_conf *dconf;
1286
    int do_100_continue;
1287
1300
1288
    dconf = ap_get_module_config(r->per_dir_config, &proxy_module);
1301
    dconf = ap_get_module_config(r->per_dir_config, &proxy_module);
1289
1302
1290
    do_100_continue = PROXY_DO_100_CONTINUE(worker, r);
1291
1292
    bb = apr_brigade_create(p, c->bucket_alloc);
1303
    bb = apr_brigade_create(p, c->bucket_alloc);
1293
    pass_bb = apr_brigade_create(p, c->bucket_alloc);
1304
    pass_bb = apr_brigade_create(p, c->bucket_alloc);
1294
1305
Lines 1307-1313 Link Here
1307
    }
1318
    }
1308
1319
1309
    /* Setup for 100-Continue timeout if appropriate */
1320
    /* Setup for 100-Continue timeout if appropriate */
1310
    if (do_100_continue) {
1321
    if (do_100_continue && worker->s->ping_timeout_set) {
1311
        apr_socket_timeout_get(backend->sock, &old_timeout);
1322
        apr_socket_timeout_get(backend->sock, &old_timeout);
1312
        if (worker->s->ping_timeout != old_timeout) {
1323
        if (worker->s->ping_timeout != old_timeout) {
1313
            apr_status_t rc;
1324
            apr_status_t rc;
Lines 1332-1337 Link Here
1332
                   origin->local_addr->port));
1343
                   origin->local_addr->port));
1333
    do {
1344
    do {
1334
        apr_status_t rc;
1345
        apr_status_t rc;
1346
        int major = 0, minor = 0;
1347
        int toclose = 0;
1335
1348
1336
        apr_brigade_cleanup(bb);
1349
        apr_brigade_cleanup(bb);
1337
1350
Lines 1404-1412 Link Here
1404
         * This is buggy if we ever see an HTTP/1.10
1417
         * This is buggy if we ever see an HTTP/1.10
1405
         */
1418
         */
1406
        if (apr_date_checkmask(buffer, "HTTP/#.# ###*")) {
1419
        if (apr_date_checkmask(buffer, "HTTP/#.# ###*")) {
1407
            int major, minor;
1408
            int toclose;
1409
1410
            major = buffer[5] - '0';
1420
            major = buffer[5] - '0';
1411
            minor = buffer[7] - '0';
1421
            minor = buffer[7] - '0';
1412
1422
Lines 1457-1464 Link Here
1457
                         "Set-Cookie", NULL);
1467
                         "Set-Cookie", NULL);
1458
1468
1459
            /* shove the headers direct into r->headers_out */
1469
            /* shove the headers direct into r->headers_out */
1460
            ap_proxy_read_headers(r, backend->r, buffer, response_field_size, origin,
1470
            ap_proxy_read_headers(r, backend->r, buffer, response_field_size,
1461
                                  &pread_len);
1471
                                  origin, &pread_len);
1462
1472
1463
            if (r->headers_out == NULL) {
1473
            if (r->headers_out == NULL) {
1464
                ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(01106)
1474
                ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(01106)
Lines 1542-1548 Link Here
1542
            r->headers_out = ap_proxy_clean_warnings(p, r->headers_out);
1552
            r->headers_out = ap_proxy_clean_warnings(p, r->headers_out);
1543
1553
1544
            /* handle Via header in response */
1554
            /* handle Via header in response */
1545
            if (conf->viaopt != via_off && conf->viaopt != via_block) {
1555
            if (req->sconf->viaopt != via_off
1556
                    && req->sconf->viaopt != via_block) {
1546
                const char *server_name = ap_get_server_name(r);
1557
                const char *server_name = ap_get_server_name(r);
1547
                /* If USE_CANONICAL_NAME_OFF was configured for the proxy virtual host,
1558
                /* If USE_CANONICAL_NAME_OFF was configured for the proxy virtual host,
1548
                 * then the server name returned by ap_get_server_name() is the
1559
                 * then the server name returned by ap_get_server_name() is the
Lines 1553-1570 Link Here
1553
                    server_name = r->server->server_hostname;
1564
                    server_name = r->server->server_hostname;
1554
                /* create a "Via:" response header entry and merge it */
1565
                /* create a "Via:" response header entry and merge it */
1555
                apr_table_addn(r->headers_out, "Via",
1566
                apr_table_addn(r->headers_out, "Via",
1556
                               (conf->viaopt == via_full)
1567
                               (req->sconf->viaopt == via_full)
1557
                                     ? apr_psprintf(p, "%d.%d %s%s (%s)",
1568
                                     ? apr_psprintf(p, "%d.%d %s%s (%s)",
1558
                                           HTTP_VERSION_MAJOR(r->proto_num),
1569
                                           HTTP_VERSION_MAJOR(r->proto_num),
1559
                                           HTTP_VERSION_MINOR(r->proto_num),
1570
                                           HTTP_VERSION_MINOR(r->proto_num),
1560
                                           server_name,
1571
                                           server_name,
1561
                                           server_portstr,
1572
                                           req->server_portstr,
1562
                                           AP_SERVER_BASEVERSION)
1573
                                           AP_SERVER_BASEVERSION)
1563
                                     : apr_psprintf(p, "%d.%d %s%s",
1574
                                     : apr_psprintf(p, "%d.%d %s%s",
1564
                                           HTTP_VERSION_MAJOR(r->proto_num),
1575
                                           HTTP_VERSION_MAJOR(r->proto_num),
1565
                                           HTTP_VERSION_MINOR(r->proto_num),
1576
                                           HTTP_VERSION_MINOR(r->proto_num),
1566
                                           server_name,
1577
                                           server_name,
1567
                                           server_portstr)
1578
                                           req->server_portstr)
1568
                );
1579
                );
1569
            }
1580
            }
1570
1581
Lines 1582-1602 Link Here
1582
        }
1593
        }
1583
1594
1584
        if (ap_is_HTTP_INFO(proxy_status)) {
1595
        if (ap_is_HTTP_INFO(proxy_status)) {
1585
            interim_response++;
1586
            if (do_100_continue
1587
                && (r->status == HTTP_CONTINUE)) {
1588
                /* Done with the 100 continue */
1589
                do_100_continue = 0;
1590
                /* Reset to old timeout if we've adjusted it */
1591
                if  (worker->s->ping_timeout != old_timeout) {
1592
                    apr_socket_timeout_set(backend->sock, old_timeout);
1593
                }
1594
            }
1595
        }
1596
        else {
1597
            interim_response = 0;
1598
        }
1599
        if (interim_response) {
1600
            /* RFC2616 tells us to forward this.
1596
            /* RFC2616 tells us to forward this.
1601
             *
1597
             *
1602
             * OTOH, an interim response here may mean the backend
1598
             * OTOH, an interim response here may mean the backend
Lines 1617-1623 Link Here
1617
            ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r,
1613
            ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r,
1618
                          "HTTP: received interim %d response", r->status);
1614
                          "HTTP: received interim %d response", r->status);
1619
            if (!policy
1615
            if (!policy
1620
                    || (!strcasecmp(policy, "RFC") && ((r->expecting_100 = 1)))) {
1616
                    || (proxy_status == HTTP_CONTINUE
1617
                        && r->expecting_100)
1618
                    || (!strcasecmp(policy, "RFC")
1619
                        && (proxy_status != HTTP_CONTINUE
1620
                            || (r->expecting_100 = 1)))) {
1621
                ap_send_interim_response(r, 1);
1621
                ap_send_interim_response(r, 1);
1622
            }
1622
            }
1623
            /* FIXME: refine this to be able to specify per-response-status
1623
            /* FIXME: refine this to be able to specify per-response-status
Lines 1627-1634 Link Here
1627
                ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(01108)
1627
                ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(01108)
1628
                              "undefined proxy interim response policy");
1628
                              "undefined proxy interim response policy");
1629
            }
1629
            }
1630
            interim_response++;
1630
        }
1631
        }
1632
        else {
1633
            interim_response = 0;
1634
        }
1631
1635
1636
        /* If we still do 100-continue (end-to-end or ping), either the
1637
         * current response is the expected "100 Continue" and we are done
1638
         * with this mode, or this is another interim response and we'll wait
1639
         * for the next one, or this is a final response and hence the backend
1640
         * did not honor our expectation.
1641
         */
1642
        if (do_100_continue
1643
                && (proxy_status == HTTP_CONTINUE || !interim_response)) {
1644
            /* Reset to old timeout iff we've adjusted it. */
1645
            if (worker->s->ping_timeout_set) {
1646
                apr_socket_timeout_set(backend->sock, old_timeout);
1647
            }
1648
            /* RFC 7231 - Section 5.1.1 - Expect - Requirement for servers
1649
             *   A server that responds with a final status code before
1650
             *   reading the entire message body SHOULD indicate in that
1651
             *   response whether it intends to close the connection or
1652
             *   continue reading and discarding the request message.
1653
             *
1654
             * So, if this response is not an interim 100 Continue, we can
1655
             * avoid sending the request body if the backend responded with
1656
             * "Connection: close" or HTTP < 1.1, and either let the core
1657
             * discard it or the caller try another balancer member with the
1658
             * same body (given status 503, though not implemented yet).
1659
             */
1660
            if (proxy_status == HTTP_CONTINUE
1661
                    || (major > 0 && minor > 0 && !toclose)) {
1662
                int status;
1663
1664
                /* Send the request body (fully). */
1665
                switch(req->rb_method) {
1666
                case RB_STREAM_CL:
1667
                    status = stream_reqbody_cl(req);
1668
                    break;
1669
                case RB_STREAM_CHUNKED:
1670
                    status = stream_reqbody_chunked(req);
1671
                    break;
1672
                case RB_SPOOL_CL:
1673
                    /* Prefetch has spooled the whole body, flush it. */
1674
                    status = ap_proxy_pass_brigade(req->bucket_alloc, r,
1675
                                                   backend, origin,
1676
                                                   req->input_brigade, 1);
1677
                    break;
1678
                default:
1679
                    /* Shouldn't happen */
1680
                    status = HTTP_INTERNAL_SERVER_ERROR;
1681
                    break;
1682
                }
1683
                if (status != OK) {
1684
                    ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
1685
                            APLOGNO() "pass request body failed "
1686
                            "to %pI (%s) from %s (%s) with status %i",
1687
                            backend->addr,
1688
                            backend->hostname ? backend->hostname : "",
1689
                            c->client_ip,
1690
                            c->remote_host ? c->remote_host : "",
1691
                            status);
1692
                    backend->close = 1;
1693
                    proxy_run_detach_backend(r, backend);
1694
                    return status;
1695
                }
1696
            }
1697
1698
            /* Once only! */
1699
            do_100_continue = 0;
1700
        }
1701
1632
        /* Moved the fixups of Date headers and those affected by
1702
        /* Moved the fixups of Date headers and those affected by
1633
         * ProxyPassReverse/etc from here to ap_proxy_read_headers
1703
         * ProxyPassReverse/etc from here to ap_proxy_read_headers
1634
         */
1704
         */
Lines 1753-1759 Link Here
1753
1823
1754
                    rv = ap_get_brigade(backend->r->input_filters, bb,
1824
                    rv = ap_get_brigade(backend->r->input_filters, bb,
1755
                                        AP_MODE_READBYTES, mode,
1825
                                        AP_MODE_READBYTES, mode,
1756
                                        conf->io_buffer_size);
1826
                                        req->sconf->io_buffer_size);
1757
1827
1758
                    /* ap_get_brigade will return success with an empty brigade
1828
                    /* ap_get_brigade will return success with an empty brigade
1759
                     * for a non-blocking read which would block: */
1829
                     * for a non-blocking read which would block: */
Lines 1863-1869 Link Here
1863
                        ap_proxy_release_connection(backend->worker->s->scheme,
1933
                        ap_proxy_release_connection(backend->worker->s->scheme,
1864
                                backend, r->server);
1934
                                backend, r->server);
1865
                        /* Ensure that the backend is not reused */
1935
                        /* Ensure that the backend is not reused */
1866
                        *backend_ptr = NULL;
1936
                        req->backend = NULL;
1867
1937
1868
                    }
1938
                    }
1869
1939
Lines 1872-1883 Link Here
1872
                        || c->aborted) {
1942
                        || c->aborted) {
1873
                        /* Ack! Phbtt! Die! User aborted! */
1943
                        /* Ack! Phbtt! Die! User aborted! */
1874
                        /* Only close backend if we haven't got all from the
1944
                        /* Only close backend if we haven't got all from the
1875
                         * backend. Furthermore if *backend_ptr is NULL it is no
1945
                         * backend. Furthermore if req->backend is NULL it is no
1876
                         * longer safe to fiddle around with backend as it might
1946
                         * longer safe to fiddle around with backend as it might
1877
                         * be already in use by another thread.
1947
                         * be already in use by another thread.
1878
                         */
1948
                         */
1879
                        if (*backend_ptr) {
1949
                        if (req->backend) {
1880
                            backend->close = 1;  /* this causes socket close below */
1950
                            /* this causes socket close below */
1951
                            req->backend->close = 1;
1881
                        }
1952
                        }
1882
                        finish = TRUE;
1953
                        finish = TRUE;
1883
                    }
1954
                    }
Lines 1901-1907 Link Here
1901
            proxy_run_detach_backend(r, backend);
1972
            proxy_run_detach_backend(r, backend);
1902
            ap_proxy_release_connection(backend->worker->s->scheme,
1973
            ap_proxy_release_connection(backend->worker->s->scheme,
1903
                    backend, r->server);
1974
                    backend, r->server);
1904
            *backend_ptr = NULL;
1975
            req->backend = NULL;
1905
1976
1906
            /* Pass EOS bucket down the filter chain. */
1977
            /* Pass EOS bucket down the filter chain. */
1907
            e = apr_bucket_eos_create(c->bucket_alloc);
1978
            e = apr_bucket_eos_create(c->bucket_alloc);
Lines 1916-1923 Link Here
1916
     * created from scpool and this pool can be freed before this brigade. */
1987
     * created from scpool and this pool can be freed before this brigade. */
1917
    apr_brigade_cleanup(bb);
1988
    apr_brigade_cleanup(bb);
1918
1989
1919
    if (*backend_ptr) {
1990
    if (req->backend) {
1920
        proxy_run_detach_backend(r, backend);
1991
        proxy_run_detach_backend(r, req->backend);
1921
    }
1992
    }
1922
1993
1923
    /* See define of AP_MAX_INTERIM_RESPONSES for why */
1994
    /* See define of AP_MAX_INTERIM_RESPONSES for why */
Lines 1959-1978 Link Here
1959
                              apr_port_t proxyport)
2030
                              apr_port_t proxyport)
1960
{
2031
{
1961
    int status;
2032
    int status;
1962
    char server_portstr[32];
1963
    char *scheme;
2033
    char *scheme;
1964
    const char *proxy_function;
2034
    const char *proxy_function;
1965
    const char *u;
2035
    const char *u;
1966
    apr_bucket_brigade *header_brigade;
2036
    proxy_http_req_t *req = NULL;
1967
    apr_bucket_brigade *input_brigade;
1968
    proxy_conn_rec *backend = NULL;
2037
    proxy_conn_rec *backend = NULL;
1969
    int is_ssl = 0;
2038
    int is_ssl = 0;
1970
    conn_rec *c = r->connection;
2039
    conn_rec *c = r->connection;
1971
    int retry = 0;
2040
    int retry = 0;
1972
    char *old_cl_val = NULL, *old_te_val = NULL;
1973
    enum rb_methods rb_method = RB_INIT;
1974
    char *locurl = url;
2041
    char *locurl = url;
1975
    int flushall = 0;
1976
    int toclose = 0;
2042
    int toclose = 0;
1977
    /*
2043
    /*
1978
     * Use a shorter-lived pool to reduce memory usage
2044
     * Use a shorter-lived pool to reduce memory usage
Lines 2014-2020 Link Here
2014
    }
2080
    }
2015
    ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "HTTP: serving URL %s", url);
2081
    ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "HTTP: serving URL %s", url);
2016
2082
2017
2018
    /* create space for state information */
2083
    /* create space for state information */
2019
    if ((status = ap_proxy_acquire_connection(proxy_function, &backend,
2084
    if ((status = ap_proxy_acquire_connection(proxy_function, &backend,
2020
                                              worker, r->server)) != OK)
2085
                                              worker, r->server)) != OK)
Lines 2022-2027 Link Here
2022
2087
2023
    backend->is_ssl = is_ssl;
2088
    backend->is_ssl = is_ssl;
2024
2089
2090
    req = apr_pcalloc(p, sizeof *req);
2091
    req->p = p;
2092
    req->r = r;
2093
    req->sconf = conf;
2094
    req->worker = worker;
2095
    req->backend = backend;
2096
    req->bucket_alloc = c->bucket_alloc;
2097
    if (r->expecting_100 || PROXY_DO_100_CONTINUE(worker, r)) {
2098
        req->do_100_continue = 1;
2099
    }
2100
    if (apr_table_get(r->subprocess_env, "proxy-flushall")) {
2101
        req->flushall = 1;
2102
    }
2103
    req->rb_method = RB_INIT;
2104
2025
    /*
2105
    /*
2026
     * In the case that we are handling a reverse proxy connection and this
2106
     * In the case that we are handling a reverse proxy connection and this
2027
     * is not a request that is coming over an already kept alive connection
2107
     * is not a request that is coming over an already kept alive connection
Lines 2035-2050 Link Here
2035
        backend->close = 1;
2115
        backend->close = 1;
2036
    }
2116
    }
2037
2117
2038
    if (apr_table_get(r->subprocess_env, "proxy-flushall")) {
2039
        flushall = 1;
2040
    }
2041
2042
    /* Step One: Determine Who To Connect To */
2118
    /* Step One: Determine Who To Connect To */
2043
    uri = apr_palloc(p, sizeof(*uri));
2119
    uri = apr_palloc(p, sizeof(*uri));
2044
    if ((status = ap_proxy_determine_connection(p, r, conf, worker, backend,
2120
    if ((status = ap_proxy_determine_connection(p, r, conf, worker, backend,
2045
                                            uri, &locurl, proxyname,
2121
                                            uri, &locurl, proxyname,
2046
                                            proxyport, server_portstr,
2122
                                            proxyport, req->server_portstr,
2047
                                            sizeof(server_portstr))) != OK)
2123
                                            sizeof req->server_portstr)))
2048
        goto cleanup;
2124
        goto cleanup;
2049
2125
2050
    /* Prefetch (nonlocking) the request body so to increase the chance to get
2126
    /* Prefetch (nonlocking) the request body so to increase the chance to get
Lines 2057-2069 Link Here
2057
     * to reduce to the minimum the unavoidable local is_socket_connected() vs
2133
     * to reduce to the minimum the unavoidable local is_socket_connected() vs
2058
     * remote keepalive race condition.
2134
     * remote keepalive race condition.
2059
     */
2135
     */
2060
    input_brigade = apr_brigade_create(p, c->bucket_alloc);
2136
    req->input_brigade = apr_brigade_create(p, req->bucket_alloc);
2061
    header_brigade = apr_brigade_create(p, c->bucket_alloc);
2137
    req->header_brigade = apr_brigade_create(p, req->bucket_alloc);
2062
    if ((status = ap_proxy_http_prefetch(p, r, backend, worker, conf, uri,
2138
    if ((status = ap_proxy_http_prefetch(req, uri, locurl)) != OK)
2063
                                         locurl, server_portstr,
2064
                                         header_brigade, input_brigade,
2065
                                         &old_cl_val, &old_te_val, &rb_method,
2066
                                         flushall)) != OK)
2067
        goto cleanup;
2139
        goto cleanup;
2068
2140
2069
    /* We need to reset backend->close now, since ap_proxy_http_prefetch() set
2141
    /* We need to reset backend->close now, since ap_proxy_http_prefetch() set
Lines 2076-2083 Link Here
2076
    backend->close = 0;
2148
    backend->close = 0;
2077
2149
2078
    while (retry < 2) {
2150
    while (retry < 2) {
2079
        conn_rec *backconn;
2080
2081
        if (retry) {
2151
        if (retry) {
2082
            char *newurl = url;
2152
            char *newurl = url;
2083
2153
Lines 2084-2090 Link Here
2084
            /* Step One (again): (Re)Determine Who To Connect To */
2154
            /* Step One (again): (Re)Determine Who To Connect To */
2085
            if ((status = ap_proxy_determine_connection(p, r, conf, worker,
2155
            if ((status = ap_proxy_determine_connection(p, r, conf, worker,
2086
                            backend, uri, &newurl, proxyname, proxyport,
2156
                            backend, uri, &newurl, proxyname, proxyport,
2087
                            server_portstr, sizeof(server_portstr))) != OK)
2157
                            req->server_portstr, sizeof req->server_portstr)))
2088
                break;
2158
                break;
2089
2159
2090
            /* The code assumes locurl is not changed during the loop, or
2160
            /* The code assumes locurl is not changed during the loop, or
Lines 2107-2124 Link Here
2107
        }
2177
        }
2108
2178
2109
        /* Step Three: Create conn_rec */
2179
        /* Step Three: Create conn_rec */
2110
        backconn = backend->connection;
2180
        req->origin = backend->connection;
2111
        if (!backconn) {
2181
        if (!req->origin) {
2112
            if ((status = ap_proxy_connection_create_ex(proxy_function,
2182
            if ((status = ap_proxy_connection_create_ex(proxy_function,
2113
                                                        backend, r)) != OK)
2183
                                                        backend, r)) != OK)
2114
                break;
2184
                break;
2115
            backconn = backend->connection;
2185
            req->origin = backend->connection;
2116
        }
2186
        }
2117
2187
2118
        /* Don't recycle the connection if prefetch (above) told not to do so */
2188
        /* Don't recycle the connection if prefetch (above) told not to do so */
2119
        if (toclose) {
2189
        if (toclose) {
2120
            backend->close = 1;
2190
            backend->close = 1;
2121
            backconn->keepalive = AP_CONN_CLOSE;
2191
            req->origin->keepalive = AP_CONN_CLOSE;
2122
        }
2192
        }
2123
2193
2124
        /* Step Four: Send the Request
2194
        /* Step Four: Send the Request
Lines 2125-2151 Link Here
2125
         * On the off-chance that we forced a 100-Continue as a
2195
         * On the off-chance that we forced a 100-Continue as a
2126
         * kinda HTTP ping test, allow for retries
2196
         * kinda HTTP ping test, allow for retries
2127
         */
2197
         */
2128
        if ((status = ap_proxy_http_request(p, r, backend,
2198
        status = ap_proxy_http_request(req);
2129
                                            header_brigade, input_brigade,
2199
        if (status != OK) {
2130
                                            old_cl_val, old_te_val, rb_method,
2131
                                            flushall)) != OK) {
2132
            proxy_run_detach_backend(r, backend);
2200
            proxy_run_detach_backend(r, backend);
2133
            if ((status == HTTP_SERVICE_UNAVAILABLE) &&
2201
            if (req->do_100_continue && status == HTTP_SERVICE_UNAVAILABLE) {
2134
                    PROXY_DO_100_CONTINUE(worker, r)) {
2135
                backend->close = 1;
2136
                ap_log_rerror(APLOG_MARK, APLOG_INFO, status, r, APLOGNO(01115)
2202
                ap_log_rerror(APLOG_MARK, APLOG_INFO, status, r, APLOGNO(01115)
2137
                              "HTTP: 100-Continue failed to %pI (%s)",
2203
                              "HTTP: 100-Continue failed to %pI (%s)",
2138
                              worker->cp->addr, worker->s->hostname_ex);
2204
                              worker->cp->addr, worker->s->hostname_ex);
2205
                backend->close = 1;
2139
                retry++;
2206
                retry++;
2140
                continue;
2207
                continue;
2141
            } else {
2142
                break;
2143
            }
2208
            }
2209
            break;
2144
        }
2210
        }
2145
2211
2146
        /* Step Five: Receive the Response... Fall thru to cleanup */
2212
        /* Step Five: Receive the Response... Fall thru to cleanup */
2147
        status = ap_proxy_http_process_response(p, r, &backend, worker,
2213
        status = ap_proxy_http_process_response(req);
2148
                                                conf, server_portstr);
2149
2214
2150
        break;
2215
        break;
2151
    }
2216
    }
Lines 2152-2161 Link Here
2152
2217
2153
    /* Step Six: Clean Up */
2218
    /* Step Six: Clean Up */
2154
cleanup:
2219
cleanup:
2155
    if (backend) {
2220
    if (req && req->backend) {
2156
        if (status != OK)
2221
        if (status != OK)
2157
            backend->close = 1;
2222
            req->backend->close = 1;
2158
        ap_proxy_http_cleanup(proxy_function, r, backend);
2223
        ap_proxy_http_cleanup(proxy_function, r, req->backend);
2159
    }
2224
    }
2160
    return status;
2225
    return status;
2161
}
2226
}
(-)server/protocol.c (-14 / +16 lines)
Lines 2283-2305 Link Here
2283
                      "Status is %d - not sending interim response", r->status);
2283
                      "Status is %d - not sending interim response", r->status);
2284
        return;
2284
        return;
2285
    }
2285
    }
2286
    if ((r->status == HTTP_CONTINUE) && !r->expecting_100) {
2286
    if (r->status == HTTP_CONTINUE) {
2287
        /*
2287
        if (!r->expecting_100) {
2288
         * Don't send 100-Continue when there was no Expect: 100-continue
2288
            /*
2289
         * in the request headers. For origin servers this is a SHOULD NOT
2289
             * Don't send 100-Continue when there was no Expect: 100-continue
2290
         * for proxies it is a MUST NOT according to RFC 2616 8.2.3
2290
             * in the request headers. For origin servers this is a SHOULD NOT
2291
             * for proxies it is a MUST NOT according to RFC 2616 8.2.3
2292
             */
2293
            return;
2294
        }
2295
2296
        /* if we send an interim response, we're no longer in a state of
2297
         * expecting one.  Also, this could feasibly be in a subrequest,
2298
         * so we need to propagate the fact that we responded.
2291
         */
2299
         */
2292
        return;
2300
        for (rr = r; rr != NULL; rr = rr->main) {
2301
            rr->expecting_100 = 0;
2302
        }
2293
    }
2303
    }
2294
2304
2295
    /* if we send an interim response, we're no longer in a state of
2296
     * expecting one.  Also, this could feasibly be in a subrequest,
2297
     * so we need to propagate the fact that we responded.
2298
     */
2299
    for (rr = r; rr != NULL; rr = rr->main) {
2300
        rr->expecting_100 = 0;
2301
    }
2302
2303
    status_line = apr_pstrcat(r->pool, AP_SERVER_PROTOCOL " ", r->status_line, CRLF, NULL);
2305
    status_line = apr_pstrcat(r->pool, AP_SERVER_PROTOCOL " ", r->status_line, CRLF, NULL);
2304
    ap_xlate_proto_to_ascii(status_line, strlen(status_line));
2306
    ap_xlate_proto_to_ascii(status_line, strlen(status_line));
2305
2307

Return to bug 60330