2014-05-15 5 views
1

Nginx는 정말 흥미로운 소프트웨어이지만, 문서가 부족해서 저를 미쳤습니다.nginx 모듈 : 전체 응답 본문을 캡처하십시오.

목표 : 전체 응답 본문을 캡처하여 서버에 기록합니다.

문제점 : 나는 항상 크기가 0 인 단일 버퍼를 가지고 있습니다.

접근

나는 전체 버퍼 체인을 반복하기 전에 last_buf은 "대기"것 body filter이 요구 사항을 달성 할 수 있기를 기대

.

/** 
* @param ngx_http_request_t  *r  HTTP request 
* @param ngx_chain_t   *in Buffer chain 
*/ 
static ngx_int_t 
create_response_snapshot(ngx_http_request_t *r, ngx_chain_t *in) 
{ 
    ngx_chain_t *chain = NULL; 
    int chain_contains_last_buffer = 0; 
    size_t buffer_size = 0; 

    // check if body is complete 
    chain = in; 
    for (; ;) 
    { 
     if (chain->buf->last_buf) 
     { 
      chain_contains_last_buffer = 1; 
     } 

     if (NULL == chain->next) 
      break; 

     chain = chain->next; 
    } 

    if (0 == chain_contains_last_buffer) 
    { 
     // response is not complete 
     return ngx_http_next_body_filter(r, in); 
    } 

    // Response Content-Length 
    ngx_log_error(NGX_LOG_ALERT,r->connection->log,0,"Content-Length: %d", 
        r->headers_out.content_length_n); 

    // lets iterate buffers chain 
    for (chain = in; NULL != chain; chain = chain->next) 
    { 
     buffer_size = ngx_buf_size(chain->buf); 
     ngx_log_error(NGX_LOG_ALERT,r->connection->log,0,"buffer_size#%d",buffer_size); 
    } 

    return ngx_http_next_body_filter(r, in); 
} 
+0

설명서가 부족해서 나를 미치게 만들었습니다. 내가 찾은 유일한 가이드 (Evan Miller 's)는 대부분의'ngx_but_t' 멤버들의 목적을 설명하기 시작하지 않습니다. 이 경우 마지막 버프를 얻을 때까지 모듈 컨텍스트의 'busy'멤버에'in' 체인을 계속 추가해야한다고 생각합니다. 왜냐하면 필터가 여러 번 호출되기 때문이며 'last_buf'를 포함하는 필터가 최종 호출이므로 항상 본 것과 분리됩니다. – GVH

+0

아, 그러면 최종 체인을 얻지 못했다면'ngx_http_next_body_filter'를 호출하는 대신'NGX_OK'를 반환 할 것입니다. 그런 다음 체인 전체를 한 번에 나머지 필터로 전달하십시오. 기본적으로 Nginx의 출력을 청크로 처리하는 기능을 제거하고 있습니다. – GVH

+0

@GVH "이 경우 마지막 버프를 얻을 때까지 in chain을 모듈 컨텍스트의 바쁜 멤버에 계속 추가해야한다고 생각합니다." "바쁜 회원"에 대해 설명해 주시겠습니까? 나는 그것이 무엇이되어야하는지에 관해 모른다. Evan Miler의 튜토리얼에 따르면 "NGX_OK"를 반환하는 경우 각 필터는 다음 필터를 호출합니다. 다른 모듈을 깊이 파헤칩니다. – PauloASilva

답변

2

내 의견은 코멘트 수 너무 커서 가지고 있지만, 그것이 적절한 대답 같은 느낌하지 않습니다 - 잘 오.

반복 할 때 게시 한 코드의 문제점은 모듈의 바디 필터 기능이 전체 체인에서 동시에 호출되지 않는다는 것입니다. nth 조각까지 첫 번째 조각, 두 번째 조각에서 호출됩니다. 마지막으로 last_buf = 1을 가진 buf가 그 자체로 항상 비어있는 이유는 무엇이든 완전히 빈 체인에서 호출됩니다.

그래서 여러분이하고 싶은 것은 여러분이 한꺼번에 모든 것을 갖출 때까지 다음 필터를 릴리즈하지 않고 모듈에 버퍼를 축적함으로써 버퍼의 흐름을 "댐 (dam)"이라고 생각합니다. 대체 필터 모듈 밖으로

확인 : http://lxr.nginx.org/source//src/http/modules/ngx_http_sub_filter_module.c

그것은 내가 언급 한 것입니다 "중"체인을 사용합니다. 무엇을 말할 수 있었는지, 실제로 어떤 버퍼가 보내 졌는지 추적하는데 사용합니다 (크기가 0이 될 때). 그리고이를 모듈 컨텍스트의 자유 목록에 추가하여 재사용 할 수 있습니다. 이 문제는 438 행의 ngx_http_sub_output을 참조하십시오.

내 제안은 전체 페이지가있을 때까지 다음 필터를 호출하지 않는 경우를 제외하고는 해당 모듈이하는 것과 같은 기능을 수행하는 것이 었습니다. 전체 페이지를 전체적으로 처리하려면 next_filter를 호출 할 수 없습니다.이 작업을 수행하면 데이터가 클라이언트로 전송됩니다. 다시 이것은 Nginx의 디자인에 맞지 않습니다. 그래서 가능한 경우 전체 응답 본문을 필요로하지 않는 대안을 찾아야한다고 생각합니다.

관련 문제