nginx-0.2.5-RELEASE import
*) Change: the duplicate value of the ngx_http_geo_module variable now
causes the warning and changes old value.
*) Feature: the ngx_http_ssi_module supports the "set" command.
*) Feature: the ngx_http_ssi_module supports the "file" parameter in
the "include" command.
*) Feature: the ngx_http_ssi_module supports the variable value
substitutions in expressions of the "if" command.
diff --git a/src/http/modules/ngx_http_autoindex_module.c b/src/http/modules/ngx_http_autoindex_module.c
index d5a6b69..f568964 100644
--- a/src/http/modules/ngx_http_autoindex_module.c
+++ b/src/http/modules/ngx_http_autoindex_module.c
@@ -514,7 +514,7 @@
b->last = ngx_cpymem(b->last, tail, sizeof(tail) - 1);
- if (r->main == NULL) {
+ if (r->main == r) {
b->last_buf = 1;
}
diff --git a/src/http/modules/ngx_http_chunked_filter_module.c b/src/http/modules/ngx_http_chunked_filter_module.c
index bfa3624..85ca934 100644
--- a/src/http/modules/ngx_http_chunked_filter_module.c
+++ b/src/http/modules/ngx_http_chunked_filter_module.c
@@ -50,7 +50,7 @@
static ngx_int_t
ngx_http_chunked_header_filter(ngx_http_request_t *r)
{
- if (r->headers_out.status == NGX_HTTP_NOT_MODIFIED || r->main) {
+ if (r->headers_out.status == NGX_HTTP_NOT_MODIFIED || r->main != r) {
return ngx_http_next_header_filter(r);
}
diff --git a/src/http/modules/ngx_http_geo_module.c b/src/http/modules/ngx_http_geo_module.c
index 2031a4c..eedc1f7 100644
--- a/src/http/modules/ngx_http_geo_module.c
+++ b/src/http/modules/ngx_http_geo_module.c
@@ -182,11 +182,11 @@
ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
{
ngx_int_t rc, n;
- ngx_uint_t i;
ngx_str_t *value, file;
+ ngx_uint_t i;
ngx_inet_cidr_t cidrin;
ngx_http_geo_conf_t *geo;
- ngx_http_variable_value_t *var, **v;
+ ngx_http_variable_value_t *var, *old, **v;
geo = cf->ctx;
@@ -274,17 +274,33 @@
*v = var;
}
- rc = ngx_radix32tree_insert(geo->tree, cidrin.addr, cidrin.mask,
- (uintptr_t) var);
- if (rc == NGX_ERROR) {
- return NGX_CONF_ERROR;
+ for (i = 2; i; i--) {
+ rc = ngx_radix32tree_insert(geo->tree, cidrin.addr, cidrin.mask,
+ (uintptr_t) var);
+ if (rc == NGX_OK) {
+ return NGX_CONF_OK;
+ }
+
+ if (rc == NGX_ERROR) {
+ return NGX_CONF_ERROR;
+ }
+
+ /* rc == NGX_BUSY */
+
+ old = (ngx_http_variable_value_t *)
+ ngx_radix32tree_find(geo->tree, cidrin.addr & cidrin.mask);
+
+ ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
+ "duplicate parameter \"%V\", value: \"%V\", "
+ "old value: \"%V\"",
+ &value[0], &var->text, &old->text);
+
+ rc = ngx_radix32tree_delete(geo->tree, cidrin.addr, cidrin.mask);
+
+ if (rc == NGX_ERROR) {
+ return NGX_CONF_ERROR;
+ }
}
- if (rc == NGX_BUSY) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "duplicate parameter \"%V\"",
- &value[0]);
- return NGX_CONF_ERROR;
- }
-
- return NGX_CONF_OK;
+ return NGX_CONF_ERROR;
}
diff --git a/src/http/modules/ngx_http_gzip_filter_module.c b/src/http/modules/ngx_http_gzip_filter_module.c
index 012ea45..923dd17 100644
--- a/src/http/modules/ngx_http_gzip_filter_module.c
+++ b/src/http/modules/ngx_http_gzip_filter_module.c
@@ -280,7 +280,7 @@
&& r->headers_out.status != NGX_HTTP_FORBIDDEN
&& r->headers_out.status != NGX_HTTP_NOT_FOUND)
|| r->header_only
- || r->main
+ || r->main != r
|| r->http_version < conf->http_version
|| r->headers_out.content_type.len == 0
|| (r->headers_out.content_encoding
diff --git a/src/http/modules/ngx_http_headers_filter_module.c b/src/http/modules/ngx_http_headers_filter_module.c
index 43cb5c8..0855990 100644
--- a/src/http/modules/ngx_http_headers_filter_module.c
+++ b/src/http/modules/ngx_http_headers_filter_module.c
@@ -84,7 +84,7 @@
if ((r->headers_out.status != NGX_HTTP_OK
&& r->headers_out.status != NGX_HTTP_NOT_MODIFIED)
- || r->main)
+ || r->main != r)
{
return ngx_http_next_header_filter(r);
}
diff --git a/src/http/modules/ngx_http_not_modified_filter_module.c b/src/http/modules/ngx_http_not_modified_filter_module.c
index 6712a91..1e2db62 100644
--- a/src/http/modules/ngx_http_not_modified_filter_module.c
+++ b/src/http/modules/ngx_http_not_modified_filter_module.c
@@ -52,7 +52,7 @@
time_t ims;
if (r->headers_out.status != NGX_HTTP_OK
- || r->main
+ || r->main != r
|| r->headers_in.if_modified_since == NULL
|| r->headers_out.last_modified_time == -1)
{
diff --git a/src/http/modules/ngx_http_range_filter_module.c b/src/http/modules/ngx_http_range_filter_module.c
index c626495..c8b30b8 100644
--- a/src/http/modules/ngx_http_range_filter_module.c
+++ b/src/http/modules/ngx_http_range_filter_module.c
@@ -134,7 +134,7 @@
if (r->http_version < NGX_HTTP_VERSION_10
|| r->headers_out.status != NGX_HTTP_OK
- || r->main
+ || r->main != r
|| r->headers_out.content_length_n == -1
|| !r->filter_allow_ranges)
{
diff --git a/src/http/modules/ngx_http_ssi_filter_module.c b/src/http/modules/ngx_http_ssi_filter_module.c
index 885d298..acbae29 100644
--- a/src/http/modules/ngx_http_ssi_filter_module.c
+++ b/src/http/modules/ngx_http_ssi_filter_module.c
@@ -8,15 +8,18 @@
#include <ngx_core.h>
#include <ngx_http.h>
-#define NGX_HTTP_SSI_MAX_PARAMS 16
+#define NGX_HTTP_SSI_MAX_PARAMS 16
-#define NGX_HTTP_SSI_COMMAND_LEN 31
-#define NGX_HTTP_SSI_PARAM_LEN 31
-#define NGX_HTTP_SSI_PARAMS_N 4
+#define NGX_HTTP_SSI_COMMAND_LEN 31
+#define NGX_HTTP_SSI_PARAM_LEN 31
+#define NGX_HTTP_SSI_PARAMS_N 4
-#define NGX_HTTP_SSI_ERROR 1
+#define NGX_HTTP_SSI_ERROR 1
-#define NGX_HTTP_SSI_DATE_LEN 2048
+#define NGX_HTTP_SSI_DATE_LEN 2048
+
+
+#define NGX_HTTP_SSI_ADD_PREFIX 1
typedef struct {
@@ -32,6 +35,12 @@
typedef struct {
+ ngx_str_t name;
+ ngx_str_t value;
+} ngx_http_ssi_var_t;
+
+
+typedef struct {
ngx_buf_t *buf;
u_char *pos;
@@ -56,6 +65,8 @@
size_t value_len;
+ ngx_array_t variables;
+
ngx_uint_t output; /* unsigned output:1; */
ngx_str_t timefmt;
@@ -113,12 +124,18 @@
ngx_http_ssi_ctx_t *ctx);
static ngx_int_t ngx_http_ssi_parse(ngx_http_request_t *r,
ngx_http_ssi_ctx_t *ctx);
+static ngx_str_t *ngx_http_ssi_get_variable(ngx_http_request_t *r,
+ ngx_str_t *name);
+static ngx_int_t ngx_http_ssi_evaluate_string(ngx_http_request_t *r,
+ ngx_http_ssi_ctx_t *ctx, ngx_str_t *text, ngx_uint_t flags);
+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_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,
ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
-static ngx_int_t ngx_http_ssi_include(ngx_http_request_t *r,
+static ngx_int_t ngx_http_ssi_set(ngx_http_request_t *r,
ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
static ngx_int_t ngx_http_ssi_if(ngx_http_request_t *r,
ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
@@ -221,6 +238,8 @@
static ngx_str_t ngx_http_ssi_none = ngx_string("(none)");
+#define NGX_HTTP_SSI_INCLUDE_VIRTUAL 0
+#define NGX_HTTP_SSI_INCLUDE_FILE 1
#define NGX_HTTP_SSI_ECHO_VAR 0
#define NGX_HTTP_SSI_ECHO_DEFAULT 1
@@ -228,26 +247,25 @@
#define NGX_HTTP_SSI_CONFIG_ERRMSG 0
#define NGX_HTTP_SSI_CONFIG_TIMEFMT 1
-#define NGX_HTTP_SSI_INCLUDE_VIRTUAL 0
-#define NGX_HTTP_SSI_INCLUDE_FILE 1
+#define NGX_HTTP_SSI_SET_VAR 0
+#define NGX_HTTP_SSI_SET_VALUE 1
#define NGX_HTTP_SSI_IF_EXPR 0
+static ngx_http_ssi_param_t ngx_http_ssi_include_params[] = {
+ { ngx_string("virtual"), NGX_HTTP_SSI_INCLUDE_VIRTUAL, 0 },
+ { ngx_string("file"), NGX_HTTP_SSI_INCLUDE_FILE, 0 },
+ { ngx_null_string, 0, 0 }
+};
+
+
static ngx_http_ssi_param_t ngx_http_ssi_echo_params[] = {
{ ngx_string("var"), NGX_HTTP_SSI_ECHO_VAR, 1 },
{ ngx_string("default"), NGX_HTTP_SSI_ECHO_DEFAULT, 0 },
{ ngx_null_string, 0, 0 }
};
-static ngx_http_ssi_param_t ngx_http_ssi_include_params[] = {
- { ngx_string("virtual"), NGX_HTTP_SSI_INCLUDE_VIRTUAL, 0 },
-#if 0
- { ngx_string("file"), NGX_HTTP_SSI_INCLUDE_FILE, 0 },
-#endif
- { ngx_null_string, 0, 0 }
-};
-
static ngx_http_ssi_param_t ngx_http_ssi_config_params[] = {
{ ngx_string("errmsg"), NGX_HTTP_SSI_CONFIG_ERRMSG, 0 },
@@ -256,8 +274,15 @@
};
+static ngx_http_ssi_param_t ngx_http_ssi_set_params[] = {
+ { ngx_string("var"), NGX_HTTP_SSI_SET_VAR, 1 },
+ { ngx_string("value"), NGX_HTTP_SSI_SET_VALUE, 1 },
+ { ngx_null_string, 0, 0 }
+};
+
+
static ngx_http_ssi_param_t ngx_http_ssi_if_params[] = {
- { ngx_string("expr"), NGX_HTTP_SSI_IF_EXPR, 0 },
+ { ngx_string("expr"), NGX_HTTP_SSI_IF_EXPR, 1 },
{ ngx_null_string, 0, 0 }
};
@@ -268,11 +293,12 @@
static ngx_http_ssi_command_t ngx_http_ssi_commands[] = {
+ { ngx_string("include"), ngx_http_ssi_include,
+ ngx_http_ssi_include_params, 0, 1 },
{ ngx_string("echo"), ngx_http_ssi_echo, ngx_http_ssi_echo_params, 0, 0 },
{ ngx_string("config"), ngx_http_ssi_config,
ngx_http_ssi_config_params, 0, 0 },
- { ngx_string("include"), ngx_http_ssi_include,
- ngx_http_ssi_include_params, 0, 1 },
+ { ngx_string("set"), ngx_http_ssi_set, ngx_http_ssi_set_params, 0, 0 },
{ ngx_string("if"), ngx_http_ssi_if, ngx_http_ssi_if_params, 0, 0 },
{ ngx_string("else"), ngx_http_ssi_else, ngx_http_ssi_no_params, 1, 0 },
@@ -355,7 +381,7 @@
r->filter_need_in_memory = 1;
- if (r->main == NULL) {
+ if (r->main == r) {
r->headers_out.content_length_n = -1;
if (r->headers_out.content_length) {
r->headers_out.content_length->hash = 0;
@@ -1301,6 +1327,296 @@
}
+static ngx_str_t *
+ngx_http_ssi_get_variable(ngx_http_request_t *r, ngx_str_t *name)
+{
+ ngx_uint_t i;
+ ngx_http_ssi_var_t *var;
+ ngx_http_ssi_ctx_t *ctx;
+
+ ctx = ngx_http_get_module_ctx(r->main, ngx_http_ssi_filter_module);
+
+ var = ctx->variables.elts;
+ for (i = 0; i < ctx->variables.nelts; i++) {
+ if (name->len != var[i].name.len) {
+ continue;
+ }
+
+ if (ngx_strncasecmp(name->data, var[i].name.data, name->len) == 0) {
+ return &var[i].value;
+ }
+ }
+
+ return NULL;
+}
+
+
+static ngx_int_t
+ngx_http_ssi_evaluate_string(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
+ ngx_str_t *text, ngx_uint_t flags)
+{
+ u_char ch, *p, **value, *data;
+ size_t *size, len, prefix;
+ ngx_str_t var, part, *val;
+ ngx_uint_t i, j, n, bracket;
+ ngx_array_t lengths, values;
+ ngx_http_variable_value_t *vv;
+
+ n = ngx_http_script_variables_count(text);
+
+ if (n == 0) {
+
+ if (!(flags & NGX_HTTP_SSI_ADD_PREFIX)) {
+ return NGX_OK;
+ }
+
+ if (text->data[0] != '/') {
+ for (prefix = r->uri.len; prefix; prefix--) {
+ if (r->uri.data[prefix - 1] == '/') {
+ break;
+ }
+ }
+
+ if (prefix) {
+ len = prefix + text->len;
+
+ data = ngx_palloc(r->pool, len);
+ if (data == NULL) {
+ return NGX_ERROR;
+ }
+
+ p = ngx_cpymem(data, r->uri.data, prefix);
+ ngx_memcpy(p, text->data, text->len);
+
+ text->len = len;
+ text->data = data;
+ }
+ }
+
+ return NGX_OK;
+ }
+
+ if (ngx_array_init(&lengths, r->pool, 8, sizeof(size_t *)) != NGX_OK) {
+ return NGX_ERROR;
+ }
+
+ if (ngx_array_init(&values, r->pool, 8, sizeof(u_char *)) != NGX_OK) {
+ return NGX_ERROR;
+ }
+
+ len = 0;
+ i = 0;
+
+ while (i < text->len) {
+
+ if (text->data[i] == '$') {
+
+ var.len = 0;
+
+ if (++i == text->len) {
+ goto invalid_variable;
+ }
+
+ if (text->data[i] == '{') {
+ bracket = 1;
+
+ if (++i == text->len) {
+ goto invalid_variable;
+ }
+
+ var.data = &text->data[i];
+
+ } else {
+ bracket = 0;
+ var.data = &text->data[i];
+ }
+
+ for ( /* void */ ; i < text->len; i++, var.len++) {
+ ch = text->data[i];
+
+ if (ch == '}' && bracket) {
+ i++;
+ bracket = 0;
+ break;
+ }
+
+ if ((ch >= 'A' && ch <= 'Z')
+ || (ch >= 'a' && ch <= 'z')
+ || (ch >= '0' && ch <= '9')
+ || ch == '_')
+ {
+ continue;
+ }
+
+ break;
+ }
+
+ if (bracket) {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "the closing bracket in \"%V\" "
+ "variable is missing", &var);
+ return NGX_ERROR;
+ }
+
+ if (var.len == 0) {
+ goto invalid_variable;
+ }
+
+ for (j = 0; j < var.len; j++) {
+ var.data[j] = ngx_tolower(var.data[j]);
+ }
+
+ val = ngx_http_ssi_get_variable(r, &var);
+
+ if (val == NULL) {
+ vv = ngx_http_get_variable(r, &var);
+
+ if (vv == NULL) {
+ return NGX_ERROR;
+ }
+
+ if (vv == NGX_HTTP_VAR_NOT_FOUND) {
+ continue;
+ }
+
+ part = vv->text;
+
+ } else {
+ part = *val;
+ }
+
+ } else {
+ part.len = 0;
+ part.data = &text->data[i];
+
+ while (i < text->len && text->data[i] != '$') {
+ i++;
+ part.len++;
+ }
+ }
+
+ len += part.len;
+
+ size = ngx_array_push(&lengths);
+ if (size == NULL) {
+ return NGX_ERROR;
+ }
+
+ *size = part.len;
+
+ value = ngx_array_push(&values);
+ if (value == NULL) {
+ return NGX_ERROR;
+ }
+
+ *value = part.data;
+ }
+
+ prefix = 0;
+
+ size = lengths.elts;
+ value = values.elts;
+
+ if (flags & NGX_HTTP_SSI_ADD_PREFIX) {
+ for (i = 0; i < values.nelts; i++) {
+ if (size[i] != 0) {
+ if (*value[i] != '/') {
+ for (prefix = r->uri.len; prefix; prefix--) {
+ if (r->uri.data[prefix - 1] == '/') {
+ len += prefix;
+ break;
+ }
+ }
+ }
+
+ break;
+ }
+ }
+ }
+
+ p = ngx_palloc(r->pool, len);
+ if (p == NULL) {
+ return NGX_ERROR;
+ }
+
+ text->len = len;
+ text->data = p;
+
+ if (prefix) {
+ p = ngx_cpymem(p, r->uri.data, prefix);
+ }
+
+ for (i = 0; i < values.nelts; i++) {
+ p = ngx_cpymem(p, value[i], size[i]);
+ }
+
+ return NGX_OK;
+
+invalid_variable:
+
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "invalid variable name in \"%V\"", text);
+
+ return NGX_ERROR;
+}
+
+
+static ngx_int_t
+ngx_http_ssi_include(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
+ ngx_str_t **params)
+{
+ ngx_str_t *uri, *file, args;
+ ngx_uint_t i;
+
+ uri = params[NGX_HTTP_SSI_INCLUDE_VIRTUAL];
+ file = params[NGX_HTTP_SSI_INCLUDE_FILE];
+
+ if (uri && file) {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "inlcusion may be either virtual=\"%V\" or file=\"%V\"",
+ uri, file);
+ return NGX_HTTP_SSI_ERROR;
+ }
+
+ if (uri == NULL && file == NULL) {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "no parameter in \"include\" SSI command");
+ return NGX_HTTP_SSI_ERROR;
+ }
+
+ if (uri == NULL) {
+ uri = file;
+ }
+
+ if (ngx_http_ssi_evaluate_string(r, ctx, uri, NGX_HTTP_SSI_ADD_PREFIX)
+ != NGX_OK)
+ {
+ return NGX_HTTP_SSI_ERROR;
+ }
+
+ args.len = 0;
+ args.data = NULL;
+
+ if (params[NGX_HTTP_SSI_INCLUDE_VIRTUAL]) {
+ for (i = 0; i < uri->len; i++) {
+ if (uri->data[i] == '?') {
+ args.len = uri->len - i - 1;
+ args.data = &uri->data[i + 1];
+ uri->len -= args.len + 1;
+
+ break;
+ }
+ }
+ }
+
+ if (ngx_http_subrequest(r, uri, &args) != NGX_OK) {
+ return NGX_HTTP_SSI_ERROR;
+ }
+
+ return NGX_OK;
+}
+
+
static ngx_int_t
ngx_http_ssi_echo(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
ngx_str_t **params)
@@ -1313,17 +1629,25 @@
var = params[NGX_HTTP_SSI_ECHO_VAR];
- for (i = 0; i < var->len; i++) {
- var->data[i] = ngx_tolower(var->data[i]);
+ value = ngx_http_ssi_get_variable(r, var);
+
+ if (value == NULL) {
+ for (i = 0; i < var->len; i++) {
+ var->data[i] = ngx_tolower(var->data[i]);
+ }
+
+ vv = ngx_http_get_variable(r, var);
+
+ if (vv == NULL) {
+ return NGX_HTTP_SSI_ERROR;
+ }
+
+ if (vv != NGX_HTTP_VAR_NOT_FOUND) {
+ value = &vv->text;
+ }
}
- vv = ngx_http_get_variable(r, var);
-
- if (vv == NULL) {
- return NGX_HTTP_SSI_ERROR;
- }
-
- if (vv == NGX_HTTP_VAR_NOT_FOUND) {
+ if (value == NULL) {
value = params[NGX_HTTP_SSI_ECHO_DEFAULT];
if (value == NULL) {
@@ -1334,8 +1658,6 @@
}
} else {
- value = &vv->text;
-
if (value->len == 0) {
return NGX_OK;
}
@@ -1387,215 +1709,49 @@
static ngx_int_t
-ngx_http_ssi_include(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
+ngx_http_ssi_set(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
ngx_str_t **params)
{
- u_char ch, *p, **value, *data;
- size_t *size, len, prefix;
- ngx_uint_t i, j, n, bracket;
- ngx_str_t uri, args, name;
- ngx_array_t lengths, values;
- ngx_http_variable_value_t *vv;
+ ngx_str_t *name, *value, *vv;
+ ngx_http_ssi_var_t *var;
+ ngx_http_ssi_ctx_t *mctx;
- /* TODO: file, virtual vs file */
+ mctx = ngx_http_get_module_ctx(r->main, ngx_http_ssi_filter_module);
- uri = *params[NGX_HTTP_SSI_INCLUDE_VIRTUAL];
- args.len = 0;
- args.data = NULL;
- prefix = 0;
-
- n = ngx_http_script_variables_count(&uri);
-
- if (n > 0) {
-
- if (ngx_array_init(&lengths, r->pool, 8, sizeof(size_t *)) != NGX_OK) {
+ if (mctx->variables.elts == NULL) {
+ if (ngx_array_init(&mctx->variables, r->pool, 4,
+ sizeof(ngx_http_ssi_var_t)) != NGX_OK)
+ {
return NGX_HTTP_SSI_ERROR;
}
-
- if (ngx_array_init(&values, r->pool, 8, sizeof(u_char *)) != NGX_OK) {
- return NGX_HTTP_SSI_ERROR;
- }
-
- len = 0;
-
- for (i = 0; i < uri.len; /* void */ ) {
-
- name.len = 0;
-
- if (uri.data[i] == '$') {
-
- if (++i == uri.len) {
- goto invalid_variable;
- }
-
- if (uri.data[i] == '{') {
- bracket = 1;
-
- if (++i == uri.len) {
- goto invalid_variable;
- }
-
- name.data = &uri.data[i];
-
- } else {
- bracket = 0;
- name.data = &uri.data[i];
- }
-
- for ( /* void */ ; i < uri.len; i++, name.len++) {
- ch = uri.data[i];
-
- if (ch == '}' && bracket) {
- i++;
- bracket = 0;
- break;
- }
-
- if ((ch >= 'A' && ch <= 'Z')
- || (ch >= 'a' && ch <= 'z')
- || (ch >= '0' && ch <= '9')
- || ch == '_')
- {
- continue;
- }
-
- break;
- }
-
- if (bracket) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "the closing bracket in \"%V\" "
- "variable is missing", &name);
- return NGX_HTTP_SSI_ERROR;
- }
-
- if (name.len == 0) {
- goto invalid_variable;
- }
-
- for (j = 0; j < name.len; j++) {
- name.data[j] = ngx_tolower(name.data[j]);
- }
-
- vv = ngx_http_get_variable(r, &name);
-
- if (vv == NULL) {
- return NGX_HTTP_SSI_ERROR;
- }
-
- if (vv == NGX_HTTP_VAR_NOT_FOUND) {
- continue;
- }
-
- name = vv->text;
-
- } else {
- name.data = &uri.data[i];
-
- while (i < uri.len && uri.data[i] != '$') {
- i++;
- name.len++;
- }
- }
-
- len += name.len;
-
- size = ngx_array_push(&lengths);
- if (size == NULL) {
- return NGX_HTTP_SSI_ERROR;
- }
-
- *size = name.len;
-
- value = ngx_array_push(&values);
- if (value == NULL) {
- return NGX_HTTP_SSI_ERROR;
- }
-
- *value = name.data;
- }
-
- size = lengths.elts;
- value = values.elts;
-
- for (i = 0; i < values.nelts; i++) {
- if (size[i] != 0) {
- if (*value[i] != '/') {
- for (prefix = r->uri.len; prefix; prefix--) {
- if (r->uri.data[prefix - 1] == '/') {
- len += prefix;
- break;
- }
- }
- }
-
- break;
- }
- }
-
- p = ngx_palloc(r->pool, len);
- if (p == NULL) {
- return NGX_HTTP_SSI_ERROR;
- }
-
- uri.len = len;
- uri.data = p;
-
- if (prefix) {
- p = ngx_cpymem(p, r->uri.data, prefix);
- }
-
- for (i = 0; i < values.nelts; i++) {
- p = ngx_cpymem(p, value[i], size[i]);
- }
-
- } else {
- if (uri.data[0] != '/') {
- for (prefix = r->uri.len; prefix; prefix--) {
- if (r->uri.data[prefix - 1] == '/') {
- break;
- }
- }
-
- if (prefix) {
- len = prefix + uri.len;
-
- data = ngx_palloc(r->pool, len);
- if (data == NULL) {
- return NGX_HTTP_SSI_ERROR;
- }
-
- p = ngx_cpymem(data, r->uri.data, prefix);
- ngx_memcpy(p, uri.data, uri.len);
-
- uri.len = len;
- uri.data = data;
- }
- }
}
- for (i = 0; i < uri.len; i++) {
- if (uri.data[i] == '?') {
- args.len = uri.len - i - 1;
- args.data = &uri.data[i + 1];
- uri.len -= args.len + 1;
+ name = params[NGX_HTTP_SSI_SET_VAR];
+ value = params[NGX_HTTP_SSI_SET_VALUE];
- break;
- }
- }
-
- if (ngx_http_subrequest(r, &uri, &args) != NGX_OK) {
+ if (ngx_http_ssi_evaluate_string(r, ctx, value, 0) != NGX_OK) {
return NGX_HTTP_SSI_ERROR;
}
+ vv = ngx_http_ssi_get_variable(r, name);
+
+ if (vv) {
+ *vv = *value;
+ return NGX_OK;
+ }
+
+ var = ngx_array_push(&mctx->variables);
+ if (var == NULL) {
+ return NGX_HTTP_SSI_ERROR;
+ }
+
+ var->name = *name;
+ var->value = *value;
+
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "set: \"%V\"=\"%V\"", name, value);
+
return NGX_OK;
-
-invalid_variable:
-
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "invalid variable name in \"%V\"", &uri);
-
- return NGX_ERROR;
}
@@ -1603,55 +1759,55 @@
ngx_http_ssi_if(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
ngx_str_t **params)
{
- u_char *p, *last;
- ngx_str_t *expr, var, left, right;
- ngx_int_t rc;
- ngx_uint_t negative, noregex;
- ngx_http_variable_value_t *vv;
+ u_char *p, *last;
+ ngx_str_t *expr, left, right;
+ ngx_int_t rc;
+ ngx_uint_t negative, noregex;
#if (NGX_PCRE)
- ngx_str_t err;
- ngx_regex_t *regex;
- u_char errstr[NGX_MAX_CONF_ERRSTR];
+ ngx_str_t err;
+ ngx_regex_t *regex;
+ u_char errstr[NGX_MAX_CONF_ERRSTR];
#endif
expr = params[NGX_HTTP_SSI_IF_EXPR];
- if (expr->data[0] != '$') {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "invalid variable name in \"%V\"", expr);
- return NGX_HTTP_SSI_ERROR;
- }
-
- var.data = expr->data + 1;
+ left.data = expr->data;
last = expr->data + expr->len;
- for (p = var.data; p < last; p++) {
+ for (p = left.data; p < last; p++) {
if (*p >= 'A' && *p <= 'Z') {
*p |= 0x20;
continue;
}
- if ((*p >= 'a' && *p <= 'z') || (*p >= '0' && *p <= '9') || *p == '_') {
+ if ((*p >= 'a' && *p <= 'z')
+ || (*p >= '0' && *p <= '9')
+ || *p == '$' || *p == '{' || *p == '}' || *p == '_')
+ {
continue;
}
break;
}
- var.len = p - var.data;
+ left.len = p - left.data;
while (p < last && *p == ' ') {
p++;
}
- vv = ngx_http_get_variable(r, &var);
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "left: \"%V\"", &left);
- if (vv == NULL) {
+ if (ngx_http_ssi_evaluate_string(r, ctx, &left, 0) != NGX_OK) {
return NGX_HTTP_SSI_ERROR;
}
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "evaluted left: \"%V\"", &left);
+
if (p == last) {
- if (vv != NGX_HTTP_VAR_NOT_FOUND && vv->text.len != 0) {
+ if (left.len) {
ctx->output = 1;
} else {
@@ -1693,16 +1849,15 @@
right.len = last - p;
right.data = p;
- if (vv == NGX_HTTP_VAR_NOT_FOUND) {
- left.len = 0;
- left.data = (u_char *) "";
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "right: \"%V\"", &right);
- } else {
- left = vv->text;
+ if (ngx_http_ssi_evaluate_string(r, ctx, &right, 0) != NGX_OK) {
+ return NGX_HTTP_SSI_ERROR;
}
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "left: \"%V\" right: \"%V\"", &left, &right);
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "evaluted right: \"%V\"", &right);
if (noregex) {
if (left.len != right.len) {
diff --git a/src/http/modules/ngx_http_static_module.c b/src/http/modules/ngx_http_static_module.c
index d8884ca..afdbf78 100644
--- a/src/http/modules/ngx_http_static_module.c
+++ b/src/http/modules/ngx_http_static_module.c
@@ -339,7 +339,7 @@
b->in_file = 1;
- if (r->main == NULL) {
+ if (r->main == r) {
b->last_buf = 1;
}
diff --git a/src/http/modules/ngx_http_userid_filter_module.c b/src/http/modules/ngx_http_userid_filter_module.c
index 1add894..221d33b 100644
--- a/src/http/modules/ngx_http_userid_filter_module.c
+++ b/src/http/modules/ngx_http_userid_filter_module.c
@@ -206,7 +206,7 @@
ngx_http_userid_ctx_t *ctx;
ngx_http_userid_conf_t *conf;
- if (r->main) {
+ if (r->main != r) {
return ngx_http_next_header_filter(r);
}
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index e9f5942..c07e367 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -498,7 +498,7 @@
r->phase = NGX_HTTP_FIND_CONFIG_PHASE;
}
- if (r->phase == NGX_HTTP_ACCESS_PHASE && r->main) {
+ if (r->phase == NGX_HTTP_ACCESS_PHASE && r->main != r) {
continue;
}
@@ -1099,7 +1099,7 @@
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
- sr->main = r->main ? r->main : r;
+ sr->main = r->main;
sr->parent = r;
sr->read_event_handler = ngx_http_request_empty_handler;
sr->write_event_handler = ngx_http_request_empty_handler;
diff --git a/src/http/ngx_http_header_filter_module.c b/src/http/ngx_http_header_filter_module.c
index 5af1cf3..db41790 100644
--- a/src/http/ngx_http_header_filter_module.c
+++ b/src/http/ngx_http_header_filter_module.c
@@ -159,7 +159,7 @@
ngx_table_elt_t *header;
ngx_http_core_loc_conf_t *clcf;
- if (r->main) {
+ if (r->main != r) {
return NGX_OK;
}
diff --git a/src/http/ngx_http_postpone_filter_module.c b/src/http/ngx_http_postpone_filter_module.c
index 73e31e6..e75e74f 100644
--- a/src/http/ngx_http_postpone_filter_module.c
+++ b/src/http/ngx_http_postpone_filter_module.c
@@ -51,7 +51,6 @@
{
ngx_int_t rc;
ngx_chain_t *out;
- ngx_http_request_t *mr;
ngx_http_postponed_request_t *pr, **ppr;
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
@@ -110,16 +109,14 @@
out = in;
}
- mr = r->main ? r->main : r;
-
- if (out == NULL && mr->out == NULL && !mr->connection->buffered) {
+ if (out == NULL && r->main->out == NULL && !r->main->connection->buffered) {
return NGX_OK;
}
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http postpone filter out \"%V\"", &r->uri);
- rc = ngx_http_next_filter(mr, out);
+ rc = ngx_http_next_filter(r->main, out);
if (rc == NGX_ERROR) {
/* NGX_ERROR may be returned by any filter */
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index 0e6613b..704d373 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -423,6 +423,8 @@
c->single_connection = 1;
r->connection = c;
+ r->main = r;
+
r->start_time = ngx_time();
r->headers_in.content_length_n = -1;
@@ -1666,8 +1668,7 @@
wev->delayed = 0;
if (!wev->ready) {
- clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
- ngx_http_core_module);
+ clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module);
ngx_add_timer(wev, clcf->send_timeout);
if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) {
@@ -1683,8 +1684,7 @@
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0,
"http writer delayed");
- clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
- ngx_http_core_module);
+ clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module);
if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) {
ngx_http_close_request(r, 0);
@@ -1712,8 +1712,7 @@
"http writer output filter: %d, \"%V\"", rc, &r->uri);
if (rc == NGX_AGAIN) {
- clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
- ngx_http_core_module);
+ clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module);
if (!wev->ready && !wev->delayed) {
ngx_add_timer(wev, clcf->send_timeout);
}
@@ -1809,7 +1808,7 @@
ssize_t size;
ngx_event_t *rev;
- if (r->main) {
+ if (r->main != r) {
return NGX_OK;
}
diff --git a/src/http/ngx_http_script.c b/src/http/ngx_http_script.c
index 27c9ce0..a8272ec 100644
--- a/src/http/ngx_http_script.c
+++ b/src/http/ngx_http_script.c
@@ -361,11 +361,11 @@
value = ngx_http_get_indexed_variable(e->request, code->index);
- if (value == NULL || value == NGX_HTTP_VAR_NOT_FOUND) {
- return 0;
+ if (value && value != NGX_HTTP_VAR_NOT_FOUND) {
+ return value->text.len;
}
- return value->text.len;
+ return 0;
}
@@ -382,15 +382,14 @@
if (!e->skip) {
value = ngx_http_get_indexed_variable(e->request, code->index);
- if (value == NULL || value == NGX_HTTP_VAR_NOT_FOUND) {
- return;
- }
+ if (value && value != NGX_HTTP_VAR_NOT_FOUND) {
+ e->pos = ngx_cpymem(e->pos, value->text.data, value->text.len);
- e->pos = ngx_cpymem(e->pos, value->text.data, value->text.len);
-
- if (e->log) {
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
- "http script var: \"%V\"", &e->buf);
+ if (e->log) {
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP,
+ e->request->connection->log, 0,
+ "http script var: \"%V\"", &e->buf);
+ }
}
}
}
@@ -879,19 +878,18 @@
value = ngx_http_get_indexed_variable(e->request, code->index);
- if (value == NULL || value == NGX_HTTP_VAR_NOT_FOUND) {
- e->sp->value = 0;
- e->sp->text.len = 0;
- e->sp->text.data = (u_char *) "";
+ if (value && value != NGX_HTTP_VAR_NOT_FOUND) {
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
+ "http script var: %ui, \"%V\"", value->value, &value->text);
+ *e->sp = *value;
e->sp++;
return;
}
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
- "http script var: %ui, \"%V\"", value->value, &value->text);
-
- *e->sp = *value;
+ e->sp->value = 0;
+ e->sp->text.len = 0;
+ e->sp->text.data = (u_char *) "";
e->sp++;
}
diff --git a/src/http/ngx_http_special_response.c b/src/http/ngx_http_special_response.c
index 4cf8810..be23d6d 100644
--- a/src/http/ngx_http_special_response.c
+++ b/src/http/ngx_http_special_response.c
@@ -423,7 +423,7 @@
cl->buf = b;
}
- if (r->main == NULL) {
+ if (r->main == r) {
b->last_buf = 1;
}
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index 834c302..647d9d2 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -495,7 +495,7 @@
}
if (r->request_body) {
- if (r->request_body->temp_file && r->main == NULL) {
+ if (r->request_body->temp_file && r->main == r) {
/*
* the r->request_body->buf can be reused for one request only,
@@ -560,7 +560,7 @@
/* reinit the subrequest's ngx_output_chain() context */
if (r->request_body) {
- if (r->request_body->temp_file && r->main && u->output.buf) {
+ if (r->request_body->temp_file && r->main != r && u->output.buf) {
u->output.free = ngx_alloc_chain_link(r->pool);
if (u->output.free == NULL) {
@@ -1454,7 +1454,7 @@
r->connection->log->action = "sending to client";
- if (rc == 0 && r->main == NULL) {
+ if (rc == 0 && r->main == r) {
rc = ngx_http_send_last(r);
}
diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c
index 0247298..214015f 100644
--- a/src/http/ngx_http_variables.c
+++ b/src/http/ngx_http_variables.c
@@ -229,7 +229,7 @@
cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
- if (cmcf->variables.elts == NULL || cmcf->variables.nelts <= index) {
+ if (cmcf->variables.nelts <= index) {
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
"unknown variable index: %d", index);
return NULL;