<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                一個模塊想要主動的丟棄客戶端發過的請求體,可以調用nginx核心提供的ngx_http_discard_request_body()接口,主動丟棄的原因可能有很多種,如模塊的業務邏輯壓根不需要請求體 ,客戶端發送了過大的請求體,另外為了兼容http1.1協議的pipeline請求,模塊有義務主動丟棄不需要的請求體。總之為了保持良好的客戶端兼容性,nginx必須主動丟棄無用的請求體。下面開始分析ngx_http_discard_request_body()函數: [](http:// "點擊提交Issue,反饋你的意見...") ngx_int_t ngx_http_discard_request_body(ngx_http_request_t *r) { ssize_t size; ngx_event_t *rev; if (r != r->main || r->discard_body) { return NGX_OK; } if (ngx_http_test_expect(r) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } rev = r->connection->read; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "http set discard body"); if (rev->timer_set) { ngx_del_timer(rev); } if (r->headers_in.content_length_n <= 0 || r->request_body) { return NGX_OK; } size = r->header_in->last - r->header_in->pos; if (size) { if (r->headers_in.content_length_n > size) { r->header_in->pos += size; r->headers_in.content_length_n -= size; } else { r->header_in->pos += (size_t) r->headers_in.content_length_n; r->headers_in.content_length_n = 0; return NGX_OK; } } r->read_event_handler = ngx_http_discarded_request_body_handler; if (ngx_handle_read_event(rev, 0) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (ngx_http_read_discarded_request_body(r) == NGX_OK) { r->lingering_close = 0; } else { r->count++; r->discard_body = 1; } return NGX_OK; } 由于函數不長,這里把它完整的列出來了,函數的開始同樣先判斷了不需要再做處理的情況:子請求不需要處理,已經調用過此函數的也不需要再處理。接著調用ngx_http_test_expect() 處理http1.1 expect的情況,根據http1.1的expect機制,如果客戶端發送了expect頭,而服務端不希望接收請求體時,必須返回417(Expectation Failed)錯誤。nginx并沒有這樣做,它只是簡單的讓客戶端把請求體發送過來,然后丟棄掉。接下來,函數刪掉了讀事件上的定時器,因為這時本身就不需要請求體,所以也無所謂客戶端發送的快還是慢了,當然后面還會講到,當nginx已經處理完該請求但客戶端還沒有發送完無用的請求體時,nginx會在讀事件上再掛上定時器。 客戶端如果打算發送請求體,就必須發送content-length頭,所以函數會檢查請求頭中的content-length頭,同時還會查看其他地方是不是已經讀取了請求體。如果確實有待處理的請求體,函數接著檢查請求頭buffer中預讀的數據,預讀的數據會直接被丟掉,當然如果請求體已經被全部預讀,函數就直接返回了。 接下來,如果還有剩余的請求體未處理,該函數調用ngx_handle_read_event()在事件處理機制中掛載好讀事件,并把讀事件的處理函數設置為ngx_http_discarded_request_body_handler。做好這些準備之后,該函數最后調用ngx_http_read_discarded_request_body()接口讀取客戶端過來的請求體并丟棄。如果客戶端并沒有一次將請求體發過來,函數會返回,剩余的數據等到下一次讀事件過來時,交給ngx_http_discarded_request_body_handler()來處理,這時,請求的discard_body將被設置為1用來標識這種情況。另外請求的引用數(count)也被加1,這樣做的目的是客戶端可能在nginx處理完請求之后仍未完整發送待發送的請求體,增加引用是防止nginx核心在處理完請求后直接釋放了請求的相關資源。 ngx_http_read_discarded_request_body()函數非常簡單,它循環的從鏈接中讀取數據并丟棄,直到讀完接收緩沖區的所有數據,如果請求體已經被讀完了,該函數會設置讀事件的處理函數為ngx_http_block_reading,這個函數僅僅刪除水平觸發的讀事件,防止同一事件不斷被觸發。 最后看一下讀事件的處理函數ngx_http_discarded_request_body_handler,這個函數每次讀事件來時會被調用,先看一下它的源碼: [](http:// "點擊提交Issue,反饋你的意見...") void ngx_http_discarded_request_body_handler(ngx_http_request_t *r) { ... c = r->connection; rev = c->read; if (rev->timedout) { c->timedout = 1; c->error = 1; ngx_http_finalize_request(r, NGX_ERROR); return; } if (r->lingering_time) { timer = (ngx_msec_t) (r->lingering_time - ngx_time()); if (timer <= 0) { r->discard_body = 0; r->lingering_close = 0; ngx_http_finalize_request(r, NGX_ERROR); return; } } else { timer = 0; } rc = ngx_http_read_discarded_request_body(r); if (rc == NGX_OK) { r->discard_body = 0; r->lingering_close = 0; ngx_http_finalize_request(r, NGX_DONE); return; } /* rc == NGX_AGAIN */ if (ngx_handle_read_event(rev, 0) != NGX_OK) { c->error = 1; ngx_http_finalize_request(r, NGX_ERROR); return; } if (timer) { clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); timer *= 1000; if (timer > clcf->lingering_timeout) { timer = clcf->lingering_timeout; } ngx_add_timer(rev, timer); } } 函數一開始就處理了讀事件超時的情況,之前說到在ngx_http_discard_request_body()函數中已經刪除了讀事件的定時器,那么什么時候會設置定時器呢?答案就是在nginx已經處理完該請求,但是又沒有完全將該請求的請求體丟棄的時候(客戶端可能還沒有發送過來),在ngx_http_finalize_connection()函數中,如果檢查到還有未丟棄的請求體時,nginx會添加一個讀事件定時器,它的時長為lingering_timeout指令所指定,默認為5秒,不過這個時間僅僅兩次讀事件之間的超時時間,等待請求體的總時長為lingering_time指令所指定,默認為30秒。這種情況中,該函數如果檢測到超時事件則直接返回并斷開連接。同樣,還需要控制整個丟棄請求體的時長不能超過lingering_time設置的時間,如果超過了最大時長,也會直接返回并斷開連接。 如果讀事件發生在請求處理完之前,則不用處理超時事件,也不用設置定時器,函數只是簡單的調用ngx_http_read_discarded_request_body()來讀取并丟棄數據。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看