Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nginx/nginx.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/http/ngx_http_core_module.c')
-rw-r--r--src/http/ngx_http_core_module.c376
1 files changed, 237 insertions, 139 deletions
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index 2a5d3da11..e7f54dd12 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -23,7 +23,6 @@ typedef struct {
#define NGX_HTTP_LOCATION_REGEX 4
-static void ngx_http_core_run_phases(ngx_http_request_t *r);
static ngx_int_t ngx_http_core_find_location(ngx_http_request_t *r,
ngx_array_t *locations, size_t len);
@@ -474,6 +473,8 @@ ngx_module_t ngx_http_core_module = {
void
ngx_http_handler(ngx_http_request_t *r)
{
+ ngx_http_core_main_conf_t *cmcf;
+
r->connection->log->action = NULL;
r->connection->unexpected_eof = 0;
@@ -500,8 +501,8 @@ ngx_http_handler(ngx_http_request_t *r)
if (r->keepalive && r->headers_in.msie && r->method == NGX_HTTP_POST) {
/*
- * MSIE may wait for some time if the response for
- * the POST request is sent over the keepalive connection
+ * MSIE may wait for some time if an response for
+ * a POST request was sent over a keepalive connection
*/
r->keepalive = 0;
@@ -515,172 +516,84 @@ ngx_http_handler(ngx_http_request_t *r)
}
}
- r->write_event_handler = ngx_http_core_run_phases;
-
r->valid_unparsed_uri = 1;
r->valid_location = 1;
- r->uri_changed = 1;
- r->phase = (!r->internal) ? NGX_HTTP_POST_READ_PHASE:
- NGX_HTTP_SERVER_REWRITE_PHASE;
- r->phase_handler = 0;
+ if (!r->internal) {
+ r->phase_handler = 0;
+ } else {
+ cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
+ r->phase_handler = cmcf->phase_engine.server_rewrite_index;
+ }
+
+ r->write_event_handler = ngx_http_core_run_phases;
ngx_http_core_run_phases(r);
}
-static void
+void
ngx_http_core_run_phases(ngx_http_request_t *r)
{
ngx_int_t rc;
- ngx_str_t path;
- ngx_http_handler_pt *h;
- ngx_http_core_loc_conf_t *clcf;
+ ngx_http_phase_handler_t *ph;
ngx_http_core_main_conf_t *cmcf;
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http phase handler");
-
cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
- for (/* void */; r->phase < NGX_HTTP_LOG_PHASE; r->phase++) {
-
- if (r->phase == NGX_HTTP_REWRITE_PHASE + 1 && r->uri_changed) {
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "uri changes: %d", r->uri_changes);
+ ph = cmcf->phase_engine.handlers;
- /*
- * gcc before 3.3 compiles the broken code for
- * if (r->uri_changes-- == 0)
- * if the r->uri_changes is defined as
- * unsigned uri_changes:4
- */
+ while (ph[r->phase_handler].checker) {
- r->uri_changes--;
-
- 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;
- }
+ rc = ph[r->phase_handler].checker(r, &ph[r->phase_handler]);
- r->phase = NGX_HTTP_FIND_CONFIG_PHASE;
- }
-
- if (r->phase == NGX_HTTP_ACCESS_PHASE && r != r->main) {
- continue;
- }
-
- if (r->phase == NGX_HTTP_CONTENT_PHASE && r->content_handler) {
- r->write_event_handler = ngx_http_request_empty_handler;
- ngx_http_finalize_request(r, r->content_handler(r));
+ if (rc == NGX_OK) {
return;
}
+ }
+}
- h = cmcf->phases[r->phase].handlers.elts;
- for (r->phase_handler = cmcf->phases[r->phase].handlers.nelts - 1;
- r->phase_handler >= 0;
- r->phase_handler--)
- {
- rc = h[r->phase_handler](r);
-
- if (rc == NGX_DONE) {
-
- /*
- * we should never use r here because
- * it may point to already freed data
- */
-
- return;
- }
-
- if (rc == NGX_DECLINED) {
- continue;
- }
-
- if (r->phase == NGX_HTTP_ACCESS_PHASE) {
- clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
-
- if (clcf->satisfy_any) {
-
- if (rc == NGX_OK) {
- r->access_code = 0;
-
- if (r->headers_out.www_authenticate) {
- r->headers_out.www_authenticate->hash = 0;
- }
-
- break;
- }
-
- if (rc == NGX_HTTP_FORBIDDEN || rc == NGX_HTTP_UNAUTHORIZED)
- {
- r->access_code = rc;
-
- continue;
- }
- }
- }
-
- if (rc >= NGX_HTTP_SPECIAL_RESPONSE
- || rc == NGX_HTTP_NO_CONTENT
- || rc == NGX_ERROR)
- {
- ngx_http_finalize_request(r, rc);
- return;
- }
-
- if (r->phase == NGX_HTTP_CONTENT_PHASE) {
- ngx_http_finalize_request(r, rc);
- return;
- }
-
- if (rc == NGX_AGAIN) {
- return;
- }
- if (rc == NGX_OK && cmcf->phases[r->phase].type == NGX_OK) {
- break;
- }
+ngx_int_t
+ngx_http_core_generic_phase(ngx_http_request_t *r, ngx_http_phase_handler_t *ph)
+{
+ ngx_int_t rc;
- }
+ /*
+ * generic phase checker,
+ * used by the post read, server rewrite, rewrite, and pre-access phases
+ */
- if (r->phase == NGX_HTTP_ACCESS_PHASE && r->access_code) {
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "generic phase: %ui", r->phase_handler);
- if (r->access_code == NGX_HTTP_FORBIDDEN) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "access forbidden by rule");
- }
+ rc = ph->handler(r);
- ngx_http_finalize_request(r, r->access_code);
- return;
- }
+ if (rc == NGX_OK) {
+ r->phase_handler = ph->next;
+ return NGX_AGAIN;
}
- /* no content handler was found */
-
- if (r->uri.data[r->uri.len - 1] == '/' && !r->zero_in_uri) {
-
- if (ngx_http_map_uri_to_path(r, &path, 0) != NULL) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "directory index of \"%V\" is forbidden", &path);
- }
+ if (rc == NGX_DECLINED) {
+ r->phase_handler++;
+ return NGX_AGAIN;
+ }
- ngx_http_finalize_request(r, NGX_HTTP_FORBIDDEN);
- return;
+ if (rc == NGX_AGAIN || rc == NGX_DONE) {
+ return NGX_OK;
}
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "no handler found");
+ /* rc == NGX_ERROR || rc == NGX_HTTP_... */
- ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND);
+ ngx_http_finalize_request(r, rc);
+
+ return NGX_OK;
}
ngx_int_t
-ngx_http_find_location_config(ngx_http_request_t *r)
+ngx_http_core_find_config_phase(ngx_http_request_t *r,
+ ngx_http_phase_handler_t *ph)
{
ngx_int_t rc;
ngx_http_core_loc_conf_t *clcf;
@@ -694,13 +607,15 @@ ngx_http_find_location_config(ngx_http_request_t *r)
rc = ngx_http_core_find_location(r, &cscf->locations, 0);
if (rc == NGX_HTTP_INTERNAL_SERVER_ERROR) {
- return rc;
+ 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);
if (!r->internal && clcf->internal) {
- return NGX_HTTP_NOT_FOUND;
+ ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND);
+ return NGX_OK;
}
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
@@ -723,14 +638,16 @@ ngx_http_find_location_config(ngx_http_request_t *r)
"client intented to send too large body: %O bytes",
r->headers_in.content_length_n);
- return NGX_HTTP_REQUEST_ENTITY_TOO_LARGE;
+ ngx_http_finalize_request(r, NGX_HTTP_REQUEST_ENTITY_TOO_LARGE);
+ return NGX_OK;
}
if (rc == NGX_HTTP_LOCATION_AUTO_REDIRECT) {
r->headers_out.location = ngx_list_push(&r->headers_out.headers);
if (r->headers_out.location == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+ return NGX_OK;
}
/*
@@ -740,9 +657,190 @@ ngx_http_find_location_config(ngx_http_request_t *r)
r->headers_out.location->value = clcf->name;
- return NGX_HTTP_MOVED_PERMANENTLY;
+ ngx_http_finalize_request(r, NGX_HTTP_MOVED_PERMANENTLY);
+ return NGX_OK;
}
+ r->phase_handler++;
+ return NGX_AGAIN;
+}
+
+
+ngx_int_t
+ngx_http_core_post_rewrite_phase(ngx_http_request_t *r,
+ ngx_http_phase_handler_t *ph)
+{
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "post rewrite phase: %ui", r->phase_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);
+
+ /*
+ * gcc before 3.3 compiles the broken code for
+ * if (r->uri_changes-- == 0)
+ * if the r->uri_changes is defined as
+ * unsigned uri_changes:4
+ */
+
+ r->uri_changes--;
+
+ 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;
+ }
+
+ r->phase_handler = ph->next;
+
+ return NGX_AGAIN;
+}
+
+
+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;
+
+ 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);
+
+ rc = ph->handler(r);
+
+ if (rc == NGX_DECLINED) {
+ r->phase_handler++;
+ return NGX_AGAIN;
+ }
+
+ if (rc == NGX_AGAIN || rc == NGX_DONE) {
+ return NGX_OK;
+ }
+
+ clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+
+ if (clcf->satisfy_any == 0) {
+
+ if (rc == NGX_OK) {
+ r->phase_handler++;
+ return NGX_AGAIN;
+ }
+
+ } else {
+ if (rc == NGX_OK) {
+ r->access_code = 0;
+
+ if (r->headers_out.www_authenticate) {
+ r->headers_out.www_authenticate->hash = 0;
+ }
+
+ r->phase_handler = ph->next;
+ return NGX_AGAIN;
+ }
+
+ if (rc == NGX_HTTP_FORBIDDEN || rc == NGX_HTTP_UNAUTHORIZED) {
+ r->access_code = rc;
+
+ r->phase_handler++;
+ return NGX_AGAIN;
+ }
+ }
+
+ /* rc == NGX_ERROR || rc == NGX_HTTP_... */
+
+ ngx_http_finalize_request(r, rc);
+ return NGX_OK;
+}
+
+
+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);
+
+ if (r->access_code) {
+
+ if (r->access_code == NGX_HTTP_FORBIDDEN) {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "access forbidden by rule");
+ }
+
+ ngx_http_finalize_request(r, r->access_code);
+ return NGX_OK;
+ }
+
+ r->phase_handler++;
+ return NGX_AGAIN;
+}
+
+
+ngx_int_t
+ngx_http_core_content_phase(ngx_http_request_t *r,
+ ngx_http_phase_handler_t *ph)
+{
+ ngx_int_t rc;
+ ngx_str_t path;
+
+ if (r->content_handler) {
+ r->write_event_handler = ngx_http_request_empty_handler;
+ ngx_http_finalize_request(r, r->content_handler(r));
+ return NGX_OK;
+ }
+
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "content phase: %ui", r->phase_handler);
+
+ rc = ph->handler(r);
+
+ if (rc == NGX_DONE) {
+ return NGX_OK;
+ }
+
+ if (rc != NGX_DECLINED) {
+ ngx_http_finalize_request(r, rc);
+ return NGX_OK;
+ }
+
+ /* rc == NGX_DECLINED */
+
+ ph++;
+
+ if (ph->checker) {
+ r->phase_handler++;
+ return NGX_AGAIN;
+ }
+
+ /* no content handler was found */
+
+ if (r->uri.data[r->uri.len - 1] == '/' && !r->zero_in_uri) {
+
+ if (ngx_http_map_uri_to_path(r, &path, 0) != NULL) {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "directory index of \"%V\" is forbidden", &path);
+ }
+
+ 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;
}
@@ -1916,7 +2014,7 @@ ngx_http_core_create_srv_conf(ngx_conf_t *cf)
return NGX_CONF_ERROR;
}
- if (ngx_array_init(&cscf->server_names, cf->pool, 4,
+ if (ngx_array_init(&cscf->server_names, cf->temp_pool, 4,
sizeof(ngx_http_server_name_t))
== NGX_ERROR)
{