ngx_http_discard_request_body 函式分析
當一個模組想要主動的丟棄客戶端發過的請求體body,可以呼叫nginx核心提供的ngx_http_discard_request_body()介面,主動丟棄的原因可能有很多種,如模組的業務邏輯壓根不需要請求體 ,客戶端傳送的請求體是非法的等。下面開始分析ngx_http_discard_request_body()函式:
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;
}
//ngx_http_test_expect函式是處理http1.1 expect的情況,
//根據http1.1的expect機制,如果客戶端傳送了expect頭,
//而服務端不希望接收請求體時,必須返回417(Expectation Failed)錯誤。
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;
}
}
//資料還沒有讀取完畢,則掛載ngx_http_discarded_request_body_handler處理函式
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; //資料還沒有讀取完畢,置變數,read_event_handler會下次處理
}
return NGX_OK;
}
void
ngx_http_discarded_request_body_handler(ngx_http_request_t *r)
{
ngx_int_t rc;
ngx_msec_t timer;
ngx_event_t *rev;
ngx_connection_t *c;
ngx_http_core_loc_conf_t *clcf;
c = r->connection;
rev = c->read;
//檢測是否超時,超時則直接斷開連線
if (rev->timedout) {
c->timedout = 1;
c->error = 1;
ngx_http_finalize_request(r, NGX_ERROR);
return;
}
//在ngx_http_finalize_connection()函式中,如果檢查到還有未丟棄的請求體時,
//nginx會新增一個讀事件定時器,它的時長為lingering_timeout指令所指定,
//預設為5秒,不過這個時間僅僅兩次讀事件之間的超時時間,
//等待請求體的總時長為lingering_time指令所指定,預設為30秒。
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);
}
}
相關文章
- Oracle分析函式七——分析函式案例Oracle函式
- Oracle聚合函式/分析函式Oracle函式
- 分析函式函式
- 【分析函式】Oracle分析函式之LAG和LEAD函式Oracle
- 分析函式概述函式
- 分析函式 over函式
- Oracle 分析函式Oracle函式
- 分析函式 - LAG函式
- Oracle分析函式Oracle函式
- Oracle分析函式與視窗函式Oracle函式
- 【Analytic】分析函式之MIN函式函式
- 【Analytic】分析函式之MAX函式函式
- 【Analytic】分析函式之AVG函式函式
- 【Analytic】分析函式之RANK函式函式
- 【Analytic】分析函式之COUNT函式函式
- oracle 10g函式大全--分析函式Oracle 10g函式
- sql優化用group by 函式代替分析函式SQL優化函式
- Hive之分析函式Hive函式
- 分析函式——NTILE(n)函式
- 分析函式——統計函式
- oracle 分析函式(轉)Oracle函式
- oracle分析函式(一)Oracle函式
- Oracle常用分析函式Oracle函式
- Oracle分析函式{轉}Oracle函式
- 多維分析函式函式
- Oracle分析函式-6Oracle函式
- Oracle分析函式-5Oracle函式
- Oracle分析函式-4Oracle函式
- Oracle分析函式-2Oracle函式
- Oracle分析函式-1Oracle函式
- Oracle分析函式-3Oracle函式
- oracle的分析函式over 及開窗函式Oracle函式
- 【Analytic】分析函式之ROW_NUMBER函式函式
- 【Analytic】分析函式之DENSE_RANK函式函式
- 【Analytic】分析函式之FIRST_VALUE函式函式
- 【Analytic】分析函式之LAST_VALUE函式函式AST
- mysql 自定義分析函式 least 及 日期函式MySql函式AST
- ORACLE函式介紹第六篇 著名函式之分析函式Oracle函式