summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2006-10-13 15:43:38 +0000
committerJonathan Kolb <jon@b0g.us>2006-10-13 15:43:38 +0000
commitcd6f8e223aa84ecf14f8bb7594ac1e5c9ee365e1 (patch)
treec6339935b2616660d2a626e1d963bb38f4c51597
parent3fccdf4f7709199ad0df81f1dd262ce075287eab (diff)
downloadnginx-cd6f8e223aa84ecf14f8bb7594ac1e5c9ee365e1.tar.gz
Changes with nginx 0.4.9 13 Oct 2006v0.4.9
*) Feature: the "set" parameter in the "include" SSI command. *) Feature: the ngx_http_perl_module now tests the nginx.pm module version.
-rw-r--r--CHANGES8
-rw-r--r--CHANGES.ru8
-rw-r--r--README3
-rw-r--r--src/core/nginx.h3
-rw-r--r--src/core/ngx_crc.h7
-rw-r--r--src/http/modules/ngx_http_addition_filter_module.c16
-rw-r--r--src/http/modules/ngx_http_autoindex_module.c5
-rw-r--r--src/http/modules/ngx_http_dav_module.c8
-rw-r--r--src/http/modules/ngx_http_fastcgi_module.c7
-rw-r--r--src/http/modules/ngx_http_flv_module.c3
-rw-r--r--src/http/modules/ngx_http_index_module.c6
-rw-r--r--src/http/modules/ngx_http_ssi_filter_module.c218
-rw-r--r--src/http/modules/ngx_http_ssi_filter_module.h2
-rw-r--r--src/http/modules/ngx_http_static_module.c3
-rw-r--r--src/http/modules/perl/nginx.pm2
-rw-r--r--src/http/modules/perl/nginx.xs3
-rw-r--r--src/http/modules/perl/ngx_http_perl_module.c14
-rw-r--r--src/http/modules/perl/ngx_http_perl_module.h1
-rw-r--r--src/http/ngx_http_core_module.c23
-rw-r--r--src/http/ngx_http_core_module.h4
-rw-r--r--src/http/ngx_http_request.c22
-rw-r--r--src/http/ngx_http_request.h21
-rw-r--r--src/http/ngx_http_upstream.c111
-rw-r--r--src/http/ngx_http_variables.c3
24 files changed, 386 insertions, 115 deletions
diff --git a/CHANGES b/CHANGES
index 951675fd6..52be26026 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,12 @@
+Changes with nginx 0.4.9 13 Oct 2006
+
+ *) Feature: the "set" parameter in the "include" SSI command.
+
+ *) Feature: the ngx_http_perl_module now tests the nginx.pm module
+ version.
+
+
Changes with nginx 0.4.8 11 Oct 2006
*) Bugfix: if an "include" SSI command were before another "include"
diff --git a/CHANGES.ru b/CHANGES.ru
index a16ab5d92..a58f85315 100644
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,12 @@
+Изменения в nginx 0.4.9 13.10.2006
+
+ *) Добавление: параметр set в команде SSI include.
+
+ *) Добавление: модуль ngx_http_perl_module теперь проверяет версию
+ модуля nginx.pm.
+
+
Изменения в nginx 0.4.8 11.10.2006
*) Исправление: если до команды SSI include с параметром wait
diff --git a/README b/README
index 626f0a53e..10af168b5 100644
--- a/README
+++ b/README
@@ -1,3 +1,4 @@
-Documentation is available at http://sysoev.ru/nginx/ only.
+The Russian documentation is available at http://sysoev.ru/nginx/
+The English documentation is available at http://nginx.net
diff --git a/src/core/nginx.h b/src/core/nginx.h
index ef20beecf..f761a7925 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,7 +8,8 @@
#define _NGINX_H_INCLUDED_
-#define NGINX_VER "nginx/0.4.8"
+#define NGINX_VERSION "0.4.9"
+#define NGINX_VER "nginx/" NGINX_VERSION
#define NGINX_VAR "NGINX"
#define NGX_OLDPID_EXT ".oldbin"
diff --git a/src/core/ngx_crc.h b/src/core/ngx_crc.h
index 73f4cdd67..b2aff8966 100644
--- a/src/core/ngx_crc.h
+++ b/src/core/ngx_crc.h
@@ -10,15 +10,16 @@
/* 32-bit crc16 */
-static ngx_inline uint32_t ngx_crc(char *data, size_t len)
+static ngx_inline uint32_t
+ngx_crc(char *data, size_t len)
{
uint32_t sum;
for (sum = 0; len; len--) {
/*
- * gcc 2.95.2 x86 and icc 7.1.006 compile that operator
- * into the single "rol" opcode.
+ * gcc 2.95.2 x86 and icc 7.1.006 compile
+ * that operator into the single "rol" opcode,
* msvc 6.0sp2 compiles it into four opcodes.
*/
sum = sum >> 1 | sum << 31;
diff --git a/src/http/modules/ngx_http_addition_filter_module.c b/src/http/modules/ngx_http_addition_filter_module.c
index 6f15a72cc..26517147c 100644
--- a/src/http/modules/ngx_http_addition_filter_module.c
+++ b/src/http/modules/ngx_http_addition_filter_module.c
@@ -144,10 +144,10 @@ ngx_http_addition_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
ctx->before_body_sent = 1;
if (conf->before_body.len) {
- if (ngx_http_subrequest(r, &conf->before_body, NULL, &sr, NULL, 0)
- == NGX_ERROR)
- {
- return NGX_ERROR;
+ rc = ngx_http_subrequest(r, &conf->before_body, NULL, &sr, NULL, 0);
+
+ if (rc == NGX_ERROR || rc == NGX_DONE) {
+ return rc;
}
}
}
@@ -168,10 +168,10 @@ ngx_http_addition_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
return rc;
}
- if (ngx_http_subrequest(r, &conf->after_body, NULL, &sr, NULL, 0)
- == NGX_ERROR)
- {
- return NGX_ERROR;
+ rc = ngx_http_subrequest(r, &conf->after_body, NULL, &sr, NULL, 0);
+
+ if (rc == NGX_ERROR || rc == NGX_DONE) {
+ return rc;
}
ngx_http_set_ctx(r, NULL, ngx_http_addition_filter_module);
diff --git a/src/http/modules/ngx_http_autoindex_module.c b/src/http/modules/ngx_http_autoindex_module.c
index 1c7709376..f5944c447 100644
--- a/src/http/modules/ngx_http_autoindex_module.c
+++ b/src/http/modules/ngx_http_autoindex_module.c
@@ -135,7 +135,7 @@ ngx_http_autoindex_handler(ngx_http_request_t *r)
{
u_char *last, *filename, scale;
off_t length;
- size_t len, copy, allocated;
+ size_t len, copy, allocated, root;
ngx_tm_t tm;
ngx_err_t err;
ngx_buf_t *b;
@@ -174,7 +174,8 @@ ngx_http_autoindex_handler(ngx_http_request_t *r)
/* NGX_DIR_MASK_LEN is lesser than NGX_HTTP_AUTOINDEX_PREALLOCATE */
- last = ngx_http_map_uri_to_path(r, &path, NGX_HTTP_AUTOINDEX_PREALLOCATE);
+ last = ngx_http_map_uri_to_path(r, &path, &root,
+ NGX_HTTP_AUTOINDEX_PREALLOCATE);
if (last == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
diff --git a/src/http/modules/ngx_http_dav_module.c b/src/http/modules/ngx_http_dav_module.c
index 02dd3886e..81c1dc49a 100644
--- a/src/http/modules/ngx_http_dav_module.c
+++ b/src/http/modules/ngx_http_dav_module.c
@@ -102,6 +102,7 @@ static ngx_int_t
ngx_http_dav_handler(ngx_http_request_t *r)
{
char *failed;
+ size_t root;
ngx_int_t rc;
ngx_str_t path;
ngx_file_info_t fi;
@@ -152,7 +153,7 @@ ngx_http_dav_handler(ngx_http_request_t *r)
return rc;
}
- ngx_http_map_uri_to_path(r, &path, 0);
+ ngx_http_map_uri_to_path(r, &path, &root, 0);
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http delete filename: \"%s\"", path.data);
@@ -219,7 +220,7 @@ ngx_http_dav_handler(ngx_http_request_t *r)
return rc;
}
- ngx_http_map_uri_to_path(r, &path, 0);
+ ngx_http_map_uri_to_path(r, &path, &root, 0);
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http mkcol path: \"%s\"", path.data);
@@ -245,6 +246,7 @@ ngx_http_dav_put_handler(ngx_http_request_t *r)
{
char *failed;
u_char *name;
+ size_t root;
time_t date;
ngx_err_t err;
ngx_str_t *temp, path;
@@ -252,7 +254,7 @@ ngx_http_dav_put_handler(ngx_http_request_t *r)
ngx_file_info_t fi;
ngx_http_dav_loc_conf_t *dlcf;
- ngx_http_map_uri_to_path(r, &path, 0);
+ ngx_http_map_uri_to_path(r, &path, &root, 0);
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http put filename: \"%s\"", path.data);
diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c
index cce31010c..f22de517a 100644
--- a/src/http/modules/ngx_http_fastcgi_module.c
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -395,6 +395,13 @@ ngx_http_fastcgi_handler(ngx_http_request_t *r)
ngx_http_upstream_t *u;
ngx_http_fastcgi_loc_conf_t *flcf;
+ if (r->subrequest_in_memory) {
+ ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+ "ngx_http_fastcgi_module does not support "
+ "subrequest in memeory");
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
+ }
+
flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
u = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_t));
diff --git a/src/http/modules/ngx_http_flv_module.c b/src/http/modules/ngx_http_flv_module.c
index dfe4299ec..6030b7ba0 100644
--- a/src/http/modules/ngx_http_flv_module.c
+++ b/src/http/modules/ngx_http_flv_module.c
@@ -62,6 +62,7 @@ ngx_http_flv_handler(ngx_http_request_t *r)
{
u_char *p;
off_t start, len;
+ size_t root;
ngx_fd_t fd;
ngx_int_t rc;
ngx_uint_t level, i;
@@ -94,7 +95,7 @@ ngx_http_flv_handler(ngx_http_request_t *r)
return rc;
}
- if (ngx_http_map_uri_to_path(r, &path, 0) == NULL) {
+ if (ngx_http_map_uri_to_path(r, &path, &root, 0) == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
diff --git a/src/http/modules/ngx_http_index_module.c b/src/http/modules/ngx_http_index_module.c
index cd1c51ee5..3af802663 100644
--- a/src/http/modules/ngx_http_index_module.c
+++ b/src/http/modules/ngx_http_index_module.c
@@ -28,6 +28,8 @@ typedef struct {
ngx_str_t path;
ngx_str_t index;
+ size_t root;
+
ngx_uint_t tested; /* unsigned tested:1 */
} ngx_http_index_ctx_t;
@@ -200,7 +202,7 @@ ngx_http_index_handler(ngx_http_request_t *r)
if (len > (size_t) (ctx->path.data + ctx->path.len - ctx->index.data)) {
- last = ngx_http_map_uri_to_path(r, &ctx->path, len);
+ last = ngx_http_map_uri_to_path(r, &ctx->path, &ctx->root, len);
if (last == NULL) {
return NGX_ERROR;
}
@@ -291,7 +293,7 @@ ngx_http_index_handler(ngx_http_request_t *r)
uri.len = r->uri.len + ctx->index.len - 1;
if (!clcf->alias) {
- uri.data = ctx->path.data + r->root_length;
+ uri.data = ctx->path.data + ctx->root;
} else {
uri.data = ngx_palloc(r->pool, uri.len);
diff --git a/src/http/modules/ngx_http_ssi_filter_module.c b/src/http/modules/ngx_http_ssi_filter_module.c
index 21bd81946..945a4e5e5 100644
--- a/src/http/modules/ngx_http_ssi_filter_module.c
+++ b/src/http/modules/ngx_http_ssi_filter_module.c
@@ -78,6 +78,10 @@ static ngx_int_t ngx_http_ssi_evaluate_string(ngx_http_request_t *r,
static ngx_int_t ngx_http_ssi_include(ngx_http_request_t *r,
ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
+static ngx_int_t ngx_http_ssi_stub_output(ngx_http_request_t *r, void *data,
+ ngx_int_t rc);
+static ngx_int_t ngx_http_ssi_set_variable(ngx_http_request_t *r, void *data,
+ ngx_int_t rc);
static ngx_int_t ngx_http_ssi_echo(ngx_http_request_t *r,
ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
static ngx_int_t ngx_http_ssi_config(ngx_http_request_t *r,
@@ -197,11 +201,14 @@ static ngx_http_output_body_filter_pt ngx_http_next_body_filter;
static u_char ngx_http_ssi_string[] = "<!--";
static ngx_str_t ngx_http_ssi_none = ngx_string("(none)");
+static ngx_str_t ngx_http_ssi_null_string = ngx_null_string;
+
#define NGX_HTTP_SSI_INCLUDE_VIRTUAL 0
#define NGX_HTTP_SSI_INCLUDE_FILE 1
#define NGX_HTTP_SSI_INCLUDE_WAIT 2
-#define NGX_HTTP_SSI_INCLUDE_STUB 3
+#define NGX_HTTP_SSI_INCLUDE_SET 3
+#define NGX_HTTP_SSI_INCLUDE_STUB 4
#define NGX_HTTP_SSI_ECHO_VAR 0
#define NGX_HTTP_SSI_ECHO_DEFAULT 1
@@ -221,6 +228,7 @@ static ngx_http_ssi_param_t ngx_http_ssi_include_params[] = {
{ ngx_string("virtual"), NGX_HTTP_SSI_INCLUDE_VIRTUAL, 0, 0 },
{ ngx_string("file"), NGX_HTTP_SSI_INCLUDE_FILE, 0, 0 },
{ ngx_string("wait"), NGX_HTTP_SSI_INCLUDE_WAIT, 0, 0 },
+ { ngx_string("set"), NGX_HTTP_SSI_INCLUDE_SET, 0, 0 },
{ ngx_string("stub"), NGX_HTTP_SSI_INCLUDE_STUB, 0, 0 },
{ ngx_null_string, 0, 0, 0 }
};
@@ -382,7 +390,6 @@ ngx_http_ssi_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
ngx_uint_t i, index;
ngx_chain_t *cl, **ll;
ngx_table_elt_t *param;
- ngx_connection_t *c;
ngx_http_request_t *pr;
ngx_http_ssi_ctx_t *ctx, *mctx;
ngx_http_ssi_block_t *bl;
@@ -801,24 +808,14 @@ ngx_http_ssi_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
}
}
- c = r->connection;
-
rc = cmd->handler(r, ctx, params);
- if (c->destroyed) {
- return NGX_DONE;
- }
-
if (rc == NGX_OK) {
continue;
}
- if (rc == NGX_AGAIN) {
- return NGX_AGAIN;
- }
-
- if (rc == NGX_ERROR) {
- return NGX_ERROR;
+ if (rc == NGX_DONE || rc == NGX_AGAIN || rc == NGX_ERROR) {
+ return rc;
}
}
@@ -1538,6 +1535,7 @@ ngx_http_ssi_get_variable(ngx_http_request_t *r, ngx_str_t *name,
ngx_uint_t key)
{
ngx_uint_t i;
+ ngx_list_part_t *part;
ngx_http_ssi_var_t *var;
ngx_http_ssi_ctx_t *ctx;
@@ -1547,8 +1545,21 @@ ngx_http_ssi_get_variable(ngx_http_request_t *r, ngx_str_t *name,
return NULL;
}
- var = ctx->variables->elts;
- for (i = 0; i < ctx->variables->nelts; i++) {
+ part = &ctx->variables->part;
+ var = part->elts;
+
+ for (i = 0; /* void */ ; i++) {
+
+ if (i >= part->nelts) {
+ if (part->next == NULL) {
+ break;
+ }
+
+ part = part->next;
+ var = part->elts;
+ i = 0;
+ }
+
if (name->len != var[i].name.len) {
continue;
}
@@ -1693,7 +1704,7 @@ ngx_http_ssi_evaluate_string(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"the closing bracket in \"%V\" "
"variable is missing", &var);
- return NGX_ERROR;
+ return NGX_HTTP_SSI_ERROR;
}
if (var.len == 0) {
@@ -1820,7 +1831,7 @@ invalid_variable:
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"invalid variable name in \"%V\"", text);
- return NGX_ERROR;
+ return NGX_HTTP_SSI_ERROR;
}
@@ -1828,18 +1839,21 @@ static ngx_int_t
ngx_http_ssi_include(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
ngx_str_t **params)
{
- ngx_int_t rc;
- ngx_str_t *uri, *file, *wait, *stub, args;
- ngx_buf_t *b;
- ngx_uint_t flags, i;
- ngx_chain_t *out, *cl, *tl, **ll;
- ngx_http_request_t *sr;
- ngx_http_ssi_ctx_t *mctx;
- ngx_http_ssi_block_t *bl;
+ ngx_int_t rc, key;
+ ngx_str_t *uri, *file, *wait, *set, *stub, args;
+ ngx_buf_t *b;
+ ngx_uint_t flags, i;
+ ngx_chain_t *cl, *tl, **ll;
+ ngx_http_request_t *sr;
+ ngx_http_ssi_var_t *var;
+ ngx_http_ssi_ctx_t *mctx;
+ ngx_http_ssi_block_t *bl;
+ ngx_http_post_subrequest_t *psr;
uri = params[NGX_HTTP_SSI_INCLUDE_VIRTUAL];
file = params[NGX_HTTP_SSI_INCLUDE_FILE];
wait = params[NGX_HTTP_SSI_INCLUDE_WAIT];
+ set = params[NGX_HTTP_SSI_INCLUDE_SET];
stub = params[NGX_HTTP_SSI_INCLUDE_STUB];
if (uri && file) {
@@ -1855,6 +1869,13 @@ ngx_http_ssi_include(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
return NGX_HTTP_SSI_ERROR;
}
+ if (set && stub) {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "\"set\" and \"stub\" may not be used together "
+ "in \"include\" SSI command");
+ return NGX_HTTP_SSI_ERROR;
+ }
+
if (wait) {
if (uri == NULL) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
@@ -1878,10 +1899,10 @@ ngx_http_ssi_include(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
uri = file;
}
- if (ngx_http_ssi_evaluate_string(r, ctx, uri, NGX_HTTP_SSI_ADD_PREFIX)
- != NGX_OK)
- {
- return NGX_HTTP_SSI_ERROR;
+ rc = ngx_http_ssi_evaluate_string(r, ctx, uri, NGX_HTTP_SSI_ADD_PREFIX);
+
+ if (rc != NGX_OK) {
+ return rc;
}
args.len = 0;
@@ -1895,11 +1916,11 @@ ngx_http_ssi_include(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
return NGX_HTTP_SSI_ERROR;
}
- out = NULL;
+ psr = NULL;
- if (stub) {
- mctx = ngx_http_get_module_ctx(r->main, ngx_http_ssi_filter_module);
+ mctx = ngx_http_get_module_ctx(r->main, ngx_http_ssi_filter_module);
+ if (stub) {
if (mctx->blocks) {
bl = mctx->blocks->elts;
for (i = 0; i < mctx->blocks->nelts; i++) {
@@ -1917,9 +1938,16 @@ ngx_http_ssi_include(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
found:
+ psr = ngx_palloc(r->pool, sizeof(ngx_http_post_subrequest_t));
+ if (psr == NULL) {
+ return NGX_ERROR;
+ }
+
+ psr->handler = ngx_http_ssi_stub_output;
+
if (bl[i].count++) {
- ll = &out;
+ ll = (ngx_chain_t **) &psr->data;
for (tl = bl[i].bufs; tl; tl = tl->next) {
@@ -1952,17 +1980,61 @@ ngx_http_ssi_include(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
}
} else {
- out = bl[i].bufs;
+ psr->data = bl[i].bufs;
+ }
+ }
+
+ if (set) {
+ key = 0;
+
+ for (i = 0; i < set->len; i++) {
+ set->data[i] = ngx_tolower(set->data[i]);
+ key = ngx_hash(key, set->data[i]);
+ }
+
+ psr = ngx_palloc(r->pool, sizeof(ngx_http_post_subrequest_t));
+ if (psr == NULL) {
+ return NGX_ERROR;
+ }
+
+ psr->handler = ngx_http_ssi_set_variable;
+ psr->data = ngx_http_ssi_get_variable(r, set, key);
+
+ if (psr->data == NULL) {
+
+ if (mctx->variables == NULL) {
+ mctx->variables = ngx_list_create(r->pool, 4,
+ sizeof(ngx_http_ssi_var_t));
+ if (mctx->variables == NULL) {
+ return NGX_ERROR;
+ }
+ }
+
+ var = ngx_list_push(mctx->variables);
+ if (var == NULL) {
+ return NGX_ERROR;
+ }
+
+ var->name = *set;
+ var->key = key;
+ var->value = ngx_http_ssi_null_string;
+ psr->data = &var->value;
}
+
+ flags |= NGX_HTTP_SUBREQUEST_IN_MEMORY;
}
- rc = ngx_http_subrequest(r, uri, &args, &sr, out, flags);
+ rc = ngx_http_subrequest(r, uri, &args, &sr, psr, flags);
+
+ if (rc == NGX_DONE) {
+ return NGX_DONE;
+ }
if (rc == NGX_ERROR) {
return NGX_HTTP_SSI_ERROR;
}
- if (wait == NULL) {
+ if (wait == NULL && set == NULL) {
return NGX_OK;
}
@@ -1981,6 +2053,48 @@ ngx_http_ssi_include(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
static ngx_int_t
+ngx_http_ssi_stub_output(ngx_http_request_t *r, void *data, ngx_int_t rc)
+{
+ ngx_chain_t *out;
+
+ if (rc == NGX_ERROR || r->connection->error || r->request_output) {
+ return rc;
+ }
+
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "ssi stub output: \"%V?%V\"", &r->uri, &r->args);
+
+ out = data;
+
+ if (!r->header_sent) {
+ if (ngx_http_set_content_type(r) == NGX_ERROR) {
+ return NGX_ERROR;
+ }
+
+ if (ngx_http_send_header(r) == NGX_ERROR) {
+ return NGX_ERROR;
+ }
+ }
+
+ return ngx_http_output_filter(r, out);
+}
+
+
+static ngx_int_t
+ngx_http_ssi_set_variable(ngx_http_request_t *r, void *data, ngx_int_t rc)
+{
+ ngx_str_t *value = data;
+
+ if (r->upstream) {
+ value->len = r->upstream->buffer.last - r->upstream->buffer.pos;
+ value->data = r->upstream->buffer.pos;
+ }
+
+ return rc;
+}
+
+
+static ngx_int_t
ngx_http_ssi_echo(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
ngx_str_t **params)
{
@@ -2090,7 +2204,7 @@ static ngx_int_t
ngx_http_ssi_set(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
ngx_str_t **params)
{
- ngx_int_t key;
+ ngx_int_t key, rc;
ngx_uint_t i;
ngx_str_t *name, *value, *vv;
ngx_http_ssi_var_t *var;
@@ -2099,10 +2213,10 @@ ngx_http_ssi_set(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
mctx = ngx_http_get_module_ctx(r->main, ngx_http_ssi_filter_module);
if (mctx->variables == NULL) {
- mctx->variables = ngx_array_create(r->pool, 4,
- sizeof(ngx_http_ssi_var_t));
+ mctx->variables = ngx_list_create(r->pool, 4,
+ sizeof(ngx_http_ssi_var_t));
if (mctx->variables == NULL) {
- return NGX_HTTP_SSI_ERROR;
+ return NGX_ERROR;
}
}
@@ -2112,8 +2226,10 @@ ngx_http_ssi_set(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"ssi set \"%V\" \"%V\"", name, value);
- if (ngx_http_ssi_evaluate_string(r, ctx, value, 0) != NGX_OK) {
- return NGX_HTTP_SSI_ERROR;
+ rc = ngx_http_ssi_evaluate_string(r, ctx, value, 0);
+
+ if (rc != NGX_OK) {
+ return rc;
}
key = 0;
@@ -2130,9 +2246,9 @@ ngx_http_ssi_set(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
return NGX_OK;
}
- var = ngx_array_push(mctx->variables);
+ var = ngx_list_push(mctx->variables);
if (var == NULL) {
- return NGX_HTTP_SSI_ERROR;
+ return NGX_ERROR;
}
var->name = *name;
@@ -2209,8 +2325,10 @@ ngx_http_ssi_if(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"left: \"%V\"", &left);
- if (ngx_http_ssi_evaluate_string(r, ctx, &left, flags) != NGX_OK) {
- return NGX_HTTP_SSI_ERROR;
+ rc = ngx_http_ssi_evaluate_string(r, ctx, &left, flags);
+
+ if (rc != NGX_OK) {
+ return rc;
}
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
@@ -2271,8 +2389,10 @@ ngx_http_ssi_if(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"right: \"%V\"", &right);
- if (ngx_http_ssi_evaluate_string(r, ctx, &right, flags) != NGX_OK) {
- return NGX_HTTP_SSI_ERROR;
+ rc = ngx_http_ssi_evaluate_string(r, ctx, &right, flags);
+
+ if (rc != NGX_OK) {
+ return rc;
}
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
diff --git a/src/http/modules/ngx_http_ssi_filter_module.h b/src/http/modules/ngx_http_ssi_filter_module.h
index 2891969e3..915d89073 100644
--- a/src/http/modules/ngx_http_ssi_filter_module.h
+++ b/src/http/modules/ngx_http_ssi_filter_module.h
@@ -56,7 +56,7 @@ typedef struct {
size_t value_len;
- ngx_array_t *variables;
+ ngx_list_t *variables;
ngx_array_t *blocks;
unsigned conditional:2;
diff --git a/src/http/modules/ngx_http_static_module.c b/src/http/modules/ngx_http_static_module.c
index f9df46eeb..bc150bffa 100644
--- a/src/http/modules/ngx_http_static_module.c
+++ b/src/http/modules/ngx_http_static_module.c
@@ -73,6 +73,7 @@ static ngx_int_t
ngx_http_static_handler(ngx_http_request_t *r)
{
u_char *last, *location;
+ size_t root;
ngx_fd_t fd;
ngx_int_t rc;
ngx_uint_t level;
@@ -112,7 +113,7 @@ ngx_http_static_handler(ngx_http_request_t *r)
* so we do not need to reserve memory for '/' for possible redirect
*/
- last = ngx_http_map_uri_to_path(r, &path, 0);
+ last = ngx_http_map_uri_to_path(r, &path, &root, 0);
if (last == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm
index 309eaa545..2ab9820f4 100644
--- a/src/http/modules/perl/nginx.pm
+++ b/src/http/modules/perl/nginx.pm
@@ -17,7 +17,7 @@ our @EXPORT = qw(
HTTP_SERVER_ERROR
);
-our $VERSION = '0.4.0';
+our $VERSION = '0.4.9';
require XSLoader;
XSLoader::load('nginx', $VERSION);
diff --git a/src/http/modules/perl/nginx.xs b/src/http/modules/perl/nginx.xs
index d261afa02..f65bbf093 100644
--- a/src/http/modules/perl/nginx.xs
+++ b/src/http/modules/perl/nginx.xs
@@ -453,6 +453,7 @@ filename(r)
CODE:
dXSTARG;
+ size_t root;
ngx_http_request_t *r;
ngx_http_perl_ctx_t *ctx;
@@ -463,7 +464,7 @@ filename(r)
goto done;
}
- if (ngx_http_map_uri_to_path(r, &ctx->filename, 0) == NULL) {
+ if (ngx_http_map_uri_to_path(r, &ctx->filename, &root, 0) == NULL) {
XSRETURN_UNDEF;
}
diff --git a/src/http/modules/perl/ngx_http_perl_module.c b/src/http/modules/perl/ngx_http_perl_module.c
index e59ece4bb..4fd19485f 100644
--- a/src/http/modules/perl/ngx_http_perl_module.c
+++ b/src/http/modules/perl/ngx_http_perl_module.c
@@ -565,7 +565,9 @@ ngx_http_perl_create_interpreter(ngx_http_perl_main_conf_t *pmcf,
ngx_log_t *log)
{
int n;
- char *embedding[6];
+ STRLEN len;
+ SV *sv;
+ char *ver, *embedding[6];
PerlInterpreter *perl;
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "create perl interpreter");
@@ -634,6 +636,16 @@ ngx_http_perl_create_interpreter(ngx_http_perl_main_conf_t *pmcf,
goto fail;
}
+ sv = get_sv("nginx::VERSION", FALSE);
+ ver = SvPV(sv, len);
+
+ if (ngx_strcmp(ver, NGINX_VERSION) != 0) {
+ ngx_log_error(NGX_LOG_ALERT, log, 0,
+ "version " NGINX_VERSION " of nginx.pm is required, "
+ "but %s was found", ver);
+ goto fail;
+ }
+
if (ngx_http_perl_run_requires(aTHX_ &pmcf->requires, log) != NGX_OK) {
goto fail;
}
diff --git a/src/http/modules/perl/ngx_http_perl_module.h b/src/http/modules/perl/ngx_http_perl_module.h
index 66d15da1c..5a3d5082a 100644
--- a/src/http/modules/perl/ngx_http_perl_module.h
+++ b/src/http/modules/perl/ngx_http_perl_module.h
@@ -11,6 +11,7 @@
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
+#include <nginx.h>
#include <EXTERN.h>
#include <perl.h>
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index c132a2d52..f70c98879 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -794,6 +794,7 @@ 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;
@@ -830,7 +831,7 @@ ngx_http_core_content_phase(ngx_http_request_t *r,
if (r->uri.data[r->uri.len - 1] == '/' && !r->zero_in_uri) {
- if (ngx_http_map_uri_to_path(r, &path, 0) != NULL) {
+ 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 \"%V\" is forbidden", &path);
}
@@ -1157,7 +1158,7 @@ ngx_http_output_filter(ngx_http_request_t *r, ngx_chain_t *in)
u_char *
ngx_http_map_uri_to_path(ngx_http_request_t *r, ngx_str_t *path,
- size_t reserved)
+ size_t *root_length, size_t reserved)
{
u_char *last;
size_t alias;
@@ -1178,7 +1179,7 @@ ngx_http_map_uri_to_path(ngx_http_request_t *r, ngx_str_t *path,
if (clcf->root_lengths == NULL) {
- r->root_length = clcf->root.len;
+ *root_length = clcf->root.len;
path->len = clcf->root.len + reserved;
@@ -1201,8 +1202,8 @@ ngx_http_map_uri_to_path(ngx_http_request_t *r, ngx_str_t *path,
return NULL;
}
- r->root_length = path->len - reserved;
- last = path->data + r->root_length;
+ *root_length = path->len - reserved;
+ last = path->data + *root_length;
}
last = ngx_cpystrn(last, r->uri.data + alias, r->uri.len - alias + 1);
@@ -1284,7 +1285,7 @@ ngx_http_auth_basic_user(ngx_http_request_t *r)
ngx_int_t
ngx_http_subrequest(ngx_http_request_t *r,
ngx_str_t *uri, ngx_str_t *args, ngx_http_request_t **psr,
- ngx_chain_t *out, ngx_uint_t flags)
+ ngx_http_post_subrequest_t *ps, ngx_uint_t flags)
{
ngx_connection_t *c;
ngx_http_request_t *sr;
@@ -1341,7 +1342,6 @@ ngx_http_subrequest(ngx_http_request_t *r,
sr->method = NGX_HTTP_GET;
sr->http_version = r->http_version;
- sr->http_major = r->http_minor;
sr->request_line = r->request_line;
sr->uri = *uri;
@@ -1353,9 +1353,8 @@ ngx_http_subrequest(ngx_http_request_t *r,
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
"http subrequest \"%V?%V\"", uri, &sr->args);
- if (flags & NGX_HTTP_ZERO_IN_URI) {
- sr->zero_in_uri = 1;
- }
+ sr->zero_in_uri = (flags & NGX_HTTP_ZERO_IN_URI) != 0;
+ sr->subrequest_in_memory = (flags & NGX_HTTP_SUBREQUEST_IN_MEMORY) != 0;
sr->unparsed_uri = r->unparsed_uri;
sr->method_name = r->method_name;
@@ -1365,9 +1364,9 @@ ngx_http_subrequest(ngx_http_request_t *r,
return NGX_ERROR;
}
- sr->out = out;
sr->main = r->main;
sr->parent = r;
+ sr->post_subrequest = ps;
sr->read_event_handler = ngx_http_request_empty_handler;
sr->write_event_handler = ngx_http_request_empty_handler;
@@ -1431,7 +1430,7 @@ ngx_http_subrequest(ngx_http_request_t *r,
return NGX_AGAIN;
}
- return NGX_OK;
+ return NGX_DONE;
}
diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h
index f8ea3281a..bdb3a4a76 100644
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -301,12 +301,12 @@ ngx_int_t ngx_http_core_content_phase(ngx_http_request_t *r,
ngx_int_t ngx_http_set_content_type(ngx_http_request_t *r);
ngx_int_t ngx_http_set_exten(ngx_http_request_t *r);
u_char *ngx_http_map_uri_to_path(ngx_http_request_t *r, ngx_str_t *name,
- size_t reserved);
+ size_t *root_length, size_t reserved);
ngx_int_t ngx_http_auth_basic_user(ngx_http_request_t *r);
ngx_int_t ngx_http_subrequest(ngx_http_request_t *r,
ngx_str_t *uri, ngx_str_t *args, ngx_http_request_t **sr,
- ngx_chain_t *out, ngx_uint_t flags);
+ ngx_http_post_subrequest_t *psr, ngx_uint_t flags);
ngx_int_t ngx_http_internal_redirect(ngx_http_request_t *r,
ngx_str_t *uri, ngx_str_t *args);
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index 5ce2e2ae7..a7bbcddd5 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -1476,26 +1476,8 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
return;
}
- if (r != r->main
- && rc != NGX_ERROR
- && !r->connection->error
- && !r->request_output
- && r->out)
- {
- if (!r->header_sent) {
- rc = ngx_http_set_content_type(r);
-
- if (rc == NGX_OK) {
- rc = ngx_http_send_header(r);
-
- if (rc != NGX_ERROR) {
- rc = ngx_http_output_filter(r, r->out);
- }
- }
-
- } else {
- rc = ngx_http_output_filter(r, r->out);
- }
+ if (r != r->main && r->post_subrequest) {
+ rc = r->post_subrequest->handler(r, r->post_subrequest->data, rc);
}
if (rc == NGX_ERROR
diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h
index 08ccd1348..1e98b2df0 100644
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -47,7 +47,9 @@
#define NGX_HTTP_PARSE_INVALID_HEADER 13
+
#define NGX_HTTP_ZERO_IN_URI 1
+#define NGX_HTTP_SUBREQUEST_IN_MEMORY 2
#define NGX_HTTP_OK 200
@@ -287,6 +289,15 @@ struct ngx_http_cleanup_s {
};
+typedef ngx_int_t (*ngx_http_post_subrequest_pt)(ngx_http_request_t *r,
+ void *data, ngx_int_t rc);
+
+typedef struct {
+ ngx_http_post_subrequest_pt handler;
+ void *data;
+} ngx_http_post_subrequest_t;
+
+
typedef struct ngx_http_postponed_request_s ngx_http_postponed_request_t;
struct ngx_http_postponed_request_s {
@@ -330,8 +341,6 @@ struct ngx_http_request_s {
ngx_uint_t method;
ngx_uint_t http_version;
- ngx_uint_t http_major;
- ngx_uint_t http_minor;
ngx_str_t request_line;
ngx_str_t uri;
@@ -346,6 +355,7 @@ struct ngx_http_request_s {
ngx_http_request_t *main;
ngx_http_request_t *parent;
ngx_http_postponed_request_t *postponed;
+ ngx_http_post_subrequest_t *post_subrequest;
uint32_t in_addr;
ngx_uint_t port;
@@ -359,8 +369,6 @@ struct ngx_http_request_s {
ngx_http_variable_value_t *variables;
- size_t root_length;
-
size_t limit_rate;
/* used to learn the Apache compatible response length without a header */
@@ -405,6 +413,7 @@ struct ngx_http_request_s {
unsigned request_body_file_log_level:3;
unsigned fast_subrequest:1;
+ unsigned subrequest_in_memory:1;
unsigned header_timeout_set:1;
@@ -456,6 +465,7 @@ struct ngx_http_request_s {
unsigned subrequests:8;
/* used to parse HTTP headers */
+
ngx_uint_t state;
u_char *uri_start;
u_char *uri_end;
@@ -475,6 +485,9 @@ struct ngx_http_request_s {
u_char *header_start;
u_char *header_end;
+ unsigned http_minor:16;
+ unsigned http_major:16;
+
ngx_uint_t header_hash;
ngx_uint_t lowcase_index;
u_char lowcase_header[NGX_HTTP_LC_HEADER_LEN];
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index e4a4d4058..dc70091de 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -21,6 +21,7 @@ static void ngx_http_upstream_send_request(ngx_http_request_t *r,
ngx_http_upstream_t *u);
static void ngx_http_upstream_send_request_handler(ngx_event_t *wev);
static void ngx_http_upstream_process_header(ngx_event_t *rev);
+static void ngx_http_upstream_process_body_in_memory(ngx_event_t *rev);
static void ngx_http_upstream_send_response(ngx_http_request_t *r,
ngx_http_upstream_t *u);
static void
@@ -1061,6 +1062,12 @@ ngx_http_upstream_process_header(ngx_event_t *rev)
/* rc == NGX_OK */
+ if (u->headers_in.status_n >= NGX_HTTP_BAD_REQUEST
+ && r->subrequest_in_memory)
+ {
+ u->buffer.last = u->buffer.pos;
+ }
+
if (u->headers_in.status_n == NGX_HTTP_INTERNAL_SERVER_ERROR) {
if (u->peer.tries > 1
@@ -1248,7 +1255,109 @@ ngx_http_upstream_process_header(ngx_event_t *rev)
u->length = NGX_MAX_SIZE_T_VALUE;
}
- ngx_http_upstream_send_response(r, u);
+ if (!r->subrequest_in_memory) {
+ ngx_http_upstream_send_response(r, u);
+ return;
+ }
+
+ /* subrequest content in memory */
+
+ if (u->input_filter == NULL) {
+ u->input_filter_init = ngx_http_upstream_non_buffered_filter_init;
+ u->input_filter = ngx_http_upstream_non_buffered_filter;
+ u->input_filter_ctx = r;
+ }
+
+ if (u->input_filter_init(u->input_filter_ctx) == NGX_ERROR) {
+ ngx_http_upstream_finalize_request(r, u,
+ NGX_HTTP_INTERNAL_SERVER_ERROR);
+ return;
+ }
+
+ if (u->buffer.last - u->buffer.pos >= (ssize_t) u->length) {
+ if (u->input_filter(u->input_filter_ctx, 0) == NGX_ERROR) {
+ ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
+ return;
+ }
+
+ ngx_http_upstream_finalize_request(r, u, 0);
+ return;
+ }
+
+ rev->handler = ngx_http_upstream_process_body_in_memory;
+
+ ngx_http_upstream_process_body_in_memory(rev);
+}
+
+
+static void
+ngx_http_upstream_process_body_in_memory(ngx_event_t *rev)
+{
+ size_t size;
+ ssize_t n;
+ ngx_buf_t *b;
+ ngx_connection_t *c;
+ ngx_http_request_t *r;
+ ngx_http_upstream_t *u;
+
+ c = rev->data;
+ r = c->data;
+ u = r->upstream;
+
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
+ "http upstream process body on memory");
+
+ if (rev->timedout) {
+ ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out");
+ ngx_http_upstream_finalize_request(r, u, NGX_ETIMEDOUT);
+ return;
+ }
+
+ b = &u->buffer;
+
+ for ( ;; ) {
+
+ size = b->end - b->last;
+
+ if (size == 0) {
+ ngx_log_error(NGX_LOG_ALERT, c->log, 0,
+ "upstream buffer is too small to read repsonse");
+ ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
+ return;
+ }
+
+ n = c->recv(c, b->last, size);
+
+ if (n == NGX_AGAIN) {
+ break;
+ }
+
+ if (n == 0 || n == NGX_ERROR) {
+ ngx_http_upstream_finalize_request(r, u, n);
+ return;
+ }
+
+ if (u->input_filter(u->input_filter_ctx, n) == NGX_ERROR) {
+ ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
+ return;
+ }
+
+ if (!rev->ready) {
+ break;
+ }
+ }
+
+ if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
+ ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
+ return;
+ }
+
+ if (rev->active) {
+ ngx_add_timer(rev, u->conf->read_timeout);
+
+ } else if (rev->timer_set) {
+ ngx_del_timer(rev);
+ }
}
diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c
index 0f1587b64..ecf20c372 100644
--- a/src/http/ngx_http_variables.c
+++ b/src/http/ngx_http_variables.c
@@ -852,9 +852,10 @@ static ngx_int_t
ngx_http_variable_request_filename(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)
{
+ size_t root;
ngx_str_t path;
- if (ngx_http_map_uri_to_path(r, &path, 0) == NULL) {
+ if (ngx_http_map_uri_to_path(r, &path, &root, 0) == NULL) {
return NGX_ERROR;
}