comparison src/http/v2/ngx_http_v2.c @ 6497:9d66d7ed2abb

HTTP/2: support for unbuffered upload of request body.
author Valentin Bartenev <vbart@nginx.com>
date Fri, 01 Apr 2016 15:57:10 +0300
parents 887cca40ba6a
children 80ba811112ed
comparison
equal deleted inserted replaced
6496:887cca40ba6a 6497:9d66d7ed2abb
3393 3393
3394 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); 3394 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
3395 return; 3395 return;
3396 } 3396 }
3397 3397
3398 r->headers_in.chunked = (r->headers_in.content_length_n == -1);
3399
3398 ngx_http_process_request(r); 3400 ngx_http_process_request(r);
3399 } 3401 }
3400 3402
3401 3403
3402 ngx_int_t 3404 ngx_int_t
3438 3440
3439 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); 3441 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
3440 3442
3441 len = r->headers_in.content_length_n; 3443 len = r->headers_in.content_length_n;
3442 3444
3445 if (r->request_body_no_buffering && !stream->in_closed) {
3446 r->request_body_in_file_only = 0;
3447
3448 if (len < 0 || len > (off_t) clcf->client_body_buffer_size) {
3449 len = clcf->client_body_buffer_size;
3450 }
3451
3452 if (len > NGX_HTTP_V2_MAX_WINDOW) {
3453 len = NGX_HTTP_V2_MAX_WINDOW;
3454 }
3455 }
3456
3443 if (len >= 0 && len <= (off_t) clcf->client_body_buffer_size 3457 if (len >= 0 && len <= (off_t) clcf->client_body_buffer_size
3444 && !r->request_body_in_file_only) 3458 && !r->request_body_in_file_only)
3445 { 3459 {
3446 rb->buf = ngx_create_temp_buf(r->pool, (size_t) len); 3460 rb->buf = ngx_create_temp_buf(r->pool, (size_t) len);
3447 3461
3456 if (rb->buf == NULL) { 3470 if (rb->buf == NULL) {
3457 return NGX_HTTP_INTERNAL_SERVER_ERROR; 3471 return NGX_HTTP_INTERNAL_SERVER_ERROR;
3458 } 3472 }
3459 3473
3460 if (stream->in_closed) { 3474 if (stream->in_closed) {
3475 r->request_body_no_buffering = 0;
3461 return ngx_http_v2_process_request_body(r, NULL, 0, 1); 3476 return ngx_http_v2_process_request_body(r, NULL, 0, 1);
3462 } 3477 }
3463 3478
3464 stream->no_flow_control = 1; 3479 if (r->request_body_no_buffering) {
3465 3480 stream->no_flow_control = 0;
3466 stream->recv_window = NGX_HTTP_V2_MAX_WINDOW; 3481 stream->recv_window = (size_t) len;
3482
3483 } else {
3484 stream->no_flow_control = 1;
3485 stream->recv_window = NGX_HTTP_V2_MAX_WINDOW;
3486 }
3467 3487
3468 if (ngx_http_v2_send_window_update(stream->connection, stream->node->id, 3488 if (ngx_http_v2_send_window_update(stream->connection, stream->node->id,
3469 stream->recv_window) 3489 stream->recv_window)
3470 == NGX_ERROR) 3490 == NGX_ERROR)
3471 { 3491 {
3523 3543
3524 if (fc->read->timer_set) { 3544 if (fc->read->timer_set) {
3525 ngx_del_timer(fc->read); 3545 ngx_del_timer(fc->read);
3526 } 3546 }
3527 3547
3548 if (r->request_body_no_buffering) {
3549 ngx_post_event(fc->read, &ngx_posted_events);
3550 return NGX_OK;
3551 }
3552
3528 rc = ngx_http_v2_filter_request_body(r); 3553 rc = ngx_http_v2_filter_request_body(r);
3529 3554
3530 if (rc != NGX_OK) { 3555 if (rc != NGX_OK) {
3531 return rc; 3556 return rc;
3532 } 3557 }
3550 return NGX_OK; 3575 return NGX_OK;
3551 } 3576 }
3552 3577
3553 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); 3578 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
3554 ngx_add_timer(fc->read, clcf->client_body_timeout); 3579 ngx_add_timer(fc->read, clcf->client_body_timeout);
3580
3581 if (r->request_body_no_buffering) {
3582 ngx_post_event(fc->read, &ngx_posted_events);
3583 return NGX_OK;
3584 }
3555 3585
3556 if (buf->sync) { 3586 if (buf->sync) {
3557 return ngx_http_v2_filter_request_body(r); 3587 return ngx_http_v2_filter_request_body(r);
3558 } 3588 }
3559 3589
3570 ngx_http_request_body_t *rb; 3600 ngx_http_request_body_t *rb;
3571 ngx_http_core_loc_conf_t *clcf; 3601 ngx_http_core_loc_conf_t *clcf;
3572 3602
3573 rb = r->request_body; 3603 rb = r->request_body;
3574 buf = rb->buf; 3604 buf = rb->buf;
3605
3606 if (buf->pos == buf->last && rb->rest) {
3607 cl = NULL;
3608 goto update;
3609 }
3575 3610
3576 cl = ngx_chain_get_free_buf(r->pool, &rb->free); 3611 cl = ngx_chain_get_free_buf(r->pool, &rb->free);
3577 if (cl == NULL) { 3612 if (cl == NULL) {
3578 return NGX_HTTP_INTERNAL_SERVER_ERROR; 3613 return NGX_HTTP_INTERNAL_SERVER_ERROR;
3579 } 3614 }
3632 3667
3633 b->last_buf = 1; 3668 b->last_buf = 1;
3634 } 3669 }
3635 3670
3636 b->tag = (ngx_buf_tag_t) &ngx_http_v2_filter_request_body; 3671 b->tag = (ngx_buf_tag_t) &ngx_http_v2_filter_request_body;
3672 b->flush = r->request_body_no_buffering;
3673
3674 update:
3637 3675
3638 rc = ngx_http_top_request_body_filter(r, cl); 3676 rc = ngx_http_top_request_body_filter(r, cl);
3639 3677
3640 ngx_chain_update_chains(r->pool, &rb->free, &rb->busy, &cl, 3678 ngx_chain_update_chains(r->pool, &rb->free, &rb->busy, &cl,
3641 (ngx_buf_tag_t) &ngx_http_v2_filter_request_body); 3679 (ngx_buf_tag_t) &ngx_http_v2_filter_request_body);
3671 r->stream->skip_data = 1; 3709 r->stream->skip_data = 1;
3672 3710
3673 ngx_http_finalize_request(r, NGX_HTTP_CLIENT_CLOSED_REQUEST); 3711 ngx_http_finalize_request(r, NGX_HTTP_CLIENT_CLOSED_REQUEST);
3674 return; 3712 return;
3675 } 3713 }
3714 }
3715
3716
3717 ngx_int_t
3718 ngx_http_v2_read_unbuffered_request_body(ngx_http_request_t *r)
3719 {
3720 size_t window;
3721 ngx_buf_t *buf;
3722 ngx_int_t rc;
3723 ngx_connection_t *fc;
3724 ngx_http_v2_stream_t *stream;
3725 ngx_http_v2_connection_t *h2c;
3726 ngx_http_core_loc_conf_t *clcf;
3727
3728 stream = r->stream;
3729 fc = r->connection;
3730
3731 if (fc->read->timedout) {
3732 if (stream->recv_window) {
3733 stream->skip_data = 1;
3734 fc->timedout = 1;
3735
3736 return NGX_HTTP_REQUEST_TIME_OUT;
3737 }
3738
3739 fc->read->timedout = 0;
3740 }
3741
3742 if (fc->error) {
3743 stream->skip_data = 1;
3744 return NGX_HTTP_BAD_REQUEST;
3745 }
3746
3747 rc = ngx_http_v2_filter_request_body(r);
3748
3749 if (rc != NGX_OK) {
3750 stream->skip_data = 1;
3751 return rc;
3752 }
3753
3754 if (!r->request_body->rest) {
3755 return NGX_OK;
3756 }
3757
3758 if (r->request_body->busy != NULL) {
3759 return NGX_AGAIN;
3760 }
3761
3762 buf = r->request_body->buf;
3763
3764 buf->pos = buf->start;
3765 buf->last = buf->start;
3766
3767 window = buf->end - buf->start;
3768 h2c = stream->connection;
3769
3770 if (h2c->state.stream == stream) {
3771 window -= h2c->state.length;
3772 }
3773
3774 if (window == stream->recv_window) {
3775 return NGX_AGAIN;
3776 }
3777
3778 if (ngx_http_v2_send_window_update(h2c, stream->node->id,
3779 window - stream->recv_window)
3780 == NGX_ERROR)
3781 {
3782 stream->skip_data = 1;
3783 return NGX_HTTP_INTERNAL_SERVER_ERROR;
3784 }
3785
3786 if (ngx_http_v2_send_output_queue(h2c) == NGX_ERROR) {
3787 stream->skip_data = 1;
3788 return NGX_HTTP_INTERNAL_SERVER_ERROR;
3789 }
3790
3791 if (stream->recv_window == 0) {
3792 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
3793 ngx_add_timer(fc->read, clcf->client_body_timeout);
3794 }
3795
3796 stream->recv_window = window;
3797
3798 return NGX_AGAIN;
3676 } 3799 }
3677 3800
3678 3801
3679 static ngx_int_t 3802 static ngx_int_t
3680 ngx_http_v2_terminate_stream(ngx_http_v2_connection_t *h2c, 3803 ngx_http_v2_terminate_stream(ngx_http_v2_connection_t *h2c,