nginx 에서 handler 처리 (2)

12801 단어 서버 설계
이번 에는 각 phase 의 checker 처 리 를 살 펴 보 겠 습 니 다.
우선 우리 가 알 아야 할 것 은 nginx 에서 일반적으로 NGXHTTP_CONTENT_PHASE 에서 outputfilter 를 호출 합 니 다. 즉, filter 는 handler 에서 호출 되 었 습 니 다. 이렇게 보면 하나의 handler 만 outputfiler 를 실행 할 수 있 습 니 다. 그 러 니까 nginx 의 handler 모듈 을 쓰 려 면 서로 다른 phase 의 반환 값 이 다른 뜻 을 나타 내 는 지 주의해 야 합 니 다.
대신 ngxhttp_core_run_phases 가 돌 아 왔 습 니 다. 즉, 어떤 phase 의 checker 가 NGX 로 돌 아 왔 습 니 다.OK 라면 현재 요청 이 끝 났 음 을 의미 합 니 다.
순서대로.
우선 ngxhttp_core_generic_phase, 그 는 주로 아래 의 phase 를 처리한다.
[quote]post read, server rewrite, rewrite, and pre-access phases[/quote]
이러한 phase 의 의 미 는 소개 하지 않 겠 습 니 다. 앞의 블 로 그 는 이미 상세 하 게 설명 하 였 습 니 다.
이 몇 개의 phase checker 에서 실행 할 handler 의 반환 값 을 4 가지 유형 으로 나 눕 니 다.
1 NGX_OK 이때 NGX 로 돌아 가기AGAIN, 여기 서 우 리 는 checker 가 ok 으로 돌아 가면 전체 handler 의 처리 가 바로 돌아 온 다 는 것 을 알 고 있 습 니 다. 즉, 이번 처리 가 끝 난 것 입 니 다.그리고 여기 phasehandler 는 ph - > next, 즉 다음 phase 의 색인 으로 할당 되 었 습 니 다.그 러 니까 다음 에 다음 phase checker 를 호출 하 겠 습 니 다.
2 NGX_DECLINED 이때 도 NGX 로 돌아 가기AGAIN, 이것 은 위 와 다 릅 니 다. 바로 phase 입 니 다.handler 의 할당 입 니 다. 여기 서 이 값 은 간단 한 + 일 뿐 입 니 다. 즉, 현재 phase 의 다음 phase 를 처리 할 것 입 니 다. 현재 phase 의 handelr 가 처리 되 어야 다음 phase 의 handler 를 처리 할 수 있 습 니 다.
3 NGX_AGAIN 혹은 NGXDONE, 이 건 바로 OK 로 돌아 갑 니 다. 즉, handler 의 처 리 를 끝 냅 니 다.
4 남 은 경우, 주로 NGX 처리ERROR, 그리고 NGXHTTP_(즉 http 의 상태 코드 를 되 돌려 주 는 것) 의 처리 입 니 다.

ngx_int_t
ngx_http_core_generic_phase(ngx_http_request_t *r, ngx_http_phase_handler_t *ph)
{
ngx_int_t rc;

// handler
rc = ph->handler(r);

// NGX_OK
if (rc == NGX_OK) {
// phase
r->phase_handler = ph->next;
return NGX_AGAIN;
}

// NGX_DECLINED
if (rc == NGX_DECLINED) {
// phase handler
r->phase_handler++;
return NGX_AGAIN;
}
// OK
if (rc == NGX_AGAIN || rc == NGX_DONE) {
return NGX_OK;
}

/* rc == NGX_ERROR || rc == NGX_HTTP_... */
// 。
ngx_http_finalize_request(r, rc);

return NGX_OK;
}

