Ticket #907: body3.patch

File body3.patch, 24.7 KB (added by Valentin V. Bartenev, 11 years ago)

That is because part of the patch was already committed. Anyway, here is an updated version.

  • src/http/ngx_http_request.h

    diff -r 5936b7ed9292 -r 08b903de944c src/http/ngx_http_request.h
    a b typedef struct {  
    284284    ngx_chain_t                      *bufs;
    285285    ngx_buf_t                        *buf;
    286286    off_t                             rest;
     287#if (NGX_HTTP_V2)
     288    off_t                             received;
     289#endif
    287290    ngx_chain_t                      *free;
    288291    ngx_chain_t                      *busy;
    289292    ngx_http_chunked_t               *chunked;
  • src/http/ngx_http_request_body.c

    diff -r 5936b7ed9292 -r 08b903de944c src/http/ngx_http_request_body.c
    a b ngx_http_read_client_request_body(ngx_ht  
    4040
    4141    r->main->count++;
    4242
     43    if (r != r->main || r->request_body || r->discard_body) {
     44        r->request_body_no_buffering = 0;
     45        post_handler(r);
     46        return NGX_OK;
     47    }
     48
    4349#if (NGX_HTTP_V2)
    44     if (r->stream && r == r->main) {
     50    if (r->stream) {
    4551        r->request_body_no_buffering = 0;
    4652        rc = ngx_http_v2_read_request_body(r, post_handler);
    4753        goto done;
    4854    }
    4955#endif
    5056
    51     if (r != r->main || r->request_body || r->discard_body) {
    52         r->request_body_no_buffering = 0;
    53         post_handler(r);
    54         return NGX_OK;
    55     }
    56 
    5757    if (ngx_http_test_expect(r) != NGX_OK) {
    5858        rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
    5959        goto done;
    … … ngx_http_discard_request_body(ngx_http_r  
    503503    ngx_int_t     rc;
    504504    ngx_event_t  *rev;
    505505
     506    if (r != r->main || r->discard_body || r->request_body) {
     507        return NGX_OK;
     508    }
     509
    506510#if (NGX_HTTP_V2)
    507     if (r->stream && r == r->main) {
    508         r->stream->skip_data = NGX_HTTP_V2_DATA_DISCARD;
     511    if (r->stream) {
     512        r->stream->skip_data = 1;
    509513        return NGX_OK;
    510514    }
    511515#endif
    512516
    513     if (r != r->main || r->discard_body || r->request_body) {
    514         return NGX_OK;
    515     }
    516 
    517517    if (ngx_http_test_expect(r) != NGX_OK) {
    518518        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    519519    }
  • src/http/v2/ngx_http_v2.c

    diff -r 5936b7ed9292 -r 08b903de944c src/http/v2/ngx_http_v2.c
    a b  
    5151#define NGX_HTTP_V2_MAX_WINDOW                   ((1U << 31) - 1)
    5252#define NGX_HTTP_V2_DEFAULT_WINDOW               65535
    5353
     54#define NGX_HTTP_V2_INITIAL_WINDOW               0
     55
    5456#define NGX_HTTP_V2_ROOT                         (void *) -1
    5557
    5658
    … … static ngx_int_t ngx_http_v2_cookie(ngx_  
    163165    ngx_http_v2_header_t *header);
    164166static ngx_int_t ngx_http_v2_construct_cookie_header(ngx_http_request_t *r);
    165167static void ngx_http_v2_run_request(ngx_http_request_t *r);
    166 static ngx_int_t ngx_http_v2_init_request_body(ngx_http_request_t *r);
     168static ngx_int_t ngx_http_v2_process_request_body(ngx_http_request_t *r,
     169    u_char *pos, size_t size, ngx_uint_t last);
     170static ngx_int_t ngx_http_v2_filter_request_body(ngx_http_request_t *r);
    167171static void ngx_http_v2_read_client_request_body_handler(ngx_http_request_t *r);
    168172
    169173static ngx_int_t ngx_http_v2_terminate_stream(ngx_http_v2_connection_t *h2c,
    … … ngx_http_v2_state_data(ngx_http_v2_conne  
    762766        if (h2c->state.length == 0) {
    763767            ngx_log_error(NGX_LOG_INFO, h2c->connection->log, 0,
    764768                          "client sent padded DATA frame "
    765                           "with incorrect length: %uz",
    766                           h2c->state.length);
     769                          "with incorrect length: 0");
    767770
    768771            return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_SIZE_ERROR);
    769772        }
    … … ngx_http_v2_state_data(ngx_http_v2_conne  
    845848
    846849    stream->recv_window -= h2c->state.length;
    847850
    848     if (stream->recv_window < NGX_HTTP_V2_MAX_WINDOW / 4) {
    849 
     851    if (stream->no_flow_control
     852        && stream->recv_window < NGX_HTTP_V2_MAX_WINDOW / 4)
     853    {
    850854        if (ngx_http_v2_send_window_update(h2c, node->id,
    851855                                           NGX_HTTP_V2_MAX_WINDOW
    852856                                           - stream->recv_window)
    … … ngx_http_v2_state_data(ngx_http_v2_conne  
    875879        return ngx_http_v2_state_skip_padded(h2c, pos, end);
    876880    }
    877881
     882    stream->in_closed = h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG;
     883
    878884    h2c->state.stream = stream;
    879885
    880886    return ngx_http_v2_state_read_data(h2c, pos, end);
    … … static u_char *  
    885891ngx_http_v2_state_read_data(ngx_http_v2_connection_t *h2c, u_char *pos,
    886892    u_char *end)
    887893{
    888     size_t                     size;
    889     ssize_t                    n;
    890     ngx_buf_t                 *buf;
    891     ngx_int_t                  rc;
    892     ngx_temp_file_t           *tf;
    893     ngx_connection_t          *fc;
    894     ngx_http_request_t        *r;
    895     ngx_http_v2_stream_t      *stream;
    896     ngx_http_request_body_t   *rb;
    897     ngx_http_core_loc_conf_t  *clcf;
     894    size_t                 size;
     895    ngx_int_t              rc;
     896    ngx_uint_t             last;
     897    ngx_http_v2_stream_t  *stream;
    898898
    899899    stream = h2c->state.stream;
    900900
    … … ngx_http_v2_state_read_data(ngx_http_v2_  
    903903    }
    904904
    905905    if (stream->skip_data) {
    906         stream->in_closed = h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG;
    907 
    908         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
    909                        "skipping http2 DATA frame, reason: %d",
    910                        stream->skip_data);
     906        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
     907                       "skipping http2 DATA frame");
    911908
    912909        return ngx_http_v2_state_skip_padded(h2c, pos, end);
    913910    }
    914911
    915912    size = end - pos;
    916913
    917     if (size > h2c->state.length) {
     914    if (size >= h2c->state.length) {
    918915        size = h2c->state.length;
    919     }
    920 
    921     r = stream->request;
    922 
    923     if (r->request_body == NULL
    924         && ngx_http_v2_init_request_body(r) != NGX_OK)
    925     {
    926         stream->skip_data = NGX_HTTP_V2_DATA_INTERNAL_ERROR;
    927         return ngx_http_v2_state_skip_padded(h2c, pos, end);
    928     }
    929 
    930     fc = r->connection;
    931     rb = r->request_body;
    932     tf = rb->temp_file;
    933     buf = rb->buf;
    934 
    935     if (size) {
    936         rb->rest += size;
    937 
    938         if (r->headers_in.content_length_n != -1
    939             && r->headers_in.content_length_n < rb->rest)
    940         {
    941             ngx_log_error(NGX_LOG_INFO, fc->log, 0,
    942                           "client intended to send body data "
    943                           "larger than declared");
    944 
    945             stream->skip_data = NGX_HTTP_V2_DATA_ERROR;
    946             goto error;
    947 
    948         } else {
    949             clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
    950 
    951             if (clcf->client_max_body_size
    952                 && clcf->client_max_body_size < rb->rest)
    953             {
    954                 ngx_log_error(NGX_LOG_ERR, fc->log, 0,
    955                               "client intended to send "
    956                               "too large chunked body: %O bytes", rb->rest);
    957 
    958                 stream->skip_data = NGX_HTTP_V2_DATA_ERROR;
    959                 goto error;
    960             }
    961         }
    962 
    963         h2c->state.length -= size;
    964 
    965         if (tf) {
    966             buf->start = pos;
    967             buf->pos = pos;
    968 
    969             pos += size;
    970 
    971             buf->end = pos;
    972             buf->last = pos;
    973 
    974             n = ngx_write_chain_to_temp_file(tf, rb->bufs);
    975 
    976             /* TODO: n == 0 or not complete and level event */
    977 
    978             if (n == NGX_ERROR) {
    979                 stream->skip_data = NGX_HTTP_V2_DATA_INTERNAL_ERROR;
    980                 goto error;
    981             }
    982 
    983             tf->offset += n;
    984 
    985         } else {
    986             buf->last = ngx_cpymem(buf->last, pos, size);
    987             pos += size;
    988         }
    989 
    990         r->request_length += size;
    991     }
     916        last = stream->in_closed;
     917
     918    } else {
     919        last = 0;
     920    }
     921
     922    rc = ngx_http_v2_process_request_body(stream->request, pos, size, last);
     923
     924    if (rc != NGX_OK) {
     925        stream->skip_data = 1;
     926        ngx_http_finalize_request(stream->request, rc);
     927    }
     928
     929    pos += size;
     930    h2c->state.length -= size;
    992931
    993932    if (h2c->state.length) {
    994         if (rb->post_handler) {
    995             clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
    996             ngx_add_timer(fc->read, clcf->client_body_timeout);
    997         }
    998 
    999933        return ngx_http_v2_state_save(h2c, pos, end,
    1000934                                      ngx_http_v2_state_read_data);
    1001935    }
    1002936
    1003     if (h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG) {
    1004         stream->in_closed = 1;
    1005 
    1006         if (r->headers_in.content_length_n < 0) {
    1007             r->headers_in.content_length_n = rb->rest;
    1008 
    1009         } else if (r->headers_in.content_length_n != rb->rest) {
    1010             ngx_log_error(NGX_LOG_INFO, fc->log, 0,
    1011                           "client prematurely closed stream: "
    1012                           "only %O out of %O bytes of request body received",
    1013                           rb->rest, r->headers_in.content_length_n);
    1014 
    1015             stream->skip_data = NGX_HTTP_V2_DATA_ERROR;
    1016             goto error;
    1017         }
    1018 
    1019         if (tf) {
    1020             ngx_memzero(buf, sizeof(ngx_buf_t));
    1021 
    1022             buf->in_file = 1;
    1023             buf->file_last = tf->file.offset;
    1024             buf->file = &tf->file;
    1025 
    1026             rb->buf = NULL;
    1027         }
    1028 
    1029         if (rb->post_handler) {
    1030             if (fc->read->timer_set) {
    1031                 ngx_del_timer(fc->read);
    1032             }
    1033 
    1034             r->read_event_handler = ngx_http_block_reading;
    1035             rb->post_handler(r);
    1036         }
    1037 
    1038     } else if (rb->post_handler) {
    1039         clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
    1040         ngx_add_timer(fc->read, clcf->client_body_timeout);
    1041     }
    1042 
    1043937    if (h2c->state.padding) {
    1044938        return ngx_http_v2_state_skip_padded(h2c, pos, end);
    1045939    }
    1046940
    1047941    return ngx_http_v2_state_complete(h2c, pos, end);
    1048 
    1049 error:
    1050 
    1051     if (rb->post_handler) {
    1052         if (fc->read->timer_set) {
    1053             ngx_del_timer(fc->read);
    1054         }
    1055 
    1056         if (stream->skip_data == NGX_HTTP_V2_DATA_ERROR) {
    1057             rc = (r->headers_in.content_length_n == -1)
    1058                  ? NGX_HTTP_REQUEST_ENTITY_TOO_LARGE : NGX_HTTP_BAD_REQUEST;
    1059 
    1060         } else {
    1061             rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
    1062         }
    1063 
    1064         ngx_http_finalize_request(r, rc);
    1065     }
    1066 
    1067     return ngx_http_v2_state_skip_padded(h2c, pos, end);
    1068942}
    1069943
    1070944
    … … ngx_http_v2_send_settings(ngx_http_v2_co  
    25562430        buf->last = ngx_http_v2_write_uint16(buf->last,
    25572431                                         NGX_HTTP_V2_INIT_WINDOW_SIZE_SETTING);
    25582432        buf->last = ngx_http_v2_write_uint32(buf->last,
    2559                                              NGX_HTTP_V2_MAX_WINDOW);
     2433                                             NGX_HTTP_V2_INITIAL_WINDOW);
    25602434
    25612435        buf->last = ngx_http_v2_write_uint16(buf->last,
    25622436                                           NGX_HTTP_V2_MAX_FRAME_SIZE_SETTING);
    … … ngx_http_v2_create_stream(ngx_http_v2_co  
    28782752    stream->connection = h2c;
    28792753
    28802754    stream->send_window = h2c->init_window;
    2881     stream->recv_window = NGX_HTTP_V2_MAX_WINDOW;
     2755    stream->recv_window = NGX_HTTP_V2_INITIAL_WINDOW;
    28822756
    28832757    h2c->processing++;
    28842758
    … … ngx_http_v2_run_request(ngx_http_request  
    35153389        ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
    35163390                      "client prematurely closed stream");
    35173391
    3518         r->stream->skip_data = NGX_HTTP_V2_DATA_ERROR;
     3392        r->stream->skip_data = 1;
    35193393
    35203394        ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
    35213395        return;
    … … ngx_http_v2_run_request(ngx_http_request  
    35253399}
    35263400
    35273401
    3528 static ngx_int_t
    3529 ngx_http_v2_init_request_body(ngx_http_request_t *r)
    3530 {
    3531     ngx_buf_t                 *buf;
    3532     ngx_temp_file_t           *tf;
    3533     ngx_http_request_body_t   *rb;
    3534     ngx_http_core_loc_conf_t  *clcf;
    3535 
    3536     rb = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t));
    3537     if (rb == NULL) {
    3538         return NGX_ERROR;
    3539     }
    3540 
    3541     r->request_body = rb;
    3542 
    3543     if (r->stream->in_closed) {
    3544         return NGX_OK;
    3545     }
    3546 
    3547     rb->rest = r->headers_in.content_length_n;
    3548 
    3549     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
    3550 
    3551     if (r->request_body_in_file_only
    3552         || rb->rest > (off_t) clcf->client_body_buffer_size
    3553         || rb->rest < 0)
    3554     {
    3555         tf = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t));
    3556         if (tf == NULL) {
    3557             return NGX_ERROR;
    3558         }
    3559 
    3560         tf->file.fd = NGX_INVALID_FILE;
    3561         tf->file.log = r->connection->log;
    3562         tf->path = clcf->client_body_temp_path;
    3563         tf->pool = r->pool;
    3564         tf->warn = "a client request body is buffered to a temporary file";
    3565         tf->log_level = r->request_body_file_log_level;
    3566         tf->persistent = r->request_body_in_persistent_file;
    3567         tf->clean = r->request_body_in_clean_file;
    3568 
    3569         if (r->request_body_file_group_access) {
    3570             tf->access = 0660;
    3571         }
    3572 
    3573         rb->temp_file = tf;
    3574 
    3575         if (r->stream->in_closed
    3576             && ngx_create_temp_file(&tf->file, tf->path, tf->pool,
    3577                                     tf->persistent, tf->clean, tf->access)
    3578                != NGX_OK)
    3579         {
    3580             return NGX_ERROR;
    3581         }
    3582 
    3583         buf = ngx_calloc_buf(r->pool);
    3584         if (buf == NULL) {
    3585             return NGX_ERROR;
    3586         }
    3587 
    3588     } else {
    3589 
    3590         if (rb->rest == 0) {
    3591             return NGX_OK;
    3592         }
    3593 
    3594         buf = ngx_create_temp_buf(r->pool, (size_t) rb->rest);
    3595         if (buf == NULL) {
    3596             return NGX_ERROR;
    3597         }
    3598     }
    3599 
    3600     rb->buf = buf;
    3601 
    3602     rb->bufs = ngx_alloc_chain_link(r->pool);
    3603     if (rb->bufs == NULL) {
    3604         return NGX_ERROR;
    3605     }
    3606 
    3607     rb->bufs->buf = buf;
    3608     rb->bufs->next = NULL;
    3609 
    3610     rb->rest = 0;
    3611 
    3612     return NGX_OK;
    3613 }
    3614 
    3615 
    36163402ngx_int_t
    36173403ngx_http_v2_read_request_body(ngx_http_request_t *r,
    36183404    ngx_http_client_body_handler_pt post_handler)
    36193405{
     3406    off_t                      len;
    36203407    ngx_http_v2_stream_t      *stream;
     3408    ngx_http_request_body_t   *rb;
    36213409    ngx_http_core_loc_conf_t  *clcf;
    36223410
    3623     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
    3624                    "http2 read request body");
    3625 
    36263411    stream = r->stream;
    36273412
    3628     switch (stream->skip_data) {
    3629 
    3630     case NGX_HTTP_V2_DATA_DISCARD:
     3413    if (stream->skip_data) {
     3414        r->request_body_no_buffering = 0;
    36313415        post_handler(r);
    36323416        return NGX_OK;
    3633 
    3634     case NGX_HTTP_V2_DATA_ERROR:
     3417    }
     3418
     3419    rb = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t));
     3420    if (rb == NULL) {
     3421        return NGX_HTTP_INTERNAL_SERVER_ERROR;
     3422    }
     3423
     3424    /*
     3425     * set by ngx_pcalloc():
     3426     *
     3427     *     rb->bufs = NULL;
     3428     *     rb->buf = NULL;
     3429     *     rb->received = 0;
     3430     *     rb->free = NULL;
     3431     *     rb->busy = NULL;
     3432     */
     3433
     3434    rb->rest = 1;
     3435    rb->post_handler = post_handler;
     3436
     3437    r->request_body = rb;
     3438
     3439    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
     3440
     3441    len = r->headers_in.content_length_n;
     3442
     3443    if (len >= 0 && len <= (off_t) clcf->client_body_buffer_size
     3444        && !r->request_body_in_file_only)
     3445    {
     3446        rb->buf = ngx_create_temp_buf(r->pool, (size_t) len);
     3447
     3448    } else {
     3449        rb->buf = ngx_calloc_buf(r->pool);
     3450
     3451        if (rb->buf != NULL) {
     3452            rb->buf->sync = 1;
     3453        }
     3454    }
     3455
     3456    if (rb->buf == NULL) {
     3457        return NGX_HTTP_INTERNAL_SERVER_ERROR;
     3458    }
     3459
     3460    if (stream->in_closed) {
     3461        return ngx_http_v2_process_request_body(r, NULL, 0, 1);
     3462    }
     3463
     3464    stream->no_flow_control = 1;
     3465
     3466    stream->recv_window = NGX_HTTP_V2_MAX_WINDOW;
     3467
     3468    if (ngx_http_v2_send_window_update(stream->connection, stream->node->id,
     3469                                       stream->recv_window)
     3470        == NGX_ERROR)
     3471    {
     3472        return NGX_HTTP_INTERNAL_SERVER_ERROR;
     3473    }
     3474
     3475    ngx_add_timer(r->connection->read, clcf->client_body_timeout);
     3476
     3477    r->read_event_handler = ngx_http_v2_read_client_request_body_handler;
     3478    r->write_event_handler = ngx_http_request_empty_handler;
     3479
     3480    return NGX_AGAIN;
     3481}
     3482
     3483
     3484static ngx_int_t
     3485ngx_http_v2_process_request_body(ngx_http_request_t *r, u_char *pos,
     3486    size_t size, ngx_uint_t last)
     3487{
     3488    ngx_buf_t                 *buf;
     3489    ngx_int_t                  rc;
     3490    ngx_connection_t          *fc;
     3491    ngx_http_request_body_t   *rb;
     3492    ngx_http_core_loc_conf_t  *clcf;
     3493
     3494    rb = r->request_body;
     3495
     3496    if (rb == NULL) {
     3497        return NGX_OK;
     3498    }
     3499
     3500    fc = r->connection;
     3501    buf = rb->buf;
     3502
     3503    if (size) {
     3504        if (buf->sync) {
     3505            buf->pos = buf->start = pos;
     3506            buf->last = buf->end = pos + size;
     3507
     3508        } else {
     3509            if (size > (size_t) (buf->end - buf->last)) {
     3510                ngx_log_error(NGX_LOG_INFO, fc->log, 0,
     3511                                "client intended to send body data "
     3512                                "larger than declared");
     3513
     3514                return NGX_HTTP_BAD_REQUEST;
     3515            }
     3516
     3517            buf->last = ngx_cpymem(buf->last, pos, size);
     3518        }
     3519    }
     3520
     3521    if (last) {
     3522        rb->rest = 0;
     3523
     3524        if (fc->read->timer_set) {
     3525            ngx_del_timer(fc->read);
     3526        }
     3527
     3528        rc = ngx_http_v2_filter_request_body(r);
     3529
     3530        if (rc != NGX_OK) {
     3531            return rc;
     3532        }
     3533
     3534        if (buf->sync) {
     3535            /* prevent reusing this buffer in the upstream module */
     3536            rb->buf = NULL;
     3537        }
     3538
    36353539        if (r->headers_in.content_length_n == -1) {
    3636             return NGX_HTTP_REQUEST_ENTITY_TOO_LARGE;
     3540            r->headers_in.content_length_n = rb->received;
     3541        }
     3542
     3543        r->read_event_handler = ngx_http_block_reading;
     3544        rb->post_handler(r);
     3545
     3546        return NGX_OK;
     3547    }
     3548
     3549    if (size == 0) {
     3550        return NGX_OK;
     3551    }
     3552
     3553    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
     3554    ngx_add_timer(fc->read, clcf->client_body_timeout);
     3555
     3556    if (buf->sync) {
     3557        return ngx_http_v2_filter_request_body(r);
     3558    }
     3559
     3560    return NGX_OK;
     3561}
     3562
     3563
     3564static ngx_int_t
     3565ngx_http_v2_filter_request_body(ngx_http_request_t *r)
     3566{
     3567    ngx_buf_t                 *b, *buf;
     3568    ngx_int_t                  rc;
     3569    ngx_chain_t               *cl;
     3570    ngx_http_request_body_t   *rb;
     3571    ngx_http_core_loc_conf_t  *clcf;
     3572
     3573    rb = r->request_body;
     3574    buf = rb->buf;
     3575
     3576    cl = ngx_chain_get_free_buf(r->pool, &rb->free);
     3577    if (cl == NULL) {
     3578        return NGX_HTTP_INTERNAL_SERVER_ERROR;
     3579    }
     3580
     3581    b = cl->buf;
     3582
     3583    ngx_memzero(b, sizeof(ngx_buf_t));
     3584
     3585    if (buf->pos != buf->last) {
     3586        r->request_length += buf->last - buf->pos;
     3587        rb->received += buf->last - buf->pos;
     3588
     3589        if (r->headers_in.content_length_n != -1) {
     3590            if (r->headers_in.content_length_n < rb->received) {
     3591                ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
     3592                              "client intended to send body data "
     3593                              "larger than declared");
     3594
     3595                return NGX_HTTP_BAD_REQUEST;
     3596            }
     3597
    36373598        } else {
     3599            clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
     3600
     3601            if (clcf->client_max_body_size
     3602                && clcf->client_max_body_size < rb->received)
     3603            {
     3604                ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
     3605                              "client intended to send too large chunked body: "
     3606                              "%O bytes", rb->received);
     3607
     3608                return NGX_HTTP_REQUEST_ENTITY_TOO_LARGE;
     3609            }
     3610        }
     3611
     3612        b->temporary = 1;
     3613        b->pos = buf->pos;
     3614        b->last = buf->last;
     3615        b->start = b->pos;
     3616        b->end = b->last;
     3617
     3618        buf->pos = buf->last;
     3619    }
     3620
     3621    if (!rb->rest) {
     3622        if (r->headers_in.content_length_n != -1
     3623            && r->headers_in.content_length_n != rb->received)
     3624        {
     3625            ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
     3626                          "client prematurely closed stream: "
     3627                          "only %O out of %O bytes of request body received",
     3628                          rb->received, r->headers_in.content_length_n);
     3629
    36383630            return NGX_HTTP_BAD_REQUEST;
    36393631        }
    36403632
    3641     case NGX_HTTP_V2_DATA_INTERNAL_ERROR:
    3642         return NGX_HTTP_INTERNAL_SERVER_ERROR;
    3643     }
    3644 
    3645     if (!r->request_body && ngx_http_v2_init_request_body(r) != NGX_OK) {
    3646         stream->skip_data = NGX_HTTP_V2_DATA_INTERNAL_ERROR;
    3647         return NGX_HTTP_INTERNAL_SERVER_ERROR;
    3648     }
    3649 
    3650     if (stream->in_closed) {
    3651         post_handler(r);
    3652         return NGX_OK;
    3653     }
    3654 
    3655     r->request_body->post_handler = post_handler;
    3656 
    3657     r->read_event_handler = ngx_http_v2_read_client_request_body_handler;
    3658     r->write_event_handler = ngx_http_request_empty_handler;
    3659 
    3660     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
    3661     ngx_add_timer(r->connection->read, clcf->client_body_timeout);
    3662 
    3663     return NGX_AGAIN;
     3633        b->last_buf = 1;
     3634    }
     3635
     3636    b->tag = (ngx_buf_tag_t) &ngx_http_v2_filter_request_body;
     3637    b->flush = r->request_body_no_buffering;
     3638
     3639    rc = ngx_http_top_request_body_filter(r, cl);
     3640
     3641    ngx_chain_update_chains(r->pool, &rb->free, &rb->busy, &cl,
     3642                            (ngx_buf_tag_t) &ngx_http_v2_filter_request_body);
     3643
     3644    return rc;
    36643645}
    36653646
    36663647
    … … ngx_http_v2_read_client_request_body_han  
    36783659        ngx_log_error(NGX_LOG_INFO, fc->log, NGX_ETIMEDOUT, "client timed out");
    36793660
    36803661        fc->timedout = 1;
    3681         r->stream->skip_data = NGX_HTTP_V2_DATA_DISCARD;
     3662        r->stream->skip_data = 1;
    36823663
    36833664        ngx_http_finalize_request(r, NGX_HTTP_REQUEST_TIME_OUT);
    36843665        return;
    … … ngx_http_v2_read_client_request_body_han  
    36883669        ngx_log_error(NGX_LOG_INFO, fc->log, 0,
    36893670                      "client prematurely closed stream");
    36903671
    3691         r->stream->skip_data = NGX_HTTP_V2_DATA_DISCARD;
     3672        r->stream->skip_data = 1;
    36923673
    36933674        ngx_http_finalize_request(r, NGX_HTTP_CLIENT_CLOSED_REQUEST);
    36943675        return;
    … … ngx_http_v2_terminate_stream(ngx_http_v2  
    37093690        return NGX_ERROR;
    37103691    }
    37113692
    3712     stream->out_closed = 1;
     3693    stream->rst_sent = 1;
    37133694
    37143695    fc = stream->request->connection;
    37153696    fc->error = 1;
    … … ngx_http_v2_close_stream(ngx_http_v2_str  
    37443725        return;
    37453726    }
    37463727
    3747     if (!stream->out_closed) {
    3748         if (ngx_http_v2_send_rst_stream(h2c, node->id,
    3749                                      fc->timedout ? NGX_HTTP_V2_PROTOCOL_ERROR
    3750                                                   : NGX_HTTP_V2_INTERNAL_ERROR)
    3751             != NGX_OK)
    3752         {
    3753             h2c->connection->error = 1;
     3728    if (!stream->rst_sent && !h2c->connection->error) {
     3729
     3730        if (!stream->out_closed) {
     3731            if (ngx_http_v2_send_rst_stream(h2c, node->id,
     3732                                      fc->timedout ? NGX_HTTP_V2_PROTOCOL_ERROR
     3733                                                   : NGX_HTTP_V2_INTERNAL_ERROR)
     3734                != NGX_OK)
     3735            {
     3736                h2c->connection->error = 1;
     3737            }
     3738
     3739        } else if (!stream->in_closed) {
     3740            if (ngx_http_v2_send_rst_stream(h2c, node->id, NGX_HTTP_V2_NO_ERROR)
     3741                != NGX_OK)
     3742            {
     3743                h2c->connection->error = 1;
     3744            }
    37543745        }
    37553746    }
    37563747
    … … ngx_http_v2_finalize_connection(ngx_http  
    39423933
    39433934    c = h2c->connection;
    39443935
    3945     if (h2c->state.stream) {
    3946         h2c->state.stream->out_closed = 1;
    3947         ngx_http_v2_close_stream(h2c->state.stream, NGX_HTTP_BAD_REQUEST);
    3948     }
    3949 
    39503936    h2c->blocked = 1;
    39513937
    39523938    if (!c->error && ngx_http_v2_send_goaway(h2c, status) != NGX_ERROR) {
    39533939        (void) ngx_http_v2_send_output_queue(h2c);
    39543940    }
    39553941
     3942    c->error = 1;
     3943
     3944    if (h2c->state.stream) {
     3945        ngx_http_v2_close_stream(h2c->state.stream, NGX_HTTP_BAD_REQUEST);
     3946    }
     3947
    39563948    if (!h2c->processing) {
    39573949        ngx_http_close_connection(c);
    39583950        return;
    39593951    }
    39603952
    3961     c->error = 1;
    39623953    c->read->handler = ngx_http_empty_handler;
    39633954    c->write->handler = ngx_http_empty_handler;
    39643955
  • src/http/v2/ngx_http_v2.h

    diff -r 5936b7ed9292 -r 08b903de944c src/http/v2/ngx_http_v2.h
    a b  
    2424#define NGX_HTTP_V2_MAX_FIELD                                                 \
    2525    (127 + (1 << (NGX_HTTP_V2_INT_OCTETS - 1) * 7) - 1)
    2626
    27 #define NGX_HTTP_V2_DATA_DISCARD         1
    28 #define NGX_HTTP_V2_DATA_ERROR           2
    29 #define NGX_HTTP_V2_DATA_INTERNAL_ERROR  3
    30 
    3127#define NGX_HTTP_V2_FRAME_HEADER_SIZE    9
    3228
    3329/* frame types */
    … … struct ngx_http_v2_stream_s {  
    194190    unsigned                         exhausted:1;
    195191    unsigned                         in_closed:1;
    196192    unsigned                         out_closed:1;
    197     unsigned                         skip_data:2;
     193    unsigned                         rst_sent:1;
     194    unsigned                         no_flow_control:1;
     195    unsigned                         skip_data:1;
    198196};
    199197
    200198