ngx_http_discard_request_body 함수 분석

4119 단어
모듈 이 클 라 이언 트 가 보 낸 요청 체 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);
    }
}

좋은 웹페이지 즐겨찾기