여기 서 우 리 는 ngx 가 있 는 것 을 발견 할 수 있 습 니 다.http_finalize_request 함수, 말 그대로 이 함 수 는 request 를 방출 하 는 데 사 용 됩 니 다. 예 를 들 어 request 와 관련 된 메모리 풀, 예 를 들 어 되 돌아 가 야 할 상태 코드, 예 를 들 어 연결 을 끊 어야 하 는 등 조작 입 니 다. 이 함 수 는 뒤에 있 는 nginx 에서 request (handler 와 filter 포함) 를 닫 을 때 상세 하 게 분석 합 니 다.
이어서 NGXHTTP_FIND_CONFIG_PHASE 라 는 phase checker.
이 phase 에 대응 하 는 checker 는 ngx 입 니 다.http_core_find_config_phase.
nginx 에서 location 의 처 리 는 매우 복잡 한 과정 이기 때문에 여기 서 우 리 는 주로 phase 의 처 리 를 보 았 기 때문에 location 이라는 phase 의 처 리 를 소개 하고 그 다음 에 더욱 상세 한 분석 location 이 있 을 것 이다.
이 checker 의 주요 역할 은 url 과 대응 하 는 location 을 연결 하 는 것 입 니 다. 사실은 대응 하 는 location 명령 과 관련 된 것 입 니 다. nginx 여기 location 의 실현 은 하나의 tree 로 이 루어 진 것 입 니 다. 여 기 는 location 의 실현 을 상세 하 게 분석 하지 않 습 니 다.주로 이 phase 의 처 리 를 보 겠 습 니 다.
이 checker 는 여러 번 호출 될 수 있 습 니 다.url 의 변화 마다 대응 하 는 location 이 바 뀌 기 때문에 전편 에서 우 리 는 전문 적 으로 find 가 있 는 것 을 볼 수 있 습 니 다.config_index 의 색인 은 다른 phase 호출 을 제공 합 니 다.
이 phase 에 주의 하 세 요. handler 가 하나 밖 에 없어 요. 바로 ngx 입 니 다.http_core_find_location, checker 에서 이 handler 를 호출 하여 해당 하 는 location 를 마 운 트 합 니 다.
그리고 find 를 통 해location 의 반환 값 은 서로 다른 조작 을 합 니 다. 예 를 들 어 error 로 돌아 갈 때 ngx 를 호출 해 야 합 니 다.http_finalize_요청 을 회수 합 니 다.
ngx_int_t
ngx_http_core_find_config_phase(ngx_http_request_t *r,
ngx_http_phase_handler_t *ph)
{
u_char *p;
size_t len;
ngx_int_t rc;
ngx_http_core_loc_conf_t *clcf;

r->content_handler = NULL;
r->uri_changed = 0;
//find location
rc = ngx_http_core_find_location(r);

if (rc == NGX_ERROR) {
// request, OK, handler 。
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
return NGX_OK;
}

clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

// internal, location , error 。
if (!r->internal && clcf->internal) {
ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND);
return NGX_OK;
}
.....................................................
}

다음은 NGXHTTP_POST_REWRITE_PHASE 이 phase 의 checker, ngxhttp_core_post_rewrite_phase。
이 rewrite phase 는 주로 rewrite 의 최대 횟수, 이 횟수 보다 크 면 finalize request 를 직접 검사 하 는 데 사 용 됩 니 다.
여기에 몇 가지 변수 가 있 습 니 다.
uri_changed: 현재 uri 가 바 뀌 었 는 지, 즉 방향 이 바 뀌 었 는 지 여부 입 니 다.
uri_changes: 이 초기 값 은 11 입 니 다. 가장 많은 rewrite 횟수 는 10 회 라 는 뜻 입 니 다.

ngx_int_t
ngx_http_core_post_rewrite_phase(ngx_http_request_t *r,
ngx_http_phase_handler_t *ph)
{
ngx_http_core_srv_conf_t *cscf;

ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"post rewrite phase: %ui", r->phase_handler);
// rewrite , again, handler 。
if (!r->uri_changed) {
r->phase_handler++;
return NGX_AGAIN;
}

ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"uri changes: %d", r->uri_changes);
//changes 。
r->uri_changes--;

