Nginx Request body read (ii)

Source: Internet
Author: User

2, discard the request body

A module wants to actively discard the client-sent request body, can call the Nginx core provided by the Ngx_http_discard_request_body () interface, the reasons for the active discard may be many, such as the module's business logic does not need the request body, The client sends an oversized request body, and in order to be compatible with the pipeline request of the http1.1 protocol, the module is obliged to voluntarily discard the unwanted request body. In order to maintain a good client compatibility, Nginx must actively discard the useless request body. The following begins the analysis of the Ngx_http_discard_request_body () function:

[CPP]View Plaincopy
  1. <span style="FONT-SIZE:18PX;" >ngx_int_t
  2. Ngx_http_discard_request_body (ngx_http_request_t *r)
  3. {
  4. ssize_t size;
  5. ngx_event_t *rev;
  6. if (r! = R->main | | r->discard_body) {
  7. return NGX_OK;
  8. }
  9. if (Ngx_http_test_expect (r)! = NGX_OK) {
  10. return ngx_http_internal_server_error;
  11. }
  12. Rev = r->connection->read;
  13. Ngx_log_debug0 (ngx_log_debug_http, Rev->log, 0, "HTTP set Discard Body");
  14. if (rev->timer_set) {
  15. Ngx_del_timer (rev.);
  16. }
  17. if (r->headers_in.content_length_n <= 0 | | r->request_body) {
  18. return NGX_OK;
  19. }
  20. Size = r->header_in->last-r->header_in->pos;
  21. if (size) {
  22. if (r->headers_in.content_length_n > size) {
  23. R->header_in->pos + = size;
  24. R->headers_in.content_length_n-= size;
  25. } Else {
  26. R->header_in->pos + = (size_t) r->headers_in.content_length_n;
  27. R->headers_in.content_length_n = 0;
  28. return NGX_OK;
  29. }
  30. }
  31. R->read_event_handler = Ngx_http_discarded_request_body_handler;
  32. if (ngx_handle_read_event (rev, 0)! = NGX_OK) {
  33. return ngx_http_internal_server_error;
  34. }
  35. if (ngx_http_read_discarded_request_body (r) = = NGX_OK) {
  36. R->lingering_close = 0;
  37. } Else {
  38. r->count++;
  39. R->discard_body = 1;
  40. }
  41. return NGX_OK;
  42. }
  43. </span>


Since the function is not long, here it is fully listed, the beginning of the function will also judge the situation does not need to do the processing: the child request does not need to process, has already called the function and does not need to be processed. Then call Ngx_http_test_expect () to handle the situation of http1.1 expect, according to the expect mechanism of http1.1, if the client sends a expect header, and the server does not want to receive the request body, must return 417 ( Expectation Failed) error. Nginx does not do this, it is simply to let the client send the request body, and then discarded. Next, the function deletes the timer on the read event, because at this time it does not need the request body, so it does not matter whether the client sends the fast or slow, of course, the back will also be to, when Nginx has finished processing the request but the client has not sent out the useless request body, Nginx will be on the reading event on the timer.

The function also checks the Content-length header in the request header, and if the client intends to send the request body, it must send the Content-length header and see if the request body has been read elsewhere. If the requested body is really pending, the function then checks the pre-read data in the request header buffer, and the pre-read data is discarded directly, although the function is returned directly if the request body has been fully pre-read.

Next, if there is still the remaining request body unhandled, the function calls Ngx_handle_read_event () to mount the read event in the event handling mechanism and set the handler function of the read event to Ngx_http_discarded_request_body_ Handler After these preparations are made, the function finally calls the Ngx_http_read_discarded_request_body () interface to read the client's request body and discard it. If the client does not send the request body at once, the function returns, and the remaining data waits for the next read event to be handed over to Ngx_http_discarded_request_body_handler () for processing, at which point the requested Discard_ Body will be set to 1 to identify this situation. Additionally, the number of references requested (count) is also incremented by 1, so that the client may not be able to send the requested body completely after Nginx finishes processing the request, increasing the reference to prevent the Nginx core from releasing the requested resource directly after processing the request.

The Ngx_http_read_discarded_request_body () function is very simple, it iterates through the link and discards the data until all the data in the receive buffer is read, and if the request body has already been read, the function sets the handler function for the Read event to Ngx_ Http_block_reading, this function only removes read events that are horizontally triggered, preventing the same event from being triggered.

Let's take a look at the processing function of the Read event Ngx_http_discarded_request_body_handler, which is called every time the event is read, first look at its source code:

[CPP]View Plaincopy
  1. <span style="FONT-SIZE:18PX;" >void
  2. Ngx_http_discarded_request_body_handler (ngx_http_request_t *r)
  3. {
  4. ...
  5. c = r->connection;
  6. Rev = c->read;
  7. if (rev->timedout) {
  8. C->timedout = 1;
  9. C->error = 1;
  10. Ngx_http_finalize_request (R, Ngx_error);
  11. return;
  12. }
  13. if (r->lingering_time) {
  14. Timer = (ngx_msec_t) (R->lingering_time-ngx_time ());
  15. if (timer <= 0) {
  16. r->discard_body = 0;
  17. R->lingering_close = 0;
  18. Ngx_http_finalize_request (R, Ngx_error);
  19. return;
  20. }
  21. } Else {
  22. Timer = 0;
  23. }
  24. rc = Ngx_http_read_discarded_request_body (r);
  25. if (rc = = NGX_OK) {
  26. r->discard_body = 0;
  27. R->lingering_close = 0;
  28. Ngx_http_finalize_request (R, Ngx_done);
  29. return;
  30. }
  31. / * rc = = Ngx_again * /
  32. if (ngx_handle_read_event (rev, 0)! = NGX_OK) {
  33. C->error = 1;
  34. Ngx_http_finalize_request (R, Ngx_error);
  35. return;
  36. }
  37. if (timer) {
  38. CLCF = ngx_http_get_module_loc_conf (R, Ngx_http_core_module);
  39. Timer *= 1000;
  40. if (Timer > clcf->lingering_timeout) {
  41. Timer = clcf->lingering_timeout;
  42. }
  43. Ngx_add_timer (rev, timer);
  44. }
  45. }
  46. </span>

The function begins by processing the Read event timeout, and when the timer is set when the Ngx_http_discard_request_body () function has already deleted the Read event. The answer is that the request has been processed by Nginx, but the request body has not been completely discarded (the client may not have sent it), and in the Ngx_http_finalize_connection () function, if the request body has not been discarded. Nginx will add a read event timer, which is specified by the lingering_timeout instruction, the default is 5 seconds, but this time only two read events between the time-out period, waiting for the total length of the request body is specified by the lingering_time instruction, the default is 30 seconds. In this case, the function returns and disconnects directly if a timeout event is detected. Similarly, it is also necessary to control the length of the entire discard request body not exceeding the Lingering_time set time, and if it exceeds the maximum length, it will also return and disconnect directly.

If the Read event occurs before the request is processed, the timeout event is not processed and the timer is not set, and the function simply calls Ngx_http_read_discarded_request_body () to read and discard the data.

Nginx Request body read (ii)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.