nginx-0.3.39-RELEASE import
*) Feature: the "uninitialized_variable_warn" directive; the logging
level of the "uninitialized variable" message was lowered from
"alert" to "warn".
*) Feature: the "override_charset" directive.
*) Change: now if the unknown variable is used in the "echo" and "if
expr='$name'" SSI-commands, then the "unknown variable" message is
not logged.
*) Bugfix: the active connection counter increased on the exceeding of
the connection limit specified by the "worker_connections"
directive; the bug had appeared in 0.2.0.
*) Bugfix: the limit rate might not work on some condition; the bug had
appeared in 0.3.38.
diff --git a/src/core/nginx.h b/src/core/nginx.h
index f47c36a..1da91b7 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,7 +8,7 @@
#define _NGINX_H_INCLUDED_
-#define NGINX_VER "nginx/0.3.38"
+#define NGINX_VER "nginx/0.3.39"
#define NGINX_VAR "NGINX"
#define NGX_OLDPID_EXT ".oldbin"
diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c
index 8dbabc2..9afb952 100644
--- a/src/core/ngx_connection.c
+++ b/src/core/ngx_connection.c
@@ -386,6 +386,21 @@
}
}
+#if 0
+ if (1) {
+ int tcp_nodelay = 1;
+
+ if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_NODELAY,
+ (const void *) &tcp_nodelay, sizeof(int))
+ == -1)
+ {
+ ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
+ "setsockopt(TCP_NODELAY) %V failed, ignored",
+ &ls[i].addr_text);
+ }
+ }
+#endif
+
if (ls[i].listen) {
if (listen(ls[i].fd, ls[i].backlog) == -1) {
ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
diff --git a/src/event/ngx_event_accept.c b/src/event/ngx_event_accept.c
index 287777d..ebba872 100644
--- a/src/event/ngx_event_accept.c
+++ b/src/event/ngx_event_accept.c
@@ -78,7 +78,6 @@
#if (NGX_STAT_STUB)
ngx_atomic_fetch_add(ngx_stat_accepted, 1);
- ngx_atomic_fetch_add(ngx_stat_active, 1);
#endif
ngx_accept_disabled = NGX_ACCEPT_THRESHOLD
@@ -95,6 +94,10 @@
return;
}
+#if (NGX_STAT_STUB)
+ ngx_atomic_fetch_add(ngx_stat_active, 1);
+#endif
+
c->pool = ngx_create_pool(ls->pool_size, ev->log);
if (c->pool == NULL) {
ngx_close_accepted_connection(c);
diff --git a/src/http/modules/ngx_http_charset_filter_module.c b/src/http/modules/ngx_http_charset_filter_module.c
index cf41b62..3c9e01b 100644
--- a/src/http/modules/ngx_http_charset_filter_module.c
+++ b/src/http/modules/ngx_http_charset_filter_module.c
@@ -13,47 +13,48 @@
typedef struct {
- char **tables;
- ngx_str_t name;
+ u_char **tables;
+ ngx_str_t name;
- ngx_uint_t utf8; /* unsigned utf8:1; */
+ ngx_uint_t utf8; /* unsigned utf8:1; */
} ngx_http_charset_t;
typedef struct {
- ngx_int_t src;
- ngx_int_t dst;
+ ngx_int_t src;
+ ngx_int_t dst;
} ngx_http_charset_recode_t;
typedef struct {
- ngx_int_t src;
- ngx_int_t dst;
- char *src2dst;
- char *dst2src;
+ ngx_int_t src;
+ ngx_int_t dst;
+ u_char *src2dst;
+ u_char *dst2src;
} ngx_http_charset_tables_t;
typedef struct {
- ngx_array_t charsets; /* ngx_http_charset_t */
- ngx_array_t tables; /* ngx_http_charset_tables_t */
- ngx_array_t recodes; /* ngx_http_charset_recode_t */
+ ngx_array_t charsets; /* ngx_http_charset_t */
+ ngx_array_t tables; /* ngx_http_charset_tables_t */
+ ngx_array_t recodes; /* ngx_http_charset_recode_t */
} ngx_http_charset_main_conf_t;
typedef struct {
- ngx_int_t charset;
- ngx_int_t source_charset;
+ ngx_int_t charset;
+ ngx_int_t source_charset;
+ ngx_flag_t override_charset;
} ngx_http_charset_loc_conf_t;
typedef struct {
- ngx_int_t server;
- ngx_int_t client;
+ u_char *table;
+ ngx_int_t charset;
} ngx_http_charset_ctx_t;
-static ngx_uint_t ngx_http_charset_recode(ngx_buf_t *b, char *table);
+static ngx_uint_t ngx_http_charset_recode(ngx_buf_t *b, u_char *table);
static char *ngx_charset_map_block(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
@@ -90,6 +91,14 @@
offsetof(ngx_http_charset_loc_conf_t, source_charset),
NULL },
+ { ngx_string("override_charset"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF
+ |NGX_HTTP_LIF_CONF|NGX_CONF_FLAG,
+ ngx_conf_set_flag_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_charset_loc_conf_t, override_charset),
+ NULL },
+
{ ngx_string("charset_map"),
NGX_HTTP_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE2,
ngx_charset_map_block,
@@ -139,16 +148,30 @@
static ngx_int_t
ngx_http_charset_header_filter(ngx_http_request_t *r)
{
+ size_t len;
+ u_char *p;
+ ngx_int_t charset, source_charset;
+ ngx_uint_t i;
ngx_http_charset_t *charsets;
ngx_http_charset_ctx_t *ctx;
ngx_http_charset_loc_conf_t *lcf;
ngx_http_charset_main_conf_t *mcf;
mcf = ngx_http_get_module_main_conf(r, ngx_http_charset_filter_module);
- lcf = ngx_http_get_module_loc_conf(r, ngx_http_charset_filter_module);
- if (lcf->charset == NGX_HTTP_NO_CHARSET) {
- return ngx_http_next_header_filter(r);
+ ctx = ngx_http_get_module_ctx(r->main, ngx_http_charset_filter_module);
+
+ if (ctx == NULL) {
+ lcf = ngx_http_get_module_loc_conf(r->main,
+ ngx_http_charset_filter_module);
+ charset = lcf->charset;
+
+ if (charset == NGX_HTTP_NO_CHARSET) {
+ return ngx_http_next_header_filter(r);
+ }
+
+ } else {
+ charset = ctx->charset;
}
if (r->headers_out.content_type.len == 0) {
@@ -162,9 +185,72 @@
return ngx_http_next_header_filter(r);
}
- if (r == r->main
- && ngx_strstr(r->headers_out.content_type.data, "charset") != NULL)
- {
+ charsets = mcf->charsets.elts;
+
+ lcf = ngx_http_get_module_loc_conf(r, ngx_http_charset_filter_module);
+
+ len = 0;
+
+ for (p = r->headers_out.content_type.data; *p; p++) {
+ if (*p == ';') {
+ len = p - r->headers_out.content_type.data;
+ }
+
+ if (ngx_strncasecmp(p, "charset=", 8) != 0) {
+ continue;
+ }
+
+ p += 8;
+
+ for (i = 0; i < mcf->charsets.nelts; i++) {
+
+ if (ngx_strcasecmp(p, charsets[i].name.data) == 0) {
+
+ if (r == r->main && lcf->override_charset == 0) {
+ ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_charset_ctx_t));
+ if (ctx == NULL) {
+ return NGX_ERROR;
+ }
+
+ ngx_http_set_ctx(r, ctx, ngx_http_charset_filter_module);
+
+ ctx->charset = i;
+
+ return ngx_http_next_header_filter(r);
+ }
+
+ if (i != (ngx_uint_t) charset
+ && (charsets[i].tables == NULL
+ || charsets[i].tables[charset] == NULL))
+ {
+ ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+ "no \"charset_map\" between the charsets "
+ "\"%V\" and \"%V\"",
+ &charsets[i].name, &charsets[charset].name);
+
+ return ngx_http_next_header_filter(r);
+ }
+
+ r->headers_out.content_type.len = len;
+
+ if (r->headers_out.status == NGX_HTTP_MOVED_PERMANENTLY
+ || r->headers_out.status == NGX_HTTP_MOVED_TEMPORARILY)
+ {
+ /*
+ * do not set charset for the redirect because NN 4.x
+ * uses this charset instead of the next page charset
+ */
+
+ r->headers_out.charset.len = 0;
+ return ngx_http_next_header_filter(r);
+ }
+
+ source_charset = i;
+
+ goto found;
+ }
+ }
+
return ngx_http_next_header_filter(r);
}
@@ -172,8 +258,8 @@
|| r->headers_out.status == NGX_HTTP_MOVED_TEMPORARILY)
{
/*
- * do not set charset for the redirect because NN 4.x uses this
- * charset instead of the next page charset
+ * do not set charset for the redirect because NN 4.x
+ * use this charset instead of the next page charset
*/
r->headers_out.charset.len = 0;
@@ -184,17 +270,17 @@
return ngx_http_next_header_filter(r);
}
- charsets = mcf->charsets.elts;
- r->headers_out.charset = charsets[lcf->charset].name;
- r->utf8 = charsets[lcf->charset].utf8;
+ source_charset = lcf->source_charset;
- if (lcf->source_charset == NGX_CONF_UNSET
- || lcf->source_charset == lcf->charset)
- {
+found:
+
+ r->headers_out.charset = charsets[charset].name;
+ r->utf8 = charsets[charset].utf8;
+
+ if (source_charset == NGX_CONF_UNSET || source_charset == charset) {
return ngx_http_next_header_filter(r);
}
-
ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_charset_ctx_t));
if (ctx == NULL) {
return NGX_ERROR;
@@ -202,6 +288,8 @@
ngx_http_set_ctx(r, ctx, ngx_http_charset_filter_module);
+ ctx->table = charsets[source_charset].tables[charset];
+ ctx->charset = charset;
r->filter_need_in_memory = 1;
@@ -212,27 +300,17 @@
static ngx_int_t
ngx_http_charset_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
{
- char *table;
- ngx_chain_t *cl;
- ngx_http_charset_t *charsets;
- ngx_http_charset_ctx_t *ctx;
- ngx_http_charset_loc_conf_t *lcf;
- ngx_http_charset_main_conf_t *mcf;
+ ngx_chain_t *cl;
+ ngx_http_charset_ctx_t *ctx;
ctx = ngx_http_get_module_ctx(r, ngx_http_charset_filter_module);
- if (ctx == NULL) {
+ if (ctx == NULL || ctx->table == NULL) {
return ngx_http_next_body_filter(r, in);
}
- mcf = ngx_http_get_module_main_conf(r, ngx_http_charset_filter_module);
- lcf = ngx_http_get_module_loc_conf(r, ngx_http_charset_filter_module);
-
- charsets = mcf->charsets.elts;
- table = charsets[lcf->source_charset].tables[lcf->charset];
-
for (cl = in; cl; cl = cl->next) {
- ngx_http_charset_recode(cl->buf, table);
+ (void) ngx_http_charset_recode(cl->buf, ctx->table);
}
return ngx_http_next_body_filter(r, in);
@@ -240,21 +318,15 @@
static ngx_uint_t
-ngx_http_charset_recode(ngx_buf_t *b, char *table)
+ngx_http_charset_recode(ngx_buf_t *b, u_char *table)
{
- u_char *p;
- ngx_uint_t change;
-
- change = 0;
+ u_char *p;
for (p = b->pos; p < b->last; p++) {
- if (*p != table[*p]) {
- change = 1;
- break;
- }
- }
- if (change) {
+ if (*p == table[*p]) {
+ continue;
+ }
while (p < b->last) {
*p = table[*p];
@@ -262,9 +334,11 @@
}
b->in_file = 0;
+
+ return 1;
}
- return change;
+ return 0;
}
@@ -330,8 +404,8 @@
}
for (i = 0; i < 128; i++) {
- table->src2dst[i] = (char) i;
- table->dst2src[i] = (char) i;
+ table->src2dst[i] = (u_char) i;
+ table->dst2src[i] = (u_char) i;
}
for (/* void */; i < 256; i++) {
@@ -382,8 +456,8 @@
table = cf->ctx;
- table->src2dst[src] = (char) dst;
- table->dst2src[dst] = (char) src;
+ table->src2dst[src] = (u_char) dst;
+ table->dst2src[dst] = (u_char) src;
return NGX_CONF_OK;
}
@@ -519,6 +593,7 @@
lcf->charset = NGX_CONF_UNSET;
lcf->source_charset = NGX_CONF_UNSET;
+ lcf->override_charset = NGX_CONF_UNSET;
return lcf;
}
@@ -534,6 +609,7 @@
ngx_http_charset_recode_t *recode;
ngx_http_charset_main_conf_t *mcf;
+ ngx_conf_merge_value(conf->override_charset, prev->override_charset, 0);
ngx_conf_merge_value(conf->charset, prev->charset, NGX_HTTP_NO_CHARSET);
if (conf->source_charset == NGX_CONF_UNSET) {
@@ -573,6 +649,7 @@
static ngx_int_t
ngx_http_charset_postconfiguration(ngx_conf_t *cf)
{
+ u_char **src, **dst;
ngx_int_t c;
ngx_uint_t i, t;
ngx_http_charset_t *charset;
@@ -591,21 +668,13 @@
c = recode[i].src;
- charset[c].tables = ngx_pcalloc(cf->pool,
- sizeof(char *) * mcf->charsets.nelts);
- if (charset[c].tables == NULL) {
- return NGX_ERROR;
- }
-
for (t = 0; t < mcf->tables.nelts; t++) {
if (c == tables[t].src && recode[i].dst == tables[t].dst) {
- charset[c].tables[tables[t].dst] = tables[t].src2dst;
goto next;
}
if (c == tables[t].dst && recode[i].dst == tables[t].src) {
- charset[c].tables[tables[t].src] = tables[t].dst2src;
goto next;
}
}
@@ -620,5 +689,34 @@
continue;
}
+
+ for (t = 0; t < mcf->tables.nelts; t++) {
+
+ src = charset[tables[t].src].tables;
+
+ if (src == NULL) {
+ src = ngx_pcalloc(cf->pool, sizeof(u_char *) * mcf->charsets.nelts);
+ if (src == NULL) {
+ return NGX_ERROR;
+ }
+
+ charset[tables[t].src].tables = src;
+ }
+
+ dst = charset[tables[t].dst].tables;
+
+ if (dst == NULL) {
+ dst = ngx_pcalloc(cf->pool, sizeof(u_char *) * mcf->charsets.nelts);
+ if (dst == NULL) {
+ return NGX_ERROR;
+ }
+
+ charset[tables[t].dst].tables = dst;
+ }
+
+ src[tables[t].dst] = tables[t].src2dst;
+ dst[tables[t].src] = tables[t].dst2src;
+ }
+
return NGX_OK;
}
diff --git a/src/http/modules/ngx_http_rewrite_module.c b/src/http/modules/ngx_http_rewrite_module.c
index 5709b56..e3b2edc 100644
--- a/src/http/modules/ngx_http_rewrite_module.c
+++ b/src/http/modules/ngx_http_rewrite_module.c
@@ -16,6 +16,7 @@
ngx_uint_t stack_size;
ngx_flag_t log;
+ ngx_flag_t uninitialized_variable_warn;
} ngx_http_rewrite_loc_conf_t;
@@ -91,13 +92,21 @@
NULL },
{ ngx_string("rewrite_log"),
- NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
- |NGX_CONF_TAKE1,
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF
+ |NGX_HTTP_LIF_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_rewrite_loc_conf_t, log),
NULL },
+ { ngx_string("uninitialized_variable_warn"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF
+ |NGX_HTTP_LIF_CONF|NGX_CONF_FLAG,
+ ngx_conf_set_flag_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_rewrite_loc_conf_t, uninitialized_variable_warn),
+ NULL },
+
ngx_null_command
};
@@ -138,11 +147,11 @@
{
ngx_http_script_code_pt code;
ngx_http_script_engine_t *e;
- ngx_http_rewrite_loc_conf_t *cf;
+ ngx_http_rewrite_loc_conf_t *rlcf;
- cf = ngx_http_get_module_loc_conf(r, ngx_http_rewrite_module);
+ rlcf = ngx_http_get_module_loc_conf(r, ngx_http_rewrite_module);
- if (cf->codes == NULL) {
+ if (rlcf->codes == NULL) {
return NGX_DECLINED;
}
@@ -152,13 +161,13 @@
}
e->sp = ngx_pcalloc(r->pool,
- cf->stack_size * sizeof(ngx_http_variable_value_t));
+ rlcf->stack_size * sizeof(ngx_http_variable_value_t));
if (e->sp == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
- if (cf->captures) {
- e->captures = ngx_palloc(r->pool, cf->captures * sizeof(int));
+ if (rlcf->captures) {
+ e->captures = ngx_palloc(r->pool, rlcf->captures * sizeof(int));
if (e->captures == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
@@ -167,10 +176,10 @@
e->captures = NULL;
}
- e->ip = cf->codes->elts;
+ e->ip = rlcf->codes->elts;
e->request = r;
e->quote = 1;
- e->log = cf->log;
+ e->log = rlcf->log;
e->status = NGX_DECLINED;
while (*(uintptr_t *) e->ip) {
@@ -186,8 +195,16 @@
ngx_http_rewrite_var(ngx_http_request_t *r, ngx_http_variable_value_t *v,
uintptr_t data)
{
- ngx_http_variable_t *var;
- ngx_http_core_main_conf_t *cmcf;
+ ngx_http_variable_t *var;
+ ngx_http_core_main_conf_t *cmcf;
+ ngx_http_rewrite_loc_conf_t *rlcf;
+
+ rlcf = ngx_http_get_module_loc_conf(r, ngx_http_rewrite_module);
+
+ if (rlcf->uninitialized_variable_warn == 0) {
+ *v = ngx_http_variable_null_value;
+ return NGX_OK;
+ }
cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
@@ -199,7 +216,7 @@
* so the handler is called only if the variable is not initialized
*/
- ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+ ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
"using uninitialized \"%V\" variable", &var[data].name);
*v = ngx_http_variable_null_value;
@@ -220,6 +237,7 @@
conf->stack_size = NGX_CONF_UNSET_UINT;
conf->log = NGX_CONF_UNSET;
+ conf->uninitialized_variable_warn = NGX_CONF_UNSET;
return conf;
}
@@ -234,6 +252,8 @@
uintptr_t *code;
ngx_conf_merge_value(conf->log, prev->log, 0);
+ ngx_conf_merge_value(conf->uninitialized_variable_warn,
+ prev->uninitialized_variable_warn, 1);
ngx_conf_merge_unsigned_value(conf->stack_size, prev->stack_size, 10);
if (conf->codes == NULL) {
diff --git a/src/http/modules/ngx_http_ssi_filter_module.c b/src/http/modules/ngx_http_ssi_filter_module.c
index f116634..541b438 100644
--- a/src/http/modules/ngx_http_ssi_filter_module.c
+++ b/src/http/modules/ngx_http_ssi_filter_module.c
@@ -14,6 +14,7 @@
#define NGX_HTTP_SSI_ADD_PREFIX 1
#define NGX_HTTP_SSI_ADD_ZERO 2
+#define NGX_HTTP_SSI_EXPR_TEST 4
typedef struct {
@@ -1502,8 +1503,8 @@
val = ngx_http_ssi_get_variable(r, &var, key);
if (val == NULL) {
- vv = ngx_http_get_variable(r, &var, key);
-
+ vv = ngx_http_get_variable(r, &var, key,
+ flags & NGX_HTTP_SSI_EXPR_TEST);
if (vv == NULL) {
return NGX_ERROR;
}
@@ -1681,7 +1682,7 @@
value = ngx_http_ssi_get_variable(r, var, key);
if (value == NULL) {
- vv = ngx_http_get_variable(r, var, key);
+ vv = ngx_http_get_variable(r, var, key, 1);
if (vv == NULL) {
return NGX_HTTP_SSI_ERROR;
@@ -1873,10 +1874,12 @@
p++;
}
+ flags = (p == last) ? NGX_HTTP_SSI_EXPR_TEST : 0;
+
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"left: \"%V\"", &left);
- if (ngx_http_ssi_evaluate_string(r, ctx, &left, 0) != NGX_OK) {
+ if (ngx_http_ssi_evaluate_string(r, ctx, &left, flags) != NGX_OK) {
return NGX_HTTP_SSI_ERROR;
}
diff --git a/src/http/modules/perl/ngx_http_perl_module.c b/src/http/modules/perl/ngx_http_perl_module.c
index 84de262..198971d 100644
--- a/src/http/modules/perl/ngx_http_perl_module.c
+++ b/src/http/modules/perl/ngx_http_perl_module.c
@@ -188,6 +188,7 @@
r->request_body_in_single_buf = 1;
r->request_body_in_persistent_file = 1;
+ r->request_body_delete_incomplete_file = 1;
rc = ngx_http_read_client_request_body(r, ngx_http_perl_handle_request);
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index 6a08c4b..b897fe1 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -486,8 +486,8 @@
if (r->keepalive && r->headers_in.msie && r->method == NGX_HTTP_POST) {
/*
- * MSIE may wait for some time if the response for the POST request
- * is sent over the keepalive connection
+ * MSIE may wait for some time if the response for
+ * the POST request is sent over the keepalive connection
*/
r->keepalive = 0;
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index c296c94..f47fde3 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -1473,21 +1473,6 @@
&pr->uri, &pr->args);
pr->write_event_handler(pr);
-
-#if 0
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http request: \"%V?%V\" still has postponed",
- &pr->uri, &pr->args);
-
- if (pr->done || pr->postponed->out) {
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http wake parent request: \"%V?%V\"",
- &pr->uri, &pr->args);
-
- pr->write_event_handler(pr);
- }
-#endif
-
}
return;
@@ -1856,7 +1841,8 @@
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay");
if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY,
- (const void *) &tcp_nodelay, sizeof(int)) == -1)
+ (const void *) &tcp_nodelay, sizeof(int))
+ == -1)
{
ngx_connection_error(c, ngx_socket_errno,
"setsockopt(TCP_NODELAY) failed");
diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c
index 2615929..9d300e6 100644
--- a/src/http/ngx_http_variables.c
+++ b/src/http/ngx_http_variables.c
@@ -324,7 +324,8 @@
ngx_http_variable_value_t *
-ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key)
+ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key,
+ ngx_uint_t nowarn)
{
ngx_http_variable_t *v;
ngx_http_variable_value_t *vv;
@@ -377,11 +378,13 @@
return NULL;
}
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "unknown \"%V\" variable", name);
-
vv->not_found = 1;
+ if (nowarn == 0) {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "unknown \"%V\" variable", name);
+ }
+
return vv;
}
diff --git a/src/http/ngx_http_variables.h b/src/http/ngx_http_variables.h
index f3f1fe8..2043a05 100644
--- a/src/http/ngx_http_variables.h
+++ b/src/http/ngx_http_variables.h
@@ -56,7 +56,7 @@
ngx_uint_t index);
ngx_http_variable_value_t *ngx_http_get_variable(ngx_http_request_t *r,
- ngx_str_t *name, ngx_uint_t key);
+ ngx_str_t *name, ngx_uint_t key, ngx_uint_t nowarn);
#define ngx_http_clear_variable(r, index) r->variables0[index].text.data = NULL;
diff --git a/src/http/ngx_http_write_filter_module.c b/src/http/ngx_http_write_filter_module.c
index 5ae24b0..5f6715c 100644
--- a/src/http/ngx_http_write_filter_module.c
+++ b/src/http/ngx_http_write_filter_module.c
@@ -209,9 +209,20 @@
return NGX_ERROR;
}
- to_send = r->limit_rate * (ngx_time() - r->start_time + 1) - c->sent;
+ if (r->limit_rate) {
+ to_send = r->limit_rate * (ngx_time() - r->start_time + 1) - c->sent;
- if (to_send < 0) {
+ if (to_send <= 0) {
+ c->write->delayed = 1;
+ ngx_add_timer(r->connection->write,
+ (ngx_msec_t) (- to_send * 1000 / r->limit_rate));
+
+ c->buffered |= NGX_HTTP_WRITE_BUFFERED;
+
+ return NGX_AGAIN;
+ }
+
+ } else {
to_send = 0;
}