// 0, rewrite , finalize request
if (r->uri_changes == 0) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"rewrite or internal redirection cycle "
"while processing \"%V\"", &r->uri);

ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
return NGX_OK;
}
// phase , use_rewrite, phase NGX_HTTP_FIND_CONFIG_PHASE。

r->phase_handler = ph->next;

cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
// loc conf
r->loc_conf = cscf->ctx->loc_conf;
// again, handler 。
return NGX_AGAIN;
}

그리고 NGXHTTP_ACCESS_PHASE 이 phase 의 checker, ngxhttp_core_access_phase。
이 chekcer 의 주요 논리 도 비교적 간단 하 다. 바로 handler 의 반환 값 을 통 해 서로 다른 조작 을 하 는 것 이다.그러나 여기 서 그녀 는 자신 이 특별히 처리 한 부분 이 있 습 니 다. 먼저 관련 된 두 도 메 인 을 살 펴 보 겠 습 니 다.
1 satisfy 이 도 메 인 은 명령 satisfy 에 대응 합 니 다.any (이것 은 이미 deprecated) 와 satisfy (이것 을 사용 하 는 것 을 권장 합 니 다).그 중 기본 값 은 NGX 입 니 다.HTTP_SATISFY_ALL. 이 명령 은 값 이 all 이면 모든 검증 을 만족 시 켜 야 하고 any 이면 하나만 만족 하면 통과 할 수 있다 는 뜻 이다.
2 access_code 이것 은 주로 다음 phase, post 에 전 달 됩 니 다.access phase 에서 처 리 했 습 니 다.
그리고 그것 의 반환 값 을 보 세 요.
1 NGX_DECLINED 는 일부 이유 로 access 가 진행 되 지 않 았 다 고 밝 혔 으 며, 이 때 는 직접 again 으로 돌아 간 후 아래 access 를 계속 합 니 다.
2 NGX_AGAIN 과 NGXDONE 는 access 모듈 이 이 두 개 를 되 돌려 주지 않 은 것 처럼 보 이 는 상황 을 찾 았 다. 그러나 우 리 는 handler 가 직접 종료 하려 면 이 두 개 를 되 돌려 주면 된다 는 것 만 알 면 된다.
3 NGX_OK 는 access 검증 을 통 해
4 기타, 예 를 들 어 error 및 http 오류 등 은 ngx 에 게 맡 깁 니 다.http_finalize_요청 처리.
access phase 는 현재 요청 이 통과 할 수 있 는 지 검증 하 는 데 사 용 됩 니 다.코드 보기

ngx_int_t
ngx_http_core_access_phase(ngx_http_request_t *r, ngx_http_phase_handler_t *ph)
{
ngx_int_t rc;
ngx_http_core_loc_conf_t *clcf;

//r->main r 。
if (r != r->main) {
r->phase_handler = ph->next;
return NGX_AGAIN;
}

ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"access phase: %ui", r->phase_handler);
// handler
rc = ph->handler(r);
// declined, handler 。
if (rc == NGX_DECLINED) {
r->phase_handler++;
return NGX_AGAIN;
}
// ok, handler 。
if (rc == NGX_AGAIN || rc == NGX_DONE) {
return NGX_OK;
}

clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
// all, access 。
if (clcf->satisfy == NGX_HTTP_SATISFY_ALL) {
// phase handler 。
if (rc == NGX_OK) {
r->phase_handler++;
return NGX_AGAIN;
}

} else {
if (rc == NGX_OK) {
// access_code 。
r->access_code = 0;

if (r->headers_out.www_authenticate) {
r->headers_out.www_authenticate->hash = 0;
}
// access , handler phase handler。
r->phase_handler = ph->next;
return NGX_AGAIN;
}
//
if (rc == NGX_HTTP_FORBIDDEN || rc == NGX_HTTP_UNAUTHORIZED) {
// access_code, handler , access_code
r->access_code = rc;
// phase handler
r->phase_handler++;
return NGX_AGAIN;
}
}

