src/http/ngx_http_request_body.c - nginx source code

Functions defined

Source code


  1. /*
  2. * Copyright (C) Igor Sysoev
  3. * Copyright (C) Nginx, Inc.
  4. */


  5. #include <ngx_config.h>
  6. #include <ngx_core.h>
  7. #include <ngx_http.h>


  8. static void ngx_http_read_client_request_body_handler(ngx_http_request_t *r);
  9. static ngx_int_t ngx_http_do_read_client_request_body(ngx_http_request_t *r);
  10. static ngx_int_t ngx_http_copy_pipelined_header(ngx_http_request_t *r,
  11.     ngx_buf_t *buf);
  12. static ngx_int_t ngx_http_write_request_body(ngx_http_request_t *r);
  13. static ngx_int_t ngx_http_read_discarded_request_body(ngx_http_request_t *r);
  14. static ngx_int_t ngx_http_discard_request_body_filter(ngx_http_request_t *r,
  15.     ngx_buf_t *b);
  16. static ngx_int_t ngx_http_test_expect(ngx_http_request_t *r);

  17. static ngx_int_t ngx_http_request_body_filter(ngx_http_request_t *r,
  18.     ngx_chain_t *in);
  19. static ngx_int_t ngx_http_request_body_length_filter(ngx_http_request_t *r,
  20.     ngx_chain_t *in);
  21. static ngx_int_t ngx_http_request_body_chunked_filter(ngx_http_request_t *r,
  22.     ngx_chain_t *in);


  23. ngx_int_t
  24. ngx_http_read_client_request_body(ngx_http_request_t *r,
  25.     ngx_http_client_body_handler_pt post_handler)
  26. {
  27.     size_t                     preread;
  28.     ssize_t                    size;
  29.     ngx_int_t                  rc;
  30.     ngx_buf_t                 *b;
  31.     ngx_chain_t                out;
  32.     ngx_http_request_body_t   *rb;
  33.     ngx_http_core_loc_conf_t  *clcf;

  34.     r->main->count++;

  35.     if (r != r->main || r->request_body || r->discard_body) {
  36.         r->request_body_no_buffering = 0;
  37.         post_handler(r);
  38.         return NGX_OK;
  39.     }

  40.     if (ngx_http_test_expect(r) != NGX_OK) {
  41.         rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
  42.         goto done;
  43.     }

  44.     rb = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t));
  45.     if (rb == NULL) {
  46.         rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
  47.         goto done;
  48.     }

  49.     /*
  50.      * set by ngx_pcalloc():
  51.      *
  52.      *     rb->temp_file = NULL;
  53.      *     rb->bufs = NULL;
  54.      *     rb->buf = NULL;
  55.      *     rb->free = NULL;
  56.      *     rb->busy = NULL;
  57.      *     rb->chunked = NULL;
  58.      *     rb->received = 0;
  59.      *     rb->filter_need_buffering = 0;
  60.      *     rb->last_sent = 0;
  61.      *     rb->last_saved = 0;
  62.      */

  63.     rb->rest = -1;
  64.     rb->post_handler = post_handler;

  65.     r->request_body = rb;

  66.     if (r->headers_in.content_length_n < 0 && !r->headers_in.chunked) {
  67.         r->request_body_no_buffering = 0;
  68.         post_handler(r);
  69.         return NGX_OK;
  70.     }

  71. #if (NGX_HTTP_V2)
  72.     if (r->stream) {
  73.         rc = ngx_http_v2_read_request_body(r);
  74.         goto done;
  75.     }
  76. #endif

  77. #if (NGX_HTTP_V3)
  78.     if (r->http_version == NGX_HTTP_VERSION_30) {
  79.         rc = ngx_http_v3_read_request_body(r);
  80.         goto done;
  81.     }
  82. #endif

  83.     preread = r->header_in->last - r->header_in->pos;

  84.     if (preread) {

  85.         /* there is the pre-read part of the request body */

  86.         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  87.                        "http client request body preread %uz", preread);

  88.         out.buf = r->header_in;
  89.         out.next = NULL;

  90.         rc = ngx_http_request_body_filter(r, &out);

  91.         if (rc != NGX_OK) {
  92.             goto done;
  93.         }

  94.         r->request_length += preread - (r->header_in->last - r->header_in->pos);

  95.         if (!r->headers_in.chunked
  96.             && rb->rest > 0
  97.             && rb->rest <= (off_t) (r->header_in->end - r->header_in->last))
  98.         {
  99.             /* the whole request body may be placed in r->header_in */

  100.             b = ngx_calloc_buf(r->pool);
  101.             if (b == NULL) {
  102.                 rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
  103.                 goto done;
  104.             }

  105.             b->temporary = 1;
  106.             b->start = r->header_in->pos;
  107.             b->pos = r->header_in->pos;
  108.             b->last = r->header_in->last;
  109.             b->end = r->header_in->end;

  110.             rb->buf = b;

  111.             r->read_event_handler = ngx_http_read_client_request_body_handler;
  112.             r->write_event_handler = ngx_http_request_empty_handler;

  113.             rc = ngx_http_do_read_client_request_body(r);
  114.             goto done;
  115.         }

  116.     } else {
  117.         /* set rb->rest */

  118.         rc = ngx_http_request_body_filter(r, NULL);

  119.         if (rc != NGX_OK) {
  120.             goto done;
  121.         }
  122.     }

  123.     if (rb->rest == 0 && rb->last_saved) {
  124.         /* the whole request body was pre-read */
  125.         r->request_body_no_buffering = 0;
  126.         post_handler(r);
  127.         return NGX_OK;
  128.     }

  129.     if (rb->rest < 0) {
  130.         ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
  131.                       "negative request body rest");
  132.         rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
  133.         goto done;
  134.     }

  135.     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

  136.     size = clcf->client_body_buffer_size;
  137.     size += size >> 2;

  138.     /* TODO: honor r->request_body_in_single_buf */

  139.     if (!r->headers_in.chunked && rb->rest < size) {
  140.         size = (ssize_t) rb->rest;

  141.         if (r->request_body_in_single_buf) {
  142.             size += preread;
  143.         }

  144.         if (size == 0) {
  145.             size++;
  146.         }

  147.     } else {
  148.         size = clcf->client_body_buffer_size;
  149.     }

  150.     rb->buf = ngx_create_temp_buf(r->pool, size);
  151.     if (rb->buf == NULL) {
  152.         rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
  153.         goto done;
  154.     }

  155.     r->read_event_handler = ngx_http_read_client_request_body_handler;
  156.     r->write_event_handler = ngx_http_request_empty_handler;

  157.     rc = ngx_http_do_read_client_request_body(r);

  158. done:

  159.     if (r->request_body_no_buffering
  160.         && (rc == NGX_OK || rc == NGX_AGAIN))
  161.     {
  162.         if (rc == NGX_OK) {
  163.             r->request_body_no_buffering = 0;

  164.         } else {
  165.             /* rc == NGX_AGAIN */
  166.             r->reading_body = 1;
  167.         }

  168.         r->read_event_handler = ngx_http_block_reading;
  169.         post_handler(r);
  170.     }

  171.     if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
  172.         r->main->count--;
  173.     }

  174.     return rc;
  175. }


  176. ngx_int_t
  177. ngx_http_read_unbuffered_request_body(ngx_http_request_t *r)
  178. {
  179.     ngx_int_t  rc;

  180. #if (NGX_HTTP_V2)
  181.     if (r->stream) {
  182.         rc = ngx_http_v2_read_unbuffered_request_body(r);

  183.         if (rc == NGX_OK) {
  184.             r->reading_body = 0;
  185.         }

  186.         return rc;
  187.     }
  188. #endif

  189. #if (NGX_HTTP_V3)
  190.     if (r->http_version == NGX_HTTP_VERSION_30) {
  191.         rc = ngx_http_v3_read_unbuffered_request_body(r);

  192.         if (rc == NGX_OK) {
  193.             r->reading_body = 0;
  194.         }

  195.         return rc;
  196.     }
  197. #endif

  198.     if (r->connection->read->timedout) {
  199.         r->connection->timedout = 1;
  200.         return NGX_HTTP_REQUEST_TIME_OUT;
  201.     }

  202.     rc = ngx_http_do_read_client_request_body(r);

  203.     if (rc == NGX_OK) {
  204.         r->reading_body = 0;
  205.     }

  206.     return rc;
  207. }


  208. static void
  209. ngx_http_read_client_request_body_handler(ngx_http_request_t *r)
  210. {
  211.     ngx_int_t  rc;

  212.     if (r->connection->read->timedout) {
  213.         r->connection->timedout = 1;
  214.         ngx_http_finalize_request(r, NGX_HTTP_REQUEST_TIME_OUT);
  215.         return;
  216.     }

  217.     rc = ngx_http_do_read_client_request_body(r);

  218.     if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
  219.         ngx_http_finalize_request(r, rc);
  220.     }
  221. }


  222. static ngx_int_t
  223. ngx_http_do_read_client_request_body(ngx_http_request_t *r)
  224. {
  225.     off_t                      rest;
  226.     size_t                     size;
  227.     ssize_t                    n;
  228.     ngx_int_t                  rc;
  229.     ngx_uint_t                 flush;
  230.     ngx_chain_t                out;
  231.     ngx_connection_t          *c;
  232.     ngx_http_request_body_t   *rb;
  233.     ngx_http_core_loc_conf_t  *clcf;

  234.     c = r->connection;
  235.     rb = r->request_body;
  236.     flush = 1;

  237.     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
  238.                    "http read client request body");

  239.     for ( ;; ) {
  240.         for ( ;; ) {
  241.             if (rb->rest == 0) {
  242.                 break;
  243.             }

  244.             if (rb->buf->last == rb->buf->end) {

  245.                 /* update chains */

  246.                 rc = ngx_http_request_body_filter(r, NULL);

  247.                 if (rc != NGX_OK) {
  248.                     return rc;
  249.                 }

  250.                 if (rb->busy != NULL) {
  251.                     if (r->request_body_no_buffering) {
  252.                         if (c->read->timer_set) {
  253.                             ngx_del_timer(c->read);
  254.                         }

  255.                         if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
  256.                             return NGX_HTTP_INTERNAL_SERVER_ERROR;
  257.                         }

  258.                         return NGX_AGAIN;
  259.                     }

  260.                     if (rb->filter_need_buffering) {
  261.                         clcf = ngx_http_get_module_loc_conf(r,
  262.                                                          ngx_http_core_module);
  263.                         ngx_add_timer(c->read, clcf->client_body_timeout);

  264.                         if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
  265.                             return NGX_HTTP_INTERNAL_SERVER_ERROR;
  266.                         }

  267.                         return NGX_AGAIN;
  268.                     }

  269.                     ngx_log_error(NGX_LOG_ALERT, c->log, 0,
  270.                                   "busy buffers after request body flush");

  271.                     return NGX_HTTP_INTERNAL_SERVER_ERROR;
  272.                 }

  273.                 flush = 0;
  274.                 rb->buf->pos = rb->buf->start;
  275.                 rb->buf->last = rb->buf->start;
  276.             }

  277.             size = rb->buf->end - rb->buf->last;
  278.             rest = rb->rest - (rb->buf->last - rb->buf->pos);

  279.             if ((off_t) size > rest) {
  280.                 size = (size_t) rest;
  281.             }

  282.             if (size == 0) {
  283.                 break;
  284.             }

  285.             n = c->recv(c, rb->buf->last, size);

  286.             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
  287.                            "http client request body recv %z", n);

  288.             if (n == NGX_AGAIN) {
  289.                 break;
  290.             }

  291.             if (n == 0) {
  292.                 ngx_log_error(NGX_LOG_INFO, c->log, 0,
  293.                               "client prematurely closed connection");
  294.             }

  295.             if (n == 0 || n == NGX_ERROR) {
  296.                 c->error = 1;
  297.                 return NGX_HTTP_BAD_REQUEST;
  298.             }

  299.             rb->buf->last += n;
  300.             r->request_length += n;

  301.             /* pass buffer to request body filter chain */

  302.             flush = 0;
  303.             out.buf = rb->buf;
  304.             out.next = NULL;

  305.             rc = ngx_http_request_body_filter(r, &out);

  306.             if (rc != NGX_OK) {
  307.                 return rc;
  308.             }

  309.             if (rb->rest == 0) {
  310.                 break;
  311.             }

  312.             if (rb->buf->last < rb->buf->end) {
  313.                 break;
  314.             }
  315.         }

  316.         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
  317.                        "http client request body rest %O", rb->rest);

  318.         if (flush) {
  319.             rc = ngx_http_request_body_filter(r, NULL);

  320.             if (rc != NGX_OK) {
  321.                 return rc;
  322.             }
  323.         }

  324.         if (rb->rest == 0 && rb->last_saved) {
  325.             break;
  326.         }

  327.         if (!c->read->ready || rb->rest == 0) {

  328.             clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
  329.             ngx_add_timer(c->read, clcf->client_body_timeout);

  330.             if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
  331.                 return NGX_HTTP_INTERNAL_SERVER_ERROR;
  332.             }

  333.             return NGX_AGAIN;
  334.         }
  335.     }

  336.     if (ngx_http_copy_pipelined_header(r, rb->buf) != NGX_OK) {
  337.         return NGX_HTTP_INTERNAL_SERVER_ERROR;
  338.     }

  339.     if (c->read->timer_set) {
  340.         ngx_del_timer(c->read);
  341.     }

  342.     if (!r->request_body_no_buffering) {
  343.         r->read_event_handler = ngx_http_block_reading;
  344.         rb->post_handler(r);
  345.     }

  346.     return NGX_OK;
  347. }


  348. static ngx_int_t
  349. ngx_http_copy_pipelined_header(ngx_http_request_t *r, ngx_buf_t *buf)
  350. {
  351.     size_t                     n;
  352.     ngx_buf_t                 *b;
  353.     ngx_chain_t               *cl;
  354.     ngx_http_connection_t     *hc;
  355.     ngx_http_core_srv_conf_t  *cscf;

  356.     b = r->header_in;
  357.     n = buf->last - buf->pos;

  358.     if (buf == b || n == 0) {
  359.         return NGX_OK;
  360.     }

  361.     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  362.                    "http body pipelined header: %uz", n);

  363.     /*
  364.      * if there is a pipelined request in the client body buffer,
  365.      * copy it to the r->header_in buffer if there is enough room,
  366.      * or allocate a large client header buffer
  367.      */

  368.     if (n > (size_t) (b->end - b->last)) {

  369.         hc = r->http_connection;

  370.         if (hc->free) {
  371.             cl = hc->free;
  372.             hc->free = cl->next;

  373.             b = cl->buf;

  374.             ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  375.                            "http large header free: %p %uz",
  376.                            b->pos, b->end - b->last);

  377.         } else {
  378.             cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);

  379.             b = ngx_create_temp_buf(r->connection->pool,
  380.                                     cscf->large_client_header_buffers.size);
  381.             if (b == NULL) {
  382.                 return NGX_ERROR;
  383.             }

  384.             cl = ngx_alloc_chain_link(r->connection->pool);
  385.             if (cl == NULL) {
  386.                 return NGX_ERROR;
  387.             }

  388.             cl->buf = b;

  389.             ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  390.                            "http large header alloc: %p %uz",
  391.                            b->pos, b->end - b->last);
  392.         }

  393.         cl->next = hc->busy;
  394.         hc->busy = cl;
  395.         hc->nbusy++;

  396.         r->header_in = b;

  397.         if (n > (size_t) (b->end - b->last)) {
  398.             ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
  399.                           "too large pipelined header after reading body");
  400.             return NGX_ERROR;
  401.         }
  402.     }

  403.     ngx_memcpy(b->last, buf->pos, n);

  404.     b->last += n;
  405.     r->request_length -= n;

  406.     return NGX_OK;
  407. }


  408. static ngx_int_t
  409. ngx_http_write_request_body(ngx_http_request_t *r)
  410. {
  411.     ssize_t                    n;
  412.     ngx_chain_t               *cl, *ln;
  413.     ngx_temp_file_t           *tf;
  414.     ngx_http_request_body_t   *rb;
  415.     ngx_http_core_loc_conf_t  *clcf;

  416.     rb = r->request_body;

  417.     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  418.                    "http write client request body, bufs %p", rb->bufs);

  419.     if (rb->temp_file == NULL) {
  420.         tf = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t));
  421.         if (tf == NULL) {
  422.             return NGX_ERROR;
  423.         }

  424.         clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

  425.         tf->file.fd = NGX_INVALID_FILE;
  426.         tf->file.log = r->connection->log;
  427.         tf->path = clcf->client_body_temp_path;
  428.         tf->pool = r->pool;
  429.         tf->warn = "a client request body is buffered to a temporary file";
  430.         tf->log_level = r->request_body_file_log_level;
  431.         tf->persistent = r->request_body_in_persistent_file;
  432.         tf->clean = r->request_body_in_clean_file;

  433.         if (r->request_body_file_group_access) {
  434.             tf->access = 0660;
  435.         }

  436.         rb->temp_file = tf;

  437.         if (rb->bufs == NULL) {
  438.             /* empty body with r->request_body_in_file_only */

  439.             if (ngx_create_temp_file(&tf->file, tf->path, tf->pool,
  440.                                      tf->persistent, tf->clean, tf->access)
  441.                 != NGX_OK)
  442.             {
  443.                 return NGX_ERROR;
  444.             }

  445.             return NGX_OK;
  446.         }
  447.     }

  448.     if (rb->bufs == NULL) {
  449.         return NGX_OK;
  450.     }

  451.     n = ngx_write_chain_to_temp_file(rb->temp_file, rb->bufs);

  452.     /* TODO: n == 0 or not complete and level event */

  453.     if (n == NGX_ERROR) {
  454.         return NGX_ERROR;
  455.     }

  456.     rb->temp_file->offset += n;

  457.     /* mark all buffers as written */

  458.     for (cl = rb->bufs; cl; /* void */) {

  459.         cl->buf->pos = cl->buf->last;

  460.         ln = cl;
  461.         cl = cl->next;
  462.         ngx_free_chain(r->pool, ln);
  463.     }

  464.     rb->bufs = NULL;

  465.     return NGX_OK;
  466. }


  467. ngx_int_t
  468. ngx_http_discard_request_body(ngx_http_request_t *r)
  469. {
  470.     ssize_t       size;
  471.     ngx_int_t     rc;
  472.     ngx_event_t  *rev;

  473.     if (r != r->main || r->discard_body || r->request_body) {
  474.         return NGX_OK;
  475.     }

  476. #if (NGX_HTTP_V2)
  477.     if (r->stream) {
  478.         r->stream->skip_data = 1;
  479.         return NGX_OK;
  480.     }
  481. #endif

  482. #if (NGX_HTTP_V3)
  483.     if (r->http_version == NGX_HTTP_VERSION_30) {
  484.         return NGX_OK;
  485.     }
  486. #endif

  487.     if (ngx_http_test_expect(r) != NGX_OK) {
  488.         return NGX_HTTP_INTERNAL_SERVER_ERROR;
  489.     }

  490.     rev = r->connection->read;

  491.     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "http set discard body");

  492.     if (rev->timer_set) {
  493.         ngx_del_timer(rev);
  494.     }

  495.     if (r->headers_in.content_length_n <= 0 && !r->headers_in.chunked) {
  496.         return NGX_OK;
  497.     }

  498.     size = r->header_in->last - r->header_in->pos;

  499.     if (size || r->headers_in.chunked) {
  500.         rc = ngx_http_discard_request_body_filter(r, r->header_in);

  501.         if (rc != NGX_OK) {
  502.             return rc;
  503.         }

  504.         if (r->headers_in.content_length_n == 0) {
  505.             return NGX_OK;
  506.         }
  507.     }

  508.     rc = ngx_http_read_discarded_request_body(r);

  509.     if (rc == NGX_OK) {
  510.         r->lingering_close = 0;
  511.         return NGX_OK;
  512.     }

  513.     if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
  514.         return rc;
  515.     }

  516.     /* rc == NGX_AGAIN */

  517.     r->read_event_handler = ngx_http_discarded_request_body_handler;

  518.     if (ngx_handle_read_event(rev, 0) != NGX_OK) {
  519.         return NGX_HTTP_INTERNAL_SERVER_ERROR;
  520.     }

  521.     r->count++;
  522.     r->discard_body = 1;

  523.     return NGX_OK;
  524. }


  525. void
  526. ngx_http_discarded_request_body_handler(ngx_http_request_t *r)
  527. {
  528.     ngx_int_t                  rc;
  529.     ngx_msec_t                 timer;
  530.     ngx_event_t               *rev;
  531.     ngx_connection_t          *c;
  532.     ngx_http_core_loc_conf_t  *clcf;

  533.     c = r->connection;
  534.     rev = c->read;

  535.     if (rev->timedout) {
  536.         c->timedout = 1;
  537.         c->error = 1;
  538.         ngx_http_finalize_request(r, NGX_ERROR);
  539.         return;
  540.     }

  541.     if (r->lingering_time) {
  542.         timer = (ngx_msec_t) r->lingering_time - (ngx_msec_t) ngx_time();

  543.         if ((ngx_msec_int_t) timer <= 0) {
  544.             r->discard_body = 0;
  545.             r->lingering_close = 0;
  546.             ngx_http_finalize_request(r, NGX_ERROR);
  547.             return;
  548.         }

  549.     } else {
  550.         timer = 0;
  551.     }

  552.     rc = ngx_http_read_discarded_request_body(r);

  553.     if (rc == NGX_OK) {
  554.         r->discard_body = 0;
  555.         r->lingering_close = 0;
  556.         r->lingering_time = 0;
  557.         ngx_http_finalize_request(r, NGX_DONE);
  558.         return;
  559.     }

  560.     if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
  561.         c->error = 1;
  562.         ngx_http_finalize_request(r, NGX_ERROR);
  563.         return;
  564.     }

  565.     /* rc == NGX_AGAIN */

  566.     if (ngx_handle_read_event(rev, 0) != NGX_OK) {
  567.         c->error = 1;
  568.         ngx_http_finalize_request(r, NGX_ERROR);
  569.         return;
  570.     }

  571.     if (timer) {

  572.         clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

  573.         timer *= 1000;

  574.         if (timer > clcf->lingering_timeout) {
  575.             timer = clcf->lingering_timeout;
  576.         }

  577.         ngx_add_timer(rev, timer);
  578.     }
  579. }


  580. static ngx_int_t
  581. ngx_http_read_discarded_request_body(ngx_http_request_t *r)
  582. {
  583.     size_t     size;
  584.     ssize_t    n;
  585.     ngx_int_t  rc;
  586.     ngx_buf_t  b;
  587.     u_char     buffer[NGX_HTTP_DISCARD_BUFFER_SIZE];

  588.     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  589.                    "http read discarded body");

  590.     ngx_memzero(&b, sizeof(ngx_buf_t));

  591.     b.temporary = 1;

  592.     for ( ;; ) {
  593.         if (r->headers_in.content_length_n == 0) {
  594.             break;
  595.         }

  596.         if (!r->connection->read->ready) {
  597.             return NGX_AGAIN;
  598.         }

  599.         size = (size_t) ngx_min(r->headers_in.content_length_n,
  600.                                 NGX_HTTP_DISCARD_BUFFER_SIZE);

  601.         n = r->connection->recv(r->connection, buffer, size);

  602.         if (n == NGX_ERROR) {
  603.             r->connection->error = 1;
  604.             return NGX_OK;
  605.         }

  606.         if (n == NGX_AGAIN) {
  607.             return NGX_AGAIN;
  608.         }

  609.         if (n == 0) {
  610.             return NGX_OK;
  611.         }

  612.         b.pos = buffer;
  613.         b.last = buffer + n;

  614.         rc = ngx_http_discard_request_body_filter(r, &b);

  615.         if (rc != NGX_OK) {
  616.             return rc;
  617.         }
  618.     }

  619.     if (ngx_http_copy_pipelined_header(r, &b) != NGX_OK) {
  620.         return NGX_HTTP_INTERNAL_SERVER_ERROR;
  621.     }

  622.     r->read_event_handler = ngx_http_block_reading;

  623.     return NGX_OK;
  624. }


  625. static ngx_int_t
  626. ngx_http_discard_request_body_filter(ngx_http_request_t *r, ngx_buf_t *b)
  627. {
  628.     size_t                     size;
  629.     ngx_int_t                  rc;
  630.     ngx_http_request_body_t   *rb;
  631.     ngx_http_core_srv_conf_t  *cscf;

  632.     if (r->headers_in.chunked) {

  633.         rb = r->request_body;

  634.         if (rb == NULL) {

  635.             rb = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t));
  636.             if (rb == NULL) {
  637.                 return NGX_HTTP_INTERNAL_SERVER_ERROR;
  638.             }

  639.             rb->chunked = ngx_pcalloc(r->pool, sizeof(ngx_http_chunked_t));
  640.             if (rb->chunked == NULL) {
  641.                 return NGX_HTTP_INTERNAL_SERVER_ERROR;
  642.             }

  643.             r->request_body = rb;
  644.         }

  645.         for ( ;; ) {

  646.             rc = ngx_http_parse_chunked(r, b, rb->chunked, 0);

  647.             if (rc == NGX_OK) {

  648.                 /* a chunk has been parsed successfully */

  649.                 size = b->last - b->pos;

  650.                 if ((off_t) size > rb->chunked->size) {
  651.                     b->pos += (size_t) rb->chunked->size;
  652.                     rb->chunked->size = 0;

  653.                 } else {
  654.                     rb->chunked->size -= size;
  655.                     b->pos = b->last;
  656.                 }

  657.                 continue;
  658.             }

  659.             if (rc == NGX_DONE) {

  660.                 /* a whole response has been parsed successfully */

  661.                 r->headers_in.content_length_n = 0;
  662.                 break;
  663.             }

  664.             if (rc == NGX_AGAIN) {

  665.                 /* set amount of data we want to see next time */

  666.                 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);

  667.                 r->headers_in.content_length_n = ngx_max(rb->chunked->length,
  668.                                (off_t) cscf->large_client_header_buffers.size);
  669.                 break;
  670.             }

  671.             /* invalid */

  672.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  673.                           "client sent invalid chunked body");

  674.             return NGX_HTTP_BAD_REQUEST;
  675.         }

  676.     } else {
  677.         size = b->last - b->pos;

  678.         if ((off_t) size > r->headers_in.content_length_n) {
  679.             b->pos += (size_t) r->headers_in.content_length_n;
  680.             r->headers_in.content_length_n = 0;

  681.         } else {
  682.             b->pos = b->last;
  683.             r->headers_in.content_length_n -= size;
  684.         }
  685.     }

  686.     return NGX_OK;
  687. }


  688. static ngx_int_t
  689. ngx_http_test_expect(ngx_http_request_t *r)
  690. {
  691.     ngx_int_t   n;
  692.     ngx_str_t  *expect;

  693.     if (r->expect_tested
  694.         || r->headers_in.expect == NULL
  695.         || r->http_version < NGX_HTTP_VERSION_11
  696. #if (NGX_HTTP_V2)
  697.         || r->stream != NULL
  698. #endif
  699. #if (NGX_HTTP_V3)
  700.         || r->connection->quic != NULL
  701. #endif
  702.        )
  703.     {
  704.         return NGX_OK;
  705.     }

  706.     r->expect_tested = 1;

  707.     expect = &r->headers_in.expect->value;

  708.     if (expect->len != sizeof("100-continue") - 1
  709.         || ngx_strncasecmp(expect->data, (u_char *) "100-continue",
  710.                            sizeof("100-continue") - 1)
  711.            != 0)
  712.     {
  713.         return NGX_OK;
  714.     }

  715.     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  716.                    "send 100 Continue");

  717.     n = r->connection->send(r->connection,
  718.                             (u_char *) "HTTP/1.1 100 Continue" CRLF CRLF,
  719.                             sizeof("HTTP/1.1 100 Continue" CRLF CRLF) - 1);

  720.     if (n == sizeof("HTTP/1.1 100 Continue" CRLF CRLF) - 1) {
  721.         return NGX_OK;
  722.     }

  723.     /* we assume that such small packet should be send successfully */

  724.     r->connection->error = 1;

  725.     return NGX_ERROR;
  726. }


  727. static ngx_int_t
  728. ngx_http_request_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
  729. {
  730.     if (r->headers_in.chunked) {
  731.         return ngx_http_request_body_chunked_filter(r, in);

  732.     } else {
  733.         return ngx_http_request_body_length_filter(r, in);
  734.     }
  735. }


  736. static ngx_int_t
  737. ngx_http_request_body_length_filter(ngx_http_request_t *r, ngx_chain_t *in)
  738. {
  739.     size_t                     size;
  740.     ngx_int_t                  rc;
  741.     ngx_buf_t                 *b;
  742.     ngx_chain_t               *cl, *tl, *out, **ll;
  743.     ngx_http_request_body_t   *rb;

  744.     rb = r->request_body;

  745.     out = NULL;
  746.     ll = &out;

  747.     if (rb->rest == -1) {
  748.         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  749.                        "http request body content length filter");

  750.         rb->rest = r->headers_in.content_length_n;

  751.         if (rb->rest == 0) {

  752.             tl = ngx_chain_get_free_buf(r->pool, &rb->free);
  753.             if (tl == NULL) {
  754.                 return NGX_HTTP_INTERNAL_SERVER_ERROR;
  755.             }

  756.             b = tl->buf;

  757.             ngx_memzero(b, sizeof(ngx_buf_t));

  758.             b->last_buf = 1;

  759.             *ll = tl;
  760.             ll = &tl->next;
  761.         }
  762.     }

  763.     for (cl = in; cl; cl = cl->next) {

  764.         if (rb->rest == 0) {
  765.             break;
  766.         }

  767.         tl = ngx_chain_get_free_buf(r->pool, &rb->free);
  768.         if (tl == NULL) {
  769.             return NGX_HTTP_INTERNAL_SERVER_ERROR;
  770.         }

  771.         b = tl->buf;

  772.         ngx_memzero(b, sizeof(ngx_buf_t));

  773.         b->temporary = 1;
  774.         b->tag = (ngx_buf_tag_t) &ngx_http_read_client_request_body;
  775.         b->start = cl->buf->pos;
  776.         b->pos = cl->buf->pos;
  777.         b->last = cl->buf->last;
  778.         b->end = cl->buf->end;
  779.         b->flush = r->request_body_no_buffering;

  780.         size = cl->buf->last - cl->buf->pos;

  781.         if ((off_t) size < rb->rest) {
  782.             cl->buf->pos = cl->buf->last;
  783.             rb->rest -= size;

  784.         } else {
  785.             cl->buf->pos += (size_t) rb->rest;
  786.             rb->rest = 0;
  787.             b->last = cl->buf->pos;
  788.             b->last_buf = 1;
  789.         }

  790.         *ll = tl;
  791.         ll = &tl->next;
  792.     }

  793.     rc = ngx_http_top_request_body_filter(r, out);

  794.     ngx_chain_update_chains(r->pool, &rb->free, &rb->busy, &out,
  795.                             (ngx_buf_tag_t) &ngx_http_read_client_request_body);

  796.     return rc;
  797. }


  798. static ngx_int_t
  799. ngx_http_request_body_chunked_filter(ngx_http_request_t *r, ngx_chain_t *in)
  800. {
  801.     size_t                     size;
  802.     ngx_int_t                  rc;
  803.     ngx_buf_t                 *b;
  804.     ngx_chain_t               *cl, *out, *tl, **ll;
  805.     ngx_http_request_body_t   *rb;
  806.     ngx_http_core_loc_conf_t  *clcf;
  807.     ngx_http_core_srv_conf_t  *cscf;

  808.     rb = r->request_body;

  809.     out = NULL;
  810.     ll = &out;

  811.     if (rb->rest == -1) {

  812.         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  813.                        "http request body chunked filter");

  814.         rb->chunked = ngx_pcalloc(r->pool, sizeof(ngx_http_chunked_t));
  815.         if (rb->chunked == NULL) {
  816.             return NGX_HTTP_INTERNAL_SERVER_ERROR;
  817.         }

  818.         cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);

  819.         r->headers_in.content_length_n = 0;
  820.         rb->rest = cscf->large_client_header_buffers.size;
  821.     }

  822.     for (cl = in; cl; cl = cl->next) {

  823.         b = NULL;

  824.         for ( ;; ) {

  825.             ngx_log_debug7(NGX_LOG_DEBUG_EVENT, r->connection->log, 0,
  826.                            "http body chunked buf "
  827.                            "t:%d f:%d %p, pos %p, size: %z file: %O, size: %O",
  828.                            cl->buf->temporary, cl->buf->in_file,
  829.                            cl->buf->start, cl->buf->pos,
  830.                            cl->buf->last - cl->buf->pos,
  831.                            cl->buf->file_pos,
  832.                            cl->buf->file_last - cl->buf->file_pos);

  833.             rc = ngx_http_parse_chunked(r, cl->buf, rb->chunked, 0);

  834.             if (rc == NGX_OK) {

  835.                 /* a chunk has been parsed successfully */

  836.                 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

  837.                 if (clcf->client_max_body_size
  838.                     && clcf->client_max_body_size
  839.                        - r->headers_in.content_length_n < rb->chunked->size)
  840.                 {
  841.                     ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  842.                                   "client intended to send too large chunked "
  843.                                   "body: %O+%O bytes",
  844.                                   r->headers_in.content_length_n,
  845.                                   rb->chunked->size);

  846.                     r->lingering_close = 1;

  847.                     return NGX_HTTP_REQUEST_ENTITY_TOO_LARGE;
  848.                 }

  849.                 if (b
  850.                     && rb->chunked->size <= 128
  851.                     && cl->buf->last - cl->buf->pos >= rb->chunked->size)
  852.                 {
  853.                     r->headers_in.content_length_n += rb->chunked->size;

  854.                     if (rb->chunked->size < 8) {

  855.                         while (rb->chunked->size) {
  856.                             *b->last++ = *cl->buf->pos++;
  857.                             rb->chunked->size--;
  858.                         }

  859.                     } else {
  860.                         ngx_memmove(b->last, cl->buf->pos, rb->chunked->size);
  861.                         b->last += rb->chunked->size;
  862.                         cl->buf->pos += rb->chunked->size;
  863.                         rb->chunked->size = 0;
  864.                     }

  865.                     continue;
  866.                 }

  867.                 tl = ngx_chain_get_free_buf(r->pool, &rb->free);
  868.                 if (tl == NULL) {
  869.                     return NGX_HTTP_INTERNAL_SERVER_ERROR;
  870.                 }

  871.                 b = tl->buf;

  872.                 ngx_memzero(b, sizeof(ngx_buf_t));

  873.                 b->temporary = 1;
  874.                 b->tag = (ngx_buf_tag_t) &ngx_http_read_client_request_body;
  875.                 b->start = cl->buf->pos;
  876.                 b->pos = cl->buf->pos;
  877.                 b->last = cl->buf->last;
  878.                 b->end = cl->buf->end;
  879.                 b->flush = r->request_body_no_buffering;

  880.                 *ll = tl;
  881.                 ll = &tl->next;

  882.                 size = cl->buf->last - cl->buf->pos;

  883.                 if ((off_t) size > rb->chunked->size) {
  884.                     cl->buf->pos += (size_t) rb->chunked->size;
  885.                     r->headers_in.content_length_n += rb->chunked->size;
  886.                     rb->chunked->size = 0;

  887.                 } else {
  888.                     rb->chunked->size -= size;
  889.                     r->headers_in.content_length_n += size;
  890.                     cl->buf->pos = cl->buf->last;
  891.                 }

  892.                 b->last = cl->buf->pos;

  893.                 continue;
  894.             }

  895.             if (rc == NGX_DONE) {

  896.                 /* a whole response has been parsed successfully */

  897.                 rb->rest = 0;

  898.                 tl = ngx_chain_get_free_buf(r->pool, &rb->free);
  899.                 if (tl == NULL) {
  900.                     return NGX_HTTP_INTERNAL_SERVER_ERROR;
  901.                 }

  902.                 b = tl->buf;

  903.                 ngx_memzero(b, sizeof(ngx_buf_t));

  904.                 b->last_buf = 1;

  905.                 *ll = tl;
  906.                 ll = &tl->next;

  907.                 break;
  908.             }

  909.             if (rc == NGX_AGAIN) {

  910.                 /* set rb->rest, amount of data we want to see next time */

  911.                 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);

  912.                 rb->rest = ngx_max(rb->chunked->length,
  913.                                (off_t) cscf->large_client_header_buffers.size);

  914.                 break;
  915.             }

  916.             /* invalid */

  917.             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
  918.                           "client sent invalid chunked body");

  919.             return NGX_HTTP_BAD_REQUEST;
  920.         }
  921.     }

  922.     rc = ngx_http_top_request_body_filter(r, out);

  923.     ngx_chain_update_chains(r->pool, &rb->free, &rb->busy, &out,
  924.                             (ngx_buf_tag_t) &ngx_http_read_client_request_body);

  925.     return rc;
  926. }


  927. ngx_int_t
  928. ngx_http_request_body_save_filter(ngx_http_request_t *r, ngx_chain_t *in)
  929. {
  930.     ngx_buf_t                 *b;
  931.     ngx_chain_t               *cl, *tl, **ll;
  932.     ngx_http_request_body_t   *rb;

  933.     rb = r->request_body;

  934.     ll = &rb->bufs;

  935.     for (cl = rb->bufs; cl; cl = cl->next) {

  936. #if 0
  937.         ngx_log_debug7(NGX_LOG_DEBUG_EVENT, r->connection->log, 0,
  938.                        "http body old buf t:%d f:%d %p, pos %p, size: %z "
  939.                        "file: %O, size: %O",
  940.                        cl->buf->temporary, cl->buf->in_file,
  941.                        cl->buf->start, cl->buf->pos,
  942.                        cl->buf->last - cl->buf->pos,
  943.                        cl->buf->file_pos,
  944.                        cl->buf->file_last - cl->buf->file_pos);
  945. #endif

  946.         ll = &cl->next;
  947.     }

  948.     for (cl = in; cl; cl = cl->next) {

  949.         ngx_log_debug7(NGX_LOG_DEBUG_EVENT, r->connection->log, 0,
  950.                        "http body new buf t:%d f:%d %p, pos %p, size: %z "
  951.                        "file: %O, size: %O",
  952.                        cl->buf->temporary, cl->buf->in_file,
  953.                        cl->buf->start, cl->buf->pos,
  954.                        cl->buf->last - cl->buf->pos,
  955.                        cl->buf->file_pos,
  956.                        cl->buf->file_last - cl->buf->file_pos);

  957.         if (cl->buf->last_buf) {

  958.             if (rb->last_saved) {
  959.                 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
  960.                               "duplicate last buf in save filter");
  961.                 *ll = NULL;
  962.                 return NGX_HTTP_INTERNAL_SERVER_ERROR;
  963.             }

  964.             rb->last_saved = 1;
  965.         }

  966.         tl = ngx_alloc_chain_link(r->pool);
  967.         if (tl == NULL) {
  968.             *ll = NULL;
  969.             return NGX_HTTP_INTERNAL_SERVER_ERROR;
  970.         }

  971.         tl->buf = cl->buf;
  972.         *ll = tl;
  973.         ll = &tl->next;
  974.     }

  975.     *ll = NULL;

  976.     if (r->request_body_no_buffering) {
  977.         return NGX_OK;
  978.     }

  979.     if (rb->rest > 0) {

  980.         if (rb->bufs && rb->buf && rb->buf->last == rb->buf->end
  981.             && ngx_http_write_request_body(r) != NGX_OK)
  982.         {
  983.             return NGX_HTTP_INTERNAL_SERVER_ERROR;
  984.         }

  985.         return NGX_OK;
  986.     }

  987.     if (!rb->last_saved) {
  988.         return NGX_OK;
  989.     }

  990.     if (rb->temp_file || r->request_body_in_file_only) {

  991.         if (rb->bufs && rb->bufs->buf->in_file) {
  992.             ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
  993.                           "body already in file");
  994.             return NGX_HTTP_INTERNAL_SERVER_ERROR;
  995.         }

  996.         if (ngx_http_write_request_body(r) != NGX_OK) {
  997.             return NGX_HTTP_INTERNAL_SERVER_ERROR;
  998.         }

  999.         if (rb->temp_file->file.offset != 0) {

  1000.             cl = ngx_chain_get_free_buf(r->pool, &rb->free);
  1001.             if (cl == NULL) {
  1002.                 return NGX_HTTP_INTERNAL_SERVER_ERROR;
  1003.             }

  1004.             b = cl->buf;

  1005.             ngx_memzero(b, sizeof(ngx_buf_t));

  1006.             b->in_file = 1;
  1007.             b->file_last = rb->temp_file->file.offset;
  1008.             b->file = &rb->temp_file->file;

  1009.             rb->bufs = cl;
  1010.         }
  1011.     }

  1012.     return NGX_OK;
  1013. }