diff options
author | Igor Sysoev <igor@sysoev.ru> | 2005-10-04 14:38:53 +0400 |
---|---|---|
committer | Igor Sysoev <igor@sysoev.ru> | 2005-10-04 14:38:53 +0400 |
commit | f6e1fe3f28ee43792a4543e8b9e8702713c5b74a (patch) | |
tree | 67cd150690123c53effef3aac42cca767ceafbbf /src/http | |
parent | 4dabff2624d4bae5e9cae37fb80d864501481432 (diff) |
nginx-0.2.5-RELEASE importrelease-0.2.5
*) 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.
Diffstat (limited to 'src/http')
-rw-r--r-- | src/http/modules/ngx_http_autoindex_module.c | 2 | ||||
-rw-r--r-- | src/http/modules/ngx_http_chunked_filter_module.c | 2 | ||||
-rw-r--r-- | src/http/modules/ngx_http_geo_module.c | 40 | ||||
-rw-r--r-- | src/http/modules/ngx_http_gzip_filter_module.c | 2 | ||||
-rw-r--r-- | src/http/modules/ngx_http_headers_filter_module.c | 2 | ||||
-rw-r--r-- | src/http/modules/ngx_http_not_modified_filter_module.c | 2 | ||||
-rw-r--r-- | src/http/modules/ngx_http_range_filter_module.c | 2 | ||||
-rw-r--r-- | src/http/modules/ngx_http_ssi_filter_module.c | 633 | ||||
-rw-r--r-- | src/http/modules/ngx_http_static_module.c | 2 | ||||
-rw-r--r-- | src/http/modules/ngx_http_userid_filter_module.c | 2 | ||||
-rw-r--r-- | src/http/ngx_http_core_module.c | 4 | ||||
-rw-r--r-- | src/http/ngx_http_header_filter_module.c | 2 | ||||
-rw-r--r-- | src/http/ngx_http_postpone_filter_module.c | 7 | ||||
-rw-r--r-- | src/http/ngx_http_request.c | 13 | ||||
-rw-r--r-- | src/http/ngx_http_script.c | 36 | ||||
-rw-r--r-- | src/http/ngx_http_special_response.c | 2 | ||||
-rw-r--r-- | src/http/ngx_http_upstream.c | 6 | ||||
-rw-r--r-- | src/http/ngx_http_variables.c | 2 |
18 files changed, 463 insertions, 298 deletions
diff --git a/src/http/modules/ngx_http_autoindex_module.c b/src/http/modules/ngx_http_autoindex_module.c index d5a6b69ba..f56896489 100644 --- a/src/http/modules/ngx_http_autoindex_module.c +++ b/src/http/modules/ngx_http_autoindex_module.c @@ -514,7 +514,7 @@ ngx_http_autoindex_handler(ngx_http_request_t *r) 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 bfa362408..85ca93486 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_http_output_body_filter_pt ngx_http_next_body_filter; 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 2031a4c0b..eedc1f7b2 100644 --- a/src/http/modules/ngx_http_geo_module.c +++ b/src/http/modules/ngx_http_geo_module.c @@ -182,11 +182,11 @@ static char * 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 @@ ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) *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_BUSY) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "duplicate parameter \"%V\"", - &value[0]); - return NGX_CONF_ERROR; + 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; + } } - 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 012ea4581..923dd1724 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 @@ ngx_http_gzip_header_filter(ngx_http_request_t *r) && 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 43cb5c8cd..0855990a5 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 @@ ngx_http_headers_filter(ngx_http_request_t *r) 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 6712a917d..1e2db62cd 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 @@ static ngx_int_t ngx_http_not_modified_header_filter(ngx_http_request_t *r) 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 c62649595..c8b30b850 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 @@ ngx_http_range_header_filter(ngx_http_request_t *r) 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 885d29817..acbae29eb 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 { 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 @@ typedef struct { size_t value_len; + ngx_array_t variables; + ngx_uint_t output; /* unsigned output:1; */ ngx_str_t timefmt; @@ -113,12 +124,18 @@ static ngx_int_t ngx_http_ssi_output(ngx_http_request_t *r, 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 u_char ngx_http_ssi_string[] = "<!--"; 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,23 +247,22 @@ static ngx_str_t ngx_http_ssi_none = ngx_string("(none)"); #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_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_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 } }; @@ -256,8 +274,15 @@ static ngx_http_ssi_param_t ngx_http_ssi_config_params[] = { }; +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_param_t ngx_http_ssi_no_params[] = { 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 @@ found: 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,223 +1327,197 @@ ngx_http_ssi_parse(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx) } -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_str_t * +ngx_http_ssi_get_variable(ngx_http_request_t *r, ngx_str_t *name) { - ngx_uint_t i; - ngx_buf_t *b; - ngx_str_t *var, *value; - ngx_chain_t *cl; - ngx_http_variable_value_t *vv; - - var = params[NGX_HTTP_SSI_ECHO_VAR]; + ngx_uint_t i; + ngx_http_ssi_var_t *var; + ngx_http_ssi_ctx_t *ctx; - 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; - } + ctx = ngx_http_get_module_ctx(r->main, ngx_http_ssi_filter_module); - if (vv == NGX_HTTP_VAR_NOT_FOUND) { - value = params[NGX_HTTP_SSI_ECHO_DEFAULT]; - - if (value == NULL) { - value = &ngx_http_ssi_none; - - } else if (value->len == 0) { - return NGX_OK; + var = ctx->variables.elts; + for (i = 0; i < ctx->variables.nelts; i++) { + if (name->len != var[i].name.len) { + continue; } - } else { - value = &vv->text; - - if (value->len == 0) { - return NGX_OK; + if (ngx_strncasecmp(name->data, var[i].name.data, name->len) == 0) { + return &var[i].value; } } - b = ngx_calloc_buf(r->pool); - if (b == NULL) { - return NGX_HTTP_SSI_ERROR; - } - - cl = ngx_alloc_chain_link(r->pool); - if (cl == NULL) { - return NGX_HTTP_SSI_ERROR; - } - - b->memory = 1; - b->pos = value->data; - b->last = value->data + value->len; - - cl->buf = b; - cl->next = NULL; - *ctx->last_out = cl; - ctx->last_out = &cl->next; - - return NGX_OK; + return NULL; } static ngx_int_t -ngx_http_ssi_config(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, - ngx_str_t **params) -{ - ngx_str_t *value; - - value = params[NGX_HTTP_SSI_CONFIG_TIMEFMT]; - - if (value) { - ctx->timefmt = *value; - } - - value = params[NGX_HTTP_SSI_CONFIG_ERRMSG]; - - if (value) { - ctx->errmsg = *value; - } - - return NGX_OK; -} - - -static ngx_int_t -ngx_http_ssi_include(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, - ngx_str_t **params) +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_str_t uri, args, name; ngx_array_t lengths, values; ngx_http_variable_value_t *vv; - /* TODO: file, virtual vs file */ + n = ngx_http_script_variables_count(text); - uri = *params[NGX_HTTP_SSI_INCLUDE_VIRTUAL]; - args.len = 0; - args.data = NULL; - prefix = 0; + if (n == 0) { - n = ngx_http_script_variables_count(&uri); + if (!(flags & NGX_HTTP_SSI_ADD_PREFIX)) { + return NGX_OK; + } - if (n > 0) { + if (text->data[0] != '/') { + for (prefix = r->uri.len; prefix; prefix--) { + if (r->uri.data[prefix - 1] == '/') { + break; + } + } - if (ngx_array_init(&lengths, r->pool, 8, sizeof(size_t *)) != NGX_OK) { - return NGX_HTTP_SSI_ERROR; - } + if (prefix) { + len = prefix + text->len; - if (ngx_array_init(&values, r->pool, 8, sizeof(u_char *)) != NGX_OK) { - return NGX_HTTP_SSI_ERROR; + 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; + } } - len = 0; + return NGX_OK; + } - for (i = 0; i < uri.len; /* void */ ) { + if (ngx_array_init(&lengths, r->pool, 8, sizeof(size_t *)) != NGX_OK) { + return NGX_ERROR; + } - name.len = 0; + if (ngx_array_init(&values, r->pool, 8, sizeof(u_char *)) != NGX_OK) { + return NGX_ERROR; + } - if (uri.data[i] == '$') { + len = 0; + i = 0; - if (++i == uri.len) { - goto invalid_variable; - } + while (i < text->len) { - if (uri.data[i] == '{') { - bracket = 1; + if (text->data[i] == '$') { - if (++i == uri.len) { - goto invalid_variable; - } + var.len = 0; - name.data = &uri.data[i]; + if (++i == text->len) { + goto invalid_variable; + } - } else { - bracket = 0; - name.data = &uri.data[i]; + if (text->data[i] == '{') { + bracket = 1; + + if (++i == text->len) { + goto invalid_variable; } - for ( /* void */ ; i < uri.len; i++, name.len++) { - ch = uri.data[i]; + var.data = &text->data[i]; - if (ch == '}' && bracket) { - i++; - bracket = 0; - break; - } + } else { + bracket = 0; + var.data = &text->data[i]; + } - if ((ch >= 'A' && ch <= 'Z') - || (ch >= 'a' && ch <= 'z') - || (ch >= '0' && ch <= '9') - || ch == '_') - { - continue; - } + for ( /* void */ ; i < text->len; i++, var.len++) { + ch = text->data[i]; + if (ch == '}' && bracket) { + i++; + bracket = 0; 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 ((ch >= 'A' && ch <= 'Z') + || (ch >= 'a' && ch <= 'z') + || (ch >= '0' && ch <= '9') + || ch == '_') + { + continue; } - if (name.len == 0) { - goto invalid_variable; - } + break; + } - for (j = 0; j < name.len; j++) { - name.data[j] = ngx_tolower(name.data[j]); - } + if (bracket) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "the closing bracket in \"%V\" " + "variable is missing", &var); + return NGX_ERROR; + } - vv = ngx_http_get_variable(r, &name); + 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_HTTP_SSI_ERROR; + return NGX_ERROR; } if (vv == NGX_HTTP_VAR_NOT_FOUND) { continue; } - name = vv->text; + part = vv->text; } else { - name.data = &uri.data[i]; - - while (i < uri.len && uri.data[i] != '$') { - i++; - name.len++; - } + part = *val; } - len += name.len; + } else { + part.len = 0; + part.data = &text->data[i]; - size = ngx_array_push(&lengths); - if (size == NULL) { - return NGX_HTTP_SSI_ERROR; + while (i < text->len && text->data[i] != '$') { + i++; + part.len++; } + } - *size = name.len; + len += part.len; - value = ngx_array_push(&values); - if (value == NULL) { - return NGX_HTTP_SSI_ERROR; - } + size = ngx_array_push(&lengths); + if (size == NULL) { + return NGX_ERROR; + } - *value = name.data; + *size = part.len; + + value = ngx_array_push(&values); + if (value == NULL) { + return NGX_ERROR; } - size = lengths.elts; - value = values.elts; + *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] != '/') { @@ -1532,70 +1532,226 @@ ngx_http_ssi_include(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, break; } } + } - p = ngx_palloc(r->pool, len); - if (p == NULL) { - return NGX_HTTP_SSI_ERROR; + 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; + } } + } - uri.len = len; - uri.data = p; + if (ngx_http_subrequest(r, uri, &args) != NGX_OK) { + return NGX_HTTP_SSI_ERROR; + } - if (prefix) { - p = ngx_cpymem(p, r->uri.data, prefix); + 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) +{ + ngx_uint_t i; + ngx_buf_t *b; + ngx_str_t *var, *value; + ngx_chain_t *cl; + ngx_http_variable_value_t *vv; + + var = params[NGX_HTTP_SSI_ECHO_VAR]; + + 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]); } - for (i = 0; i < values.nelts; i++) { - p = ngx_cpymem(p, value[i], size[i]); + vv = ngx_http_get_variable(r, var); + + if (vv == NULL) { + return NGX_HTTP_SSI_ERROR; } - } else { - if (uri.data[0] != '/') { - for (prefix = r->uri.len; prefix; prefix--) { - if (r->uri.data[prefix - 1] == '/') { - break; - } - } + if (vv != NGX_HTTP_VAR_NOT_FOUND) { + value = &vv->text; + } + } - if (prefix) { - len = prefix + uri.len; + if (value == NULL) { + value = params[NGX_HTTP_SSI_ECHO_DEFAULT]; - data = ngx_palloc(r->pool, len); - if (data == NULL) { - return NGX_HTTP_SSI_ERROR; - } + if (value == NULL) { + value = &ngx_http_ssi_none; - p = ngx_cpymem(data, r->uri.data, prefix); - ngx_memcpy(p, uri.data, uri.len); + } else if (value->len == 0) { + return NGX_OK; + } - uri.len = len; - uri.data = data; - } + } else { + if (value->len == 0) { + return NGX_OK; } } - 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; + b = ngx_calloc_buf(r->pool); + if (b == NULL) { + return NGX_HTTP_SSI_ERROR; + } - break; + cl = ngx_alloc_chain_link(r->pool); + if (cl == NULL) { + return NGX_HTTP_SSI_ERROR; + } + + b->memory = 1; + b->pos = value->data; + b->last = value->data + value->len; + + cl->buf = b; + cl->next = NULL; + *ctx->last_out = cl; + ctx->last_out = &cl->next; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_ssi_config(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, + ngx_str_t **params) +{ + ngx_str_t *value; + + value = params[NGX_HTTP_SSI_CONFIG_TIMEFMT]; + + if (value) { + ctx->timefmt = *value; + } + + value = params[NGX_HTTP_SSI_CONFIG_ERRMSG]; + + if (value) { + ctx->errmsg = *value; + } + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_ssi_set(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, + ngx_str_t **params) +{ + ngx_str_t *name, *value, *vv; + ngx_http_ssi_var_t *var; + ngx_http_ssi_ctx_t *mctx; + + mctx = ngx_http_get_module_ctx(r->main, ngx_http_ssi_filter_module); + + 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_http_subrequest(r, &uri, &args) != NGX_OK) { + name = params[NGX_HTTP_SSI_SET_VAR]; + value = params[NGX_HTTP_SSI_SET_VALUE]; + + if (ngx_http_ssi_evaluate_string(r, ctx, value, 0) != NGX_OK) { return NGX_HTTP_SSI_ERROR; } - return NGX_OK; + vv = ngx_http_ssi_get_variable(r, name); -invalid_variable: + if (vv) { + *vv = *value; + return NGX_OK; + } - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "invalid variable name in \"%V\"", &uri); + var = ngx_array_push(&mctx->variables); + if (var == NULL) { + return NGX_HTTP_SSI_ERROR; + } - return NGX_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; } @@ -1603,55 +1759,55 @@ static ngx_int_t 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 @@ ngx_http_ssi_if(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, 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 d8884cac8..afdbf7864 100644 --- a/src/http/modules/ngx_http_static_module.c +++ b/src/http/modules/ngx_http_static_module.c @@ -339,7 +339,7 @@ ngx_http_static_handler(ngx_http_request_t *r) 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 1add894be..221d33bf3 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_filter(ngx_http_request_t *r) 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 e9f594217..c07e367a0 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -498,7 +498,7 @@ ngx_http_core_run_phases(ngx_http_request_t *r) 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 @@ ngx_http_subrequest(ngx_http_request_t *r, 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 5af1cf386..db4179091 100644 --- a/src/http/ngx_http_header_filter_module.c +++ b/src/http/ngx_http_header_filter_module.c @@ -159,7 +159,7 @@ ngx_http_header_filter(ngx_http_request_t *r) 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 73e31e698..e75e74ffc 100644 --- a/src/http/ngx_http_postpone_filter_module.c +++ b/src/http/ngx_http_postpone_filter_module.c @@ -51,7 +51,6 @@ ngx_http_postpone_filter(ngx_http_request_t *r, ngx_chain_t *in) { 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 @@ ngx_http_postpone_filter(ngx_http_request_t *r, ngx_chain_t *in) 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 0e6613b51..704d373b6 100644 --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -423,6 +423,8 @@ void ngx_http_init_request(ngx_event_t *rev) 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 @@ ngx_http_writer(ngx_http_request_t *r) 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_http_writer(ngx_http_request_t *r) 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 @@ ngx_http_writer(ngx_http_request_t *r) "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 @@ ngx_http_discard_body(ngx_http_request_t *r) 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 27c9ce045..a8272ec67 100644 --- a/src/http/ngx_http_script.c +++ b/src/http/ngx_http_script.c @@ -361,11 +361,11 @@ ngx_http_script_copy_var_len_code(ngx_http_script_engine_t *e) 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 @@ ngx_http_script_copy_var_code(ngx_http_script_engine_t *e) 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 @@ ngx_http_script_var_code(ngx_http_script_engine_t *e) 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 4cf88101e..be23d6d5b 100644 --- a/src/http/ngx_http_special_response.c +++ b/src/http/ngx_http_special_response.c @@ -423,7 +423,7 @@ ngx_http_special_response_handler(ngx_http_request_t *r, ngx_int_t error) 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 834c30244..647d9d20a 100644 --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -495,7 +495,7 @@ ngx_http_upstream_connect(ngx_http_request_t *r, ngx_http_upstream_t *u) } 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 @@ ngx_http_upstream_reinit(ngx_http_request_t *r, ngx_http_upstream_t *u) /* 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 @@ ngx_http_upstream_finalize_request(ngx_http_request_t *r, 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 0247298b1..214015fe9 100644 --- a/src/http/ngx_http_variables.c +++ b/src/http/ngx_http_variables.c @@ -229,7 +229,7 @@ ngx_http_get_indexed_variable(ngx_http_request_t *r, ngx_uint_t index) 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; |