Mercurial > hg > nginx-quic
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, |