/* rc == NGX_ERROR || rc == NGX_HTTP_... */
// request
ngx_http_finalize_request(r, rc);
return NGX_OK;
}

그리고 NGXHTTP_ACCESS_PHASE 이 phase 의 checker, ngxhttp_core_post_access_phase。여기 주의 하 세 요. use 만 있 습 니 다.access 에서 이 checker 를 호출 할 수 있 습 니 다. 그렇지 않 으 면 checker 체인 에 이 phase 가 없습니다.
이 phase 는 비교적 간단 합 니 다. 주로 access 를 처리 합 니 다.code, 즉 access phase 에 설 치 된 accesscode.
ngx_int_t
ngx_http_core_post_access_phase(ngx_http_request_t *r,
ngx_http_phase_handler_t *ph)
{
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"post access phase: %ui", r->phase_handler);
// access_code
if (r->access_code) {
// error
if (r->access_code == NGX_HTTP_FORBIDDEN) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"access forbidden by rule");
}
// request
ngx_http_finalize_request(r, r->access_code);
return NGX_OK;
}
// handler
r->phase_handler++;
return NGX_AGAIN;
}

그리고 NGXHTTP_TRY_FILES_PHASE 이 phase 의 checker, ngxhttp_core_try_files_phase。
이 phase 코드 는 좀 작 지만 논 리 는 간단 합 니 다. 요청 파일 이 없 으 면 try 를 엽 니 다.file 이 정의 한 location 에서 해당 하 는 파일 을 호출 하고 마지막 에 정상적으로 되 돌아 갑 니 다. 즉, AGAIN 으로 돌아 갑 니 다.
마지막 으로 NGXHTTP_CONTENT_PHASE 의 checker, ngxhttp_core_content_phase。
이 phase 는 일반적으로 우리 가 작성 한 대부분의 handler 는 이 phase 에 속 합 니 다. 그 는 내용 을 만 드 는 데 사 용 됩 니 다.
하지만 여 기 는 도 메 인 content 를 주의해 야 합 니 다.handler, 이 handler 가 존재 한다 면 전체 content phase 는 이 handler 만 실행 하고 NGX 로 돌아 갑 니 다.OK.
그리고 handler 반환 값 을 분석 합 니 다.
1 NGX_돈 은 이때 handler 가 성공 했다 는 것 을 설명 한다.
2 NGX_DECLINED 는 이 phase 의 다음 handler 를 실행 해 야 함 을 표시 합 니 다.
3 기타, 이 때 finalize request 가 필요 합 니 다.
코드 보기
ngx_int_t
ngx_http_core_content_phase(ngx_http_request_t *r,
ngx_http_phase_handler_t *ph)
{
size_t root;
ngx_int_t rc;
ngx_str_t path;

// content_handler, conteng_handler
if (r->content_handler) {
r->write_event_handler = ngx_http_request_empty_handler;
ngx_http_finalize_request(r, r->content_handler(r));
// NGX_OK
return NGX_OK;
}

ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"content phase: %ui", r->phase_handler);
// push handler
rc = ph->handler(r);

if (rc == NGX_DONE) {
// ok, 。
return NGX_OK;
}

if (rc != NGX_DECLINED) {
// finalize requst
ngx_http_finalize_request(r, rc);
return NGX_OK;
}

/* rc == NGX_DECLINED */

ph++;

// handler checker again,
if (ph->checker) {
r->phase_handler++;
return NGX_AGAIN;
}

/* no content handler was found */

// handler 。
if (r->uri.data[r->uri.len - 1] == '/' && !r->zero_in_uri) {

if (ngx_http_map_uri_to_path(r, &path, &root, 0) != NULL) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"directory index of \"%s\" is forbidden", path.data);
}

ngx_http_finalize_request(r, NGX_HTTP_FORBIDDEN);
return NGX_OK;
}

ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "no handler found");

ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND);
return NGX_OK;
}

좋은 웹페이지 즐겨찾기