# HG changeset patch
# User Igor Sysoev Core Module
Example Configuration
-user www www;
-worker_processes 2;
-
-error_log /var/log/nginx-error.log info;
-
-events {
- use kqueue;
- worker_connections 2048;
-}
-
-...
-
daemon on
| off
daemon on
main
-Determines whether nginx should become a daemon. -Mainly used during development. -
env VAR
[=VALUE
]
env TZ
main
-Allows to limit a set of environment variables, change their values, -or create new environment variables, for the following cases: -
-The TZ variable is always inherited and made available to the module -ngx_http_perl_module, -unless configured explicitly. -
-Usage example: -
-env MALLOC_OPTIONS; -env PERL5LIB=/data/site/modules; -env OPENSSL_ALLOW_PROXY_CERTS=1; -
include file
| mask
-Includes another file
, or files matching the
-specified mask
, into configuration.
-Included files should consist of
-syntactically correct directives and blocks.
-
-Usage example: -
-include mime.types; -include vhosts/*.conf; -
master_process on
| off
master_process on
main
-Determines whether worker processes are started. -This directive is intended for nginx developers. -
pid file
pid nginx.pid
main
-Defines a file
which will store the process ID of the main process.
-
ssl_engine device
main
-Defines the name of the hardware SSL accelerator. -
user user
[group
]
user nobody nobody
main
-Defines user
and group
-credentials used by worker processes.
-If group
is omitted, a group whose name equals
-that of user
is used.
-
timer_resolution interval
main
-Reduces timer resolution in worker processes, thus reducing the
-number of gettimeofday()
system calls made.
-By default, gettimeofday()
is called each time
-on receiving a kernel event.
-With reduced resolution, gettimeofday()
is only
-called once per specified interval
.
-
-Example: -
-timer_resolution 100ms; -
-An internal implementation of interval depends on the method used: -
EVFILT_TIMER
filter if kqueue
is used;
-timer_create()
if eventport
is used;
-setitimer()
otherwise.
-worker_rlimit_core size
main
-Changes the limit on the largest size of a core file
-(RLIMIT_CORE
) for worker processes.
-Used to increase the limit without restarting the main process.
-
worker_rlimit_nofile number
main
-Changes the limit on the maximum number of open files
-(RLIMIT_NOFILE
) for worker processes.
-Used to increase the limit without restarting the main process.
-
worker_priority number
worker_priority 0
main
-Defines a scheduling priority for worker processes like is
-done by the nice
: a negative
-number
-means higher priority.
-Allowed range normally varies from -20 to 20.
-
-Example: -
-worker_priority -10; -
worker_processes number
worker_processes 1
main
-Defines the number of worker processes. -
working_directory directory
main
-Defines a current working directory for a worker process. -It is primarily used when writing a core-file, in which case -a working process should have write permission for the -specified directory. -
diff --git a/src/core/nginx.h b/src/core/nginx.h --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -8,8 +8,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1001005 -#define NGINX_VERSION "1.1.5" +#define nginx_version 1001006 +#define NGINX_VERSION "1.1.6" #define NGINX_VER "nginx/" NGINX_VERSION #define NGINX_VAR "NGINX" diff --git a/src/core/ngx_parse.c b/src/core/ngx_parse.c --- a/src/core/ngx_parse.c +++ b/src/core/ngx_parse.c @@ -93,7 +93,7 @@ ngx_parse_offset(ngx_str_t *line) ngx_int_t -ngx_parse_time(ngx_str_t *line, ngx_uint_t sec) +ngx_parse_time(ngx_str_t *line, ngx_uint_t is_sec) { u_char *p, *last; ngx_int_t value, total, scale; @@ -114,8 +114,8 @@ ngx_parse_time(ngx_str_t *line, ngx_uint valid = 0; value = 0; total = 0; - step = sec ? st_start : st_month; - scale = sec ? 1 : 1000; + step = is_sec ? st_start : st_month; + scale = is_sec ? 1 : 1000; p = line->data; last = p + line->len; @@ -135,81 +135,81 @@ ngx_parse_time(ngx_str_t *line, ngx_uint return NGX_ERROR; } step = st_year; - max = 68; + max = NGX_MAX_INT32_VALUE / (60 * 60 * 24 * 365); scale = 60 * 60 * 24 * 365; break; case 'M': - if (step > st_year) { + if (step >= st_month) { return NGX_ERROR; } step = st_month; - max = 828; + max = NGX_MAX_INT32_VALUE / (60 * 60 * 24 * 30); scale = 60 * 60 * 24 * 30; break; case 'w': - if (step > st_month) { + if (step >= st_week) { return NGX_ERROR; } step = st_week; - max = 3550; + max = NGX_MAX_INT32_VALUE / (60 * 60 * 24 * 7); scale = 60 * 60 * 24 * 7; break; case 'd': - if (step > st_week) { + if (step >= st_day) { return NGX_ERROR; } step = st_day; - max = 24855; + max = NGX_MAX_INT32_VALUE / (60 * 60 * 24); scale = 60 * 60 * 24; break; case 'h': - if (step > st_day) { + if (step >= st_hour) { return NGX_ERROR; } step = st_hour; - max = 596523; + max = NGX_MAX_INT32_VALUE / (60 * 60); scale = 60 * 60; break; case 'm': if (*p == 's') { - if (sec || step > st_sec) { + if (is_sec || step >= st_msec) { return NGX_ERROR; } p++; step = st_msec; - max = 2147483647; + max = NGX_MAX_INT32_VALUE; scale = 1; break; } - if (step > st_hour) { + if (step >= st_min) { return NGX_ERROR; } step = st_min; - max = 35791394; + max = NGX_MAX_INT32_VALUE / 60; scale = 60; break; case 's': - if (step > st_min) { + if (step >= st_sec) { return NGX_ERROR; } step = st_sec; - max = 2147483647; + max = NGX_MAX_INT32_VALUE; scale = 1; break; case ' ': - if (step > st_min) { + if (step >= st_sec) { return NGX_ERROR; } step = st_last; - max = 2147483647; + max = NGX_MAX_INT32_VALUE; scale = 1; break; @@ -217,7 +217,7 @@ ngx_parse_time(ngx_str_t *line, ngx_uint return NGX_ERROR; } - if (step != st_msec && !sec) { + if (step != st_msec && !is_sec) { scale *= 1000; max /= 1000; } @@ -228,12 +228,12 @@ ngx_parse_time(ngx_str_t *line, ngx_uint total += value * scale; - if ((ngx_uint_t) total > 2147483647) { + if ((ngx_uint_t) total > NGX_MAX_INT32_VALUE) { return NGX_ERROR; } value = 0; - scale = sec ? 1 : 1000; + scale = is_sec ? 1 : 1000; while (p < last && *p == ' ') { p++; diff --git a/src/core/ngx_parse.h b/src/core/ngx_parse.h --- a/src/core/ngx_parse.h +++ b/src/core/ngx_parse.h @@ -17,7 +17,7 @@ ssize_t ngx_parse_size(ngx_str_t *line); off_t ngx_parse_offset(ngx_str_t *line); -ngx_int_t ngx_parse_time(ngx_str_t *line, ngx_uint_t sec); +ngx_int_t ngx_parse_time(ngx_str_t *line, ngx_uint_t is_sec); #endif /* _NGX_PARSE_H_INCLUDED_ */ diff --git a/src/core/ngx_string.c b/src/core/ngx_string.c --- a/src/core/ngx_string.c +++ b/src/core/ngx_string.c @@ -1211,19 +1211,19 @@ ngx_utf8_decode(u_char **p, size_t n) u = **p; - if (u > 0xf0) { + if (u >= 0xf0) { u &= 0x07; valid = 0xffff; len = 3; - } else if (u > 0xe0) { + } else if (u >= 0xe0) { u &= 0x0f; valid = 0x7ff; len = 2; - } else if (u > 0xc0) { + } else if (u >= 0xc2) { u &= 0x1f; valid = 0x7f; @@ -1380,6 +1380,26 @@ ngx_escape_uri(u_char *dst, u_char *src, 0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */ }; + /* not ALPHA, DIGIT, "-", ".", "_", "~" */ + + static uint32_t uri_component[] = { + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + + /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */ + 0xfc009fff, /* 1111 1100 0000 0000 1001 1111 1111 1111 */ + + /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */ + 0x78000001, /* 0111 1000 0000 0000 0000 0000 0000 0001 */ + + /* ~}| {zyx wvut srqp onml kjih gfed cba` */ + 0xb8000001, /* 1011 1000 0000 0000 0000 0000 0000 0001 */ + + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + }; + /* " ", "#", """, "%", "'", %00-%1F, %7F-%FF */ static uint32_t html[] = { @@ -1443,7 +1463,7 @@ ngx_escape_uri(u_char *dst, u_char *src, /* mail_auth is the same as memcached */ static uint32_t *map[] = - { uri, args, html, refresh, memcached, memcached }; + { uri, args, uri_component, html, refresh, memcached, memcached }; escape = map[type]; diff --git a/src/core/ngx_string.h b/src/core/ngx_string.h --- a/src/core/ngx_string.h +++ b/src/core/ngx_string.h @@ -189,12 +189,13 @@ size_t ngx_utf8_length(u_char *p, size_t u_char *ngx_utf8_cpystrn(u_char *dst, u_char *src, size_t n, size_t len); -#define NGX_ESCAPE_URI 0 -#define NGX_ESCAPE_ARGS 1 -#define NGX_ESCAPE_HTML 2 -#define NGX_ESCAPE_REFRESH 3 -#define NGX_ESCAPE_MEMCACHED 4 -#define NGX_ESCAPE_MAIL_AUTH 5 +#define NGX_ESCAPE_URI 0 +#define NGX_ESCAPE_ARGS 1 +#define NGX_ESCAPE_URI_COMPONENT 2 +#define NGX_ESCAPE_HTML 3 +#define NGX_ESCAPE_REFRESH 4 +#define NGX_ESCAPE_MEMCACHED 5 +#define NGX_ESCAPE_MAIL_AUTH 6 #define NGX_UNESCAPE_URI 1 #define NGX_UNESCAPE_REDIRECT 2 diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -175,6 +175,14 @@ ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_ SSL_CTX_set_options(ssl->ctx, ngx_ssl_protocols[protocols >> 1]); } +#ifdef SSL_OP_NO_COMPRESSION + SSL_CTX_set_options(ssl->ctx, SSL_OP_NO_COMPRESSION); +#endif + +#ifdef SSL_MODE_RELEASE_BUFFERS + SSL_CTX_set_mode(ssl->ctx, SSL_MODE_RELEASE_BUFFERS); +#endif + SSL_CTX_set_read_ahead(ssl->ctx, 1); SSL_CTX_set_info_callback(ssl->ctx, ngx_ssl_info_callback); diff --git a/src/http/modules/ngx_http_autoindex_module.c b/src/http/modules/ngx_http_autoindex_module.c --- a/src/http/modules/ngx_http_autoindex_module.c +++ b/src/http/modules/ngx_http_autoindex_module.c @@ -26,9 +26,9 @@ typedef struct { ngx_str_t name; size_t utf_len; size_t escape; + size_t escape_html; unsigned dir:1; - unsigned colon:1; time_t mtime; off_t size; @@ -138,7 +138,7 @@ ngx_http_autoindex_handler(ngx_http_requ { u_char *last, *filename, scale; off_t length; - size_t len, utf_len, allocated, root; + size_t len, char_len, escape_html, allocated, root; ngx_tm_t tm; ngx_err_t err; ngx_buf_t *b; @@ -338,7 +338,10 @@ ngx_http_autoindex_handler(ngx_http_requ ngx_cpystrn(entry->name.data, ngx_de_name(&dir), len + 1); entry->escape = 2 * ngx_escape_uri(NULL, ngx_de_name(&dir), len, - NGX_ESCAPE_HTML); + NGX_ESCAPE_URI_COMPONENT); + + entry->escape_html = ngx_escape_html(NULL, entry->name.data, + entry->name.len); if (utf8) { entry->utf_len = ngx_utf8_length(entry->name.data, entry->name.len); @@ -346,8 +349,6 @@ ngx_http_autoindex_handler(ngx_http_requ entry->utf_len = len; } - entry->colon = (ngx_strchr(entry->name.data, ':') != NULL); - entry->dir = ngx_de_is_dir(&dir); entry->mtime = ngx_de_mtime(&dir); entry->size = ngx_de_size(&dir); @@ -358,10 +359,12 @@ ngx_http_autoindex_handler(ngx_http_requ ngx_close_dir_n " \"%s\" failed", &path); } + escape_html = ngx_escape_html(NULL, r->uri.data, r->uri.len); + len = sizeof(title) - 1 - + r->uri.len + + r->uri.len + escape_html + sizeof(header) - 1 - + r->uri.len + + r->uri.len + escape_html + sizeof("") - 1 + sizeof("../" CRLF) - 1 + sizeof("
../" CRLF, @@ -406,14 +419,9 @@ ngx_http_autoindex_handler(ngx_http_requ for (i = 0; i < entries.nelts; i++) { b->last = ngx_cpymem(b->last, "last++ = '.'; - *b->last++ = '/'; - } - if (entry[i].escape) { ngx_escape_uri(b->last, entry[i].name.data, entry[i].name.len, - NGX_ESCAPE_HTML); + NGX_ESCAPE_URI_COMPONENT); b->last += entry[i].name.len + entry[i].escape; @@ -433,20 +441,41 @@ ngx_http_autoindex_handler(ngx_http_requ if (entry[i].name.len != len) { if (len > NGX_HTTP_AUTOINDEX_NAME_LEN) { - utf_len = NGX_HTTP_AUTOINDEX_NAME_LEN - 3 + 1; + char_len = NGX_HTTP_AUTOINDEX_NAME_LEN - 3 + 1; } else { - utf_len = NGX_HTTP_AUTOINDEX_NAME_LEN + 1; + char_len = NGX_HTTP_AUTOINDEX_NAME_LEN + 1; } + last = b->last; b->last = ngx_utf8_cpystrn(b->last, entry[i].name.data, - utf_len, entry[i].name.len + 1); + char_len, entry[i].name.len + 1); + + if (entry[i].escape_html) { + b->last = (u_char *) ngx_escape_html(last, entry[i].name.data, + b->last - last); + } + last = b->last; } else { - b->last = ngx_cpystrn(b->last, entry[i].name.data, - NGX_HTTP_AUTOINDEX_NAME_LEN + 1); - last = b->last - 3; + if (entry[i].escape_html) { + if (len > NGX_HTTP_AUTOINDEX_NAME_LEN) { + char_len = NGX_HTTP_AUTOINDEX_NAME_LEN - 3; + + } else { + char_len = len; + } + + b->last = (u_char *) ngx_escape_html(b->last, + entry[i].name.data, char_len); + last = b->last; + + } else { + b->last = ngx_cpystrn(b->last, entry[i].name.data, + NGX_HTTP_AUTOINDEX_NAME_LEN + 1); + last = b->last - 3; + } } if (len > NGX_HTTP_AUTOINDEX_NAME_LEN) { diff --git a/src/http/modules/ngx_http_log_module.c b/src/http/modules/ngx_http_log_module.c --- a/src/http/modules/ngx_http_log_module.c +++ b/src/http/modules/ngx_http_log_module.c @@ -690,12 +690,12 @@ ngx_http_log_escape(u_char *dst, u_char 0x10000000, /* 0001 0000 0000 0000 0000 0000 0000 0000 */ /* ~}| {zyx wvut srqp onml kjih gfed cba` */ - 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ + 0x80000000, /* 1000 0000 0000 0000 0000 0000 0000 0000 */ - 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ - 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ - 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ - 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ }; diff --git a/src/http/modules/ngx_http_mp4_module.c b/src/http/modules/ngx_http_mp4_module.c --- a/src/http/modules/ngx_http_mp4_module.c +++ b/src/http/modules/ngx_http_mp4_module.c @@ -1882,7 +1882,7 @@ ngx_http_mp4_update_stts_atom(ngx_http_m } entries = trak->time_to_sample_entries; - start_time = mp4->start * trak->timescale / 1000; + start_time = (uint64_t) mp4->start * trak->timescale / 1000; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "time-to-sample start_time:%uL", start_time); diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -1560,7 +1560,7 @@ ngx_http_proxy_copy_filter(ngx_event_pip p->upstream_done = 1; ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, - "upstream sent too many data"); + "upstream sent too much data"); } return NGX_OK; diff --git a/src/http/modules/ngx_http_rewrite_module.c b/src/http/modules/ngx_http_rewrite_module.c --- a/src/http/modules/ngx_http_rewrite_module.c +++ b/src/http/modules/ngx_http_rewrite_module.c @@ -135,10 +135,22 @@ ngx_module_t ngx_http_rewrite_module = static ngx_int_t ngx_http_rewrite_handler(ngx_http_request_t *r) { + ngx_int_t index; ngx_http_script_code_pt code; ngx_http_script_engine_t *e; + ngx_http_core_srv_conf_t *cscf; + ngx_http_core_main_conf_t *cmcf; ngx_http_rewrite_loc_conf_t *rlcf; + cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); + cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); + index = cmcf->phase_engine.location_rewrite_index; + + if (r->phase_handler == index && r->loc_conf == cscf->ctx->loc_conf) { + /* skipping location rewrite phase for server null location */ + return NGX_DECLINED; + } + rlcf = ngx_http_get_module_loc_conf(r, ngx_http_rewrite_module); if (rlcf->codes == NULL) { diff --git a/src/http/modules/ngx_http_static_module.c b/src/http/modules/ngx_http_static_module.c --- a/src/http/modules/ngx_http_static_module.c +++ b/src/http/modules/ngx_http_static_module.c @@ -139,6 +139,8 @@ ngx_http_static_handler(ngx_http_request ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "http dir"); + ngx_http_clear_location(r); + r->headers_out.location = ngx_palloc(r->pool, sizeof(ngx_table_elt_t)); if (r->headers_out.location == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; diff --git a/src/http/modules/ngx_http_upstream_ip_hash_module.c b/src/http/modules/ngx_http_upstream_ip_hash_module.c --- a/src/http/modules/ngx_http_upstream_ip_hash_module.c +++ b/src/http/modules/ngx_http_upstream_ip_hash_module.c @@ -185,8 +185,8 @@ ngx_http_upstream_get_ip_hash_peer(ngx_p break; } - if (now - peer->accessed > peer->fail_timeout) { - peer->fails = 0; + if (now - peer->checked > peer->fail_timeout) { + peer->checked = now; break; } } diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm --- a/src/http/modules/perl/nginx.pm +++ b/src/http/modules/perl/nginx.pm @@ -48,7 +48,7 @@ our @EXPORT = qw( HTTP_INSUFFICIENT_STORAGE ); -our $VERSION = '1.1.5'; +our $VERSION = '1.1.6'; require XSLoader; XSLoader::load('nginx', $VERSION); diff --git a/src/http/modules/perl/nginx.xs b/src/http/modules/perl/nginx.xs --- a/src/http/modules/perl/nginx.xs +++ b/src/http/modules/perl/nginx.xs @@ -474,6 +474,13 @@ header_out(r, key, value) r->headers_out.content_length = header; } + if (header->key.len == sizeof("Content-Encoding") - 1 + && ngx_strncasecmp(header->key.data, "Content-Encoding", + sizeof("Content-Encoding") - 1) == 0) + { + r->headers_out.content_encoding = header; + } + void filename(r) @@ -836,7 +843,7 @@ variable(r, name, value = NULL) var.len = len; var.data = lowcase; - #if (NGX_LOG_DEBUG) + #if (NGX_DEBUG) if (value) { ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, diff --git a/src/http/ngx_http_copy_filter_module.c b/src/http/ngx_http_copy_filter_module.c --- a/src/http/ngx_http_copy_filter_module.c +++ b/src/http/ngx_http_copy_filter_module.c @@ -158,6 +158,11 @@ ngx_http_copy_filter(ngx_http_request_t ngx_file_t *file; ngx_http_ephemeral_t *e; + if (r->aio) { + c->busy_sendfile = NULL; + return rc; + } + file = c->busy_sendfile->file; offset = c->busy_sendfile->file_pos; diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -983,6 +983,8 @@ ngx_http_core_find_config_phase(ngx_http } if (rc == NGX_DONE) { + ngx_http_clear_location(r); + r->headers_out.location = ngx_list_push(&r->headers_out.headers); if (r->headers_out.location == NULL) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); @@ -1796,6 +1798,8 @@ ngx_http_send_response(ngx_http_request_ if (status >= NGX_HTTP_MOVED_PERMANENTLY && status <= NGX_HTTP_SEE_OTHER) { + ngx_http_clear_location(r); + r->headers_out.location = ngx_list_push(&r->headers_out.headers); if (r->headers_out.location == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; @@ -2542,6 +2546,9 @@ ngx_http_named_location(ngx_http_request r->content_handler = NULL; r->loc_conf = (*clcfp)->loc_conf; + /* clear the modules contexts */ + ngx_memzero(r->ctx, sizeof(void *) * ngx_http_max_module); + ngx_http_update_location_config(r); cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); @@ -2994,6 +3001,12 @@ ngx_http_core_type(ngx_conf_t *cf, ngx_c value = cf->args->elts; if (ngx_strcmp(value[0].data, "include") == 0) { + if (cf->args->nelts != 2) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid number of arguments" + " in \"include\" directive"); + return NGX_CONF_ERROR; + } file = value[1]; if (ngx_conf_full_name(cf->cycle, &file, 1) != NGX_OK) { @@ -3027,7 +3040,7 @@ ngx_http_core_type(ngx_conf_t *cf, ngx_c "content type: \"%V\", " "previous content type: \"%V\"", &value[i], content_type, old); - continue; + goto next; } } @@ -3040,6 +3053,9 @@ ngx_http_core_type(ngx_conf_t *cf, ngx_c type->key = value[i]; type->key_hash = hash; type->value = content_type; + + next: + continue; } return NGX_CONF_OK; @@ -3373,7 +3389,7 @@ ngx_http_core_merge_loc_conf(ngx_conf_t ngx_cacheline_size); /* - * the special handling the "types" directive in the "http" section + * the special handling of the "types" directive in the "http" section * to inherit the http's conf->types_hash to all servers */ @@ -3400,7 +3416,7 @@ ngx_http_core_merge_loc_conf(ngx_conf_t } if (conf->types == NULL) { - conf->types = ngx_array_create(cf->pool, 4, sizeof(ngx_hash_key_t)); + conf->types = ngx_array_create(cf->pool, 3, sizeof(ngx_hash_key_t)); if (conf->types == NULL) { return NGX_CONF_ERROR; } @@ -3425,7 +3441,7 @@ ngx_http_core_merge_loc_conf(ngx_conf_t types_hash.key = ngx_hash_key_lc; types_hash.max_size = conf->types_hash_max_size; types_hash.bucket_size = conf->types_hash_bucket_size; - types_hash.name = "mime_types_hash"; + types_hash.name = "types_hash"; types_hash.pool = cf->pool; types_hash.temp_pool = NULL; @@ -3467,9 +3483,10 @@ ngx_http_core_merge_loc_conf(ngx_conf_t ngx_conf_merge_uint_value(conf->if_modified_since, prev->if_modified_since, NGX_HTTP_IMS_EXACT); ngx_conf_merge_uint_value(conf->max_ranges, prev->max_ranges, - 0x7fffffff); + NGX_MAX_INT32_VALUE); ngx_conf_merge_uint_value(conf->client_body_in_file_only, - prev->client_body_in_file_only, 0); + prev->client_body_in_file_only, + NGX_HTTP_REQUEST_BODY_FILE_OFF); ngx_conf_merge_value(conf->client_body_in_single_buffer, prev->client_body_in_single_buffer, 0); ngx_conf_merge_value(conf->internal, prev->internal, 0); @@ -3477,11 +3494,11 @@ ngx_http_core_merge_loc_conf(ngx_conf_t ngx_conf_merge_size_value(conf->sendfile_max_chunk, prev->sendfile_max_chunk, 0); #if (NGX_HAVE_FILE_AIO) - ngx_conf_merge_value(conf->aio, prev->aio, 0); + ngx_conf_merge_value(conf->aio, prev->aio, NGX_HTTP_AIO_OFF); #endif ngx_conf_merge_size_value(conf->read_ahead, prev->read_ahead, 0); ngx_conf_merge_off_value(conf->directio, prev->directio, - NGX_MAX_OFF_T_VALUE); + NGX_OPEN_FILE_DIRECTIO_OFF); ngx_conf_merge_off_value(conf->directio_alignment, prev->directio_alignment, 512); ngx_conf_merge_value(conf->tcp_nopush, prev->tcp_nopush, 0); @@ -3839,13 +3856,6 @@ ngx_http_core_server_name(ngx_conf_t *cf &value[i]); } - if (value[i].len == 1 && ch == '*') { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "\"server_name *\" is unsupported, use " - "\"server_name_in_redirect off\" instead"); - return NGX_CONF_ERROR; - } - sn = ngx_array_push(&cscf->server_names); if (sn == NULL) { return NGX_CONF_ERROR; diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h --- a/src/http/ngx_http_core_module.h +++ b/src/http/ngx_http_core_module.h @@ -529,5 +529,12 @@ extern ngx_str_t ngx_http_core_get_meth r->headers_out.last_modified = NULL; \ } +#define ngx_http_clear_location(r) \ + \ + if (r->headers_out.location) { \ + r->headers_out.location->hash = 0; \ + r->headers_out.location = NULL; \ + } + #endif /* _NGX_HTTP_CORE_H_INCLUDED_ */ diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -2248,17 +2248,17 @@ ngx_http_writer(ngx_http_request_t *r) return; } - } else { - if (wev->delayed || r->aio) { - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0, - "http writer delayed"); - - if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) { - ngx_http_close_request(r, 0); - } - - return; + } + + if (wev->delayed || r->aio) { + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0, + "http writer delayed"); + + if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) { + ngx_http_close_request(r, 0); } + + return; } rc = ngx_http_output_filter(r, NULL); @@ -2274,7 +2274,7 @@ ngx_http_writer(ngx_http_request_t *r) if (r->buffered || r->postponed || (r == r->main && c->buffered)) { - if (!wev->ready && !wev->delayed) { + if (!wev->delayed) { ngx_add_timer(wev, clcf->send_timeout); } diff --git a/src/http/ngx_http_script.c b/src/http/ngx_http_script.c --- a/src/http/ngx_http_script.c +++ b/src/http/ngx_http_script.c @@ -1106,6 +1106,8 @@ ngx_http_script_regex_end_code(ngx_http_ "rewritten redirect: \"%V\"", &e->buf); } + ngx_http_clear_location(r); + r->headers_out.location = ngx_list_push(&r->headers_out.headers); if (r->headers_out.location == NULL) { e->ip = ngx_http_script_exit; diff --git a/src/http/ngx_http_special_response.c b/src/http/ngx_http_special_response.c --- a/src/http/ngx_http_special_response.c +++ b/src/http/ngx_http_special_response.c @@ -375,7 +375,7 @@ ngx_http_special_response_handler(ngx_ht } } - if (r->lingering_close == 1) { + if (r->lingering_close) { switch (error) { case NGX_HTTP_BAD_REQUEST: case NGX_HTTP_TO_HTTPS: @@ -582,6 +582,8 @@ ngx_http_send_error_page(ngx_http_reques ngx_str_set(&location->key, "Location"); location->value = uri; + ngx_http_clear_location(r); + r->headers_out.location = location; clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -369,6 +369,9 @@ ngx_conf_bitmask_t ngx_http_upstream_ca ngx_conf_bitmask_t ngx_http_upstream_ignore_headers_masks[] = { { ngx_string("X-Accel-Redirect"), NGX_HTTP_UPSTREAM_IGN_XA_REDIRECT }, { ngx_string("X-Accel-Expires"), NGX_HTTP_UPSTREAM_IGN_XA_EXPIRES }, + { ngx_string("X-Accel-Limit-Rate"), NGX_HTTP_UPSTREAM_IGN_XA_LIMIT_RATE }, + { ngx_string("X-Accel-Buffering"), NGX_HTTP_UPSTREAM_IGN_XA_BUFFERING }, + { ngx_string("X-Accel-Charset"), NGX_HTTP_UPSTREAM_IGN_XA_CHARSET }, { ngx_string("Expires"), NGX_HTTP_UPSTREAM_IGN_EXPIRES }, { ngx_string("Cache-Control"), NGX_HTTP_UPSTREAM_IGN_CACHE_CONTROL }, { ngx_string("Set-Cookie"), NGX_HTTP_UPSTREAM_IGN_SET_COOKIE }, @@ -999,7 +1002,7 @@ ngx_http_upstream_check_broken_connectio if (!u->cacheable && u->peer.connection) { ngx_log_error(NGX_LOG_INFO, ev->log, ev->kq_errno, - "kevent() reported that client closed prematurely " + "kevent() reported that client prematurely closed " "connection, so upstream connection is closed too"); ngx_http_upstream_finalize_request(r, u, NGX_HTTP_CLIENT_CLOSED_REQUEST); @@ -1007,8 +1010,8 @@ ngx_http_upstream_check_broken_connectio } ngx_log_error(NGX_LOG_INFO, ev->log, ev->kq_errno, - "kevent() reported that client closed " - "prematurely connection"); + "kevent() reported that client prematurely closed " + "connection"); if (u->peer.connection == NULL) { ngx_http_upstream_finalize_request(r, u, @@ -1062,7 +1065,7 @@ ngx_http_upstream_check_broken_connectio if (!u->cacheable && u->peer.connection) { ngx_log_error(NGX_LOG_INFO, ev->log, err, - "client closed prematurely connection, " + "client prematurely closed connection, " "so upstream connection is closed too"); ngx_http_upstream_finalize_request(r, u, NGX_HTTP_CLIENT_CLOSED_REQUEST); @@ -1070,7 +1073,7 @@ ngx_http_upstream_check_broken_connectio } ngx_log_error(NGX_LOG_INFO, ev->log, err, - "client closed prematurely connection"); + "client prematurely closed connection"); if (u->peer.connection == NULL) { ngx_http_upstream_finalize_request(r, u, @@ -3328,9 +3331,15 @@ static ngx_int_t ngx_http_upstream_process_limit_rate(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset) { - ngx_int_t n; - - r->upstream->headers_in.x_accel_limit_rate = h; + ngx_int_t n; + ngx_http_upstream_t *u; + + u = r->upstream; + u->headers_in.x_accel_limit_rate = h; + + if (u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_XA_LIMIT_RATE) { + return NGX_OK; + } n = ngx_atoi(h->value.data, h->value.len); @@ -3346,16 +3355,23 @@ static ngx_int_t ngx_http_upstream_process_buffering(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset) { - u_char c0, c1, c2; - - if (r->upstream->conf->change_buffering) { + u_char c0, c1, c2; + ngx_http_upstream_t *u; + + u = r->upstream; + + if (u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_XA_BUFFERING) { + return NGX_OK; + } + + if (u->conf->change_buffering) { if (h->value.len == 2) { c0 = ngx_tolower(h->value.data[0]); c1 = ngx_tolower(h->value.data[1]); if (c0 == 'n' && c1 == 'o') { - r->upstream->buffering = 0; + u->buffering = 0; } } else if (h->value.len == 3) { @@ -3364,7 +3380,7 @@ ngx_http_upstream_process_buffering(ngx_ c2 = ngx_tolower(h->value.data[2]); if (c0 == 'y' && c1 == 'e' && c2 == 's') { - r->upstream->buffering = 1; + u->buffering = 1; } } } @@ -3377,6 +3393,10 @@ static ngx_int_t ngx_http_upstream_process_charset(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset) { + if (r->upstream->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_XA_CHARSET) { + return NGX_OK; + } + r->headers_out.override_charset = &h->value; return NGX_OK; diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h --- a/src/http/ngx_http_upstream.h +++ b/src/http/ngx_http_upstream.h @@ -44,6 +44,9 @@ #define NGX_HTTP_UPSTREAM_IGN_EXPIRES 0x00000008 #define NGX_HTTP_UPSTREAM_IGN_CACHE_CONTROL 0x00000010 #define NGX_HTTP_UPSTREAM_IGN_SET_COOKIE 0x00000020 +#define NGX_HTTP_UPSTREAM_IGN_XA_LIMIT_RATE 0x00000040 +#define NGX_HTTP_UPSTREAM_IGN_XA_BUFFERING 0x00000080 +#define NGX_HTTP_UPSTREAM_IGN_XA_CHARSET 0x00000100 typedef struct { diff --git a/src/http/ngx_http_upstream_round_robin.c b/src/http/ngx_http_upstream_round_robin.c --- a/src/http/ngx_http_upstream_round_robin.c +++ b/src/http/ngx_http_upstream_round_robin.c @@ -443,8 +443,8 @@ ngx_http_upstream_get_round_robin_peer(n break; } - if (now - peer->accessed > peer->fail_timeout) { - peer->fails = 0; + if (now - peer->checked > peer->fail_timeout) { + peer->checked = now; break; } @@ -491,8 +491,8 @@ ngx_http_upstream_get_round_robin_peer(n break; } - if (now - peer->accessed > peer->fail_timeout) { - peer->fails = 0; + if (now - peer->checked > peer->fail_timeout) { + peer->checked = now; break; } @@ -663,15 +663,16 @@ ngx_http_upstream_free_round_robin_peer( return; } + peer = &rrp->peers->peer[rrp->current]; + if (state & NGX_PEER_FAILED) { now = ngx_time(); - peer = &rrp->peers->peer[rrp->current]; - /* ngx_lock_mutex(rrp->peers->mutex); */ peer->fails++; peer->accessed = now; + peer->checked = now; if (peer->max_fails) { peer->current_weight -= peer->weight / peer->max_fails; @@ -686,6 +687,14 @@ ngx_http_upstream_free_round_robin_peer( } /* ngx_unlock_mutex(rrp->peers->mutex); */ + + } else { + + /* mark peer live if check passed */ + + if (peer->accessed < peer->checked) { + peer->fails = 0; + } } rrp->current++; diff --git a/src/http/ngx_http_upstream_round_robin.h b/src/http/ngx_http_upstream_round_robin.h --- a/src/http/ngx_http_upstream_round_robin.h +++ b/src/http/ngx_http_upstream_round_robin.h @@ -23,6 +23,7 @@ typedef struct { ngx_uint_t fails; time_t accessed; + time_t checked; ngx_uint_t max_fails; time_t fail_timeout;