ngx_http_discard_request_body 函数分析

来源:互联网 发布:游族网络怎么样 编辑:程序博客网 时间:2024/06/11 21:44

        当一个模块想要主动的丢弃客户端发过的请求体body,可以调用nginx核心提供的ngx_http_discard_request_body()接口,主动丢弃的原因可能有很多种,如模块的业务逻辑压根不需要请求体 ,客户端发送的请求体是非法的等。下面开始分析ngx_http_discard_request_body()函数:

ngx_int_tngx_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;}




voidngx_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);    }}



原创粉丝点击