# HG changeset patch # User Igor Sysoev # Date 1258318800 -10800 # Node ID e19e5f54287869c93f4dc51035231772e5dca61c # Parent 91e4b06e1a016648d2294b6e9cceaebbed1639b1 nginx 0.8.25 *) Change: now no message is written in an error log if a variable is not found by $r->variable() method. *) Feature: the ngx_http_degradation_module. *) Feature: regular expression named captures. *) Feature: now URI part is not required a "proxy_pass" directive if variables are used. *) Feature: now the "msie_padding" directive works for Chrome too. *) Bugfix: a segmentation fault occurred in a worker process on low memory condition; the bug had appeared in 0.8.18. *) Bugfix: nginx sent gzipped responses to clients those do not support gzip, if "gzip_static on" and "gzip_vary off"; the bug had appeared in 0.8.16. diff --git a/CHANGES b/CHANGES --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,26 @@ +Changes with nginx 0.8.25 16 Nov 2009 + + *) Change: now no message is written in an error log if a variable is + not found by $r->variable() method. + + *) Feature: the ngx_http_degradation_module. + + *) Feature: regular expression named captures. + + *) Feature: now URI part is not required a "proxy_pass" directive if + variables are used. + + *) Feature: now the "msie_padding" directive works for Chrome too. + + *) Bugfix: a segmentation fault occurred in a worker process on low + memory condition; the bug had appeared in 0.8.18. + + *) Bugfix: nginx sent gzipped responses to clients those do not support + gzip, if "gzip_static on" and "gzip_vary off"; the bug had appeared + in 0.8.16. + + Changes with nginx 0.8.24 11 Nov 2009 *) Bugfix: nginx always added "Content-Encoding: gzip" response header diff --git a/CHANGES.ru b/CHANGES.ru --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,4 +1,26 @@ +Изменения в nginx 0.8.25 16.11.2009 + + *) Изменение: теперь в лог ошибок не пишется сообщение, если переменная + не найдена с помощью метода $r->variable(). + + *) Добавление: модуль ngx_http_degradation_module. + + *) Добавление: именованные выделения в регулярных выражениях. + + *) Добавление: теперь при использовании переменных в директиве + proxy_pass не требуется задавать URI. + + *) Добавление: теперь директива msie_padding работает и для Chrome. + + *) Исправление: в рабочем процессе происходил segmentation fault при + недостатке памяти; ошибка появилась в 0.8.18. + + *) Исправление: nginx передавал сжатые ответы клиентам, не + поддерживающим сжатие при настройках gzip_static on и gzip_vary off; + ошибка появилась в 0.8.16. + + Изменения в nginx 0.8.24 11.11.2009 *) Исправление: nginx всегда добавлял строку "Content-Encoding: gzip" в diff --git a/auto/modules b/auto/modules --- a/auto/modules +++ b/auto/modules @@ -316,6 +316,11 @@ if [ $HTTP_SECURE_LINK = YES ]; then HTTP_SRCS="$HTTP_SRCS $HTTP_SECURE_LINK_SRCS" fi +if [ $HTTP_DEGRADATION = YES ]; then + HTTP_MODULES="$HTTP_MODULES $HTTP_DEGRADATION_MODULE" + HTTP_SRCS="$HTTP_SRCS $HTTP_DEGRADATION_SRCS" +fi + if [ $HTTP_FLV = YES ]; then HTTP_MODULES="$HTTP_MODULES $HTTP_FLV_MODULE" HTTP_SRCS="$HTTP_SRCS $HTTP_FLV_SRCS" diff --git a/auto/options b/auto/options --- a/auto/options +++ b/auto/options @@ -85,6 +85,7 @@ HTTP_LIMIT_REQ=YES HTTP_EMPTY_GIF=YES HTTP_BROWSER=YES HTTP_SECURE_LINK=NO +HTTP_DEGRADATION=NO HTTP_FLV=NO HTTP_GZIP_STATIC=NO HTTP_UPSTREAM_IP_HASH=YES @@ -194,6 +195,7 @@ do --with-http_gzip_static_module) HTTP_GZIP_STATIC=YES ;; --with-http_random_index_module) HTTP_RANDOM_INDEX=YES ;; --with-http_secure_link_module) HTTP_SECURE_LINK=YES ;; + --with-http_degradation_module) HTTP_DEGRADATION=YES ;; --without-http_charset_module) HTTP_CHARSET=NO ;; --without-http_gzip_module) HTTP_GZIP=NO ;; @@ -322,6 +324,7 @@ cat << END --with-http_gzip_static_module enable ngx_http_gzip_static_module --with-http_random_index_module enable ngx_http_random_index_module --with-http_secure_link_module enable ngx_http_secure_link_module + --with-http_degradation_module enable ngx_http_degradation_module --with-http_stub_status_module enable ngx_http_stub_status_module --without-http_charset_module disable ngx_http_charset_module diff --git a/auto/sources b/auto/sources --- a/auto/sources +++ b/auto/sources @@ -438,6 +438,10 @@ HTTP_SECURE_LINK_MODULE=ngx_http_secure_ HTTP_SECURE_LINK_SRCS=src/http/modules/ngx_http_secure_link_module.c +HTTP_DEGRADATION_MODULE=ngx_http_degradation_module +HTTP_DEGRADATION_SRCS=src/http/modules/ngx_http_degradation_module.c + + HTTP_FLV_MODULE=ngx_http_flv_module HTTP_FLV_SRCS=src/http/modules/ngx_http_flv_module.c 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 8024 -#define NGINX_VERSION "0.8.24" +#define nginx_version 8025 +#define NGINX_VERSION "0.8.25" #define NGINX_VER "nginx/" NGINX_VERSION #define NGINX_VAR "NGINX" diff --git a/src/core/ngx_core.h b/src/core/ngx_core.h --- a/src/core/ngx_core.h +++ b/src/core/ngx_core.h @@ -83,7 +83,9 @@ typedef void (*ngx_connection_handler_pt #define CRLF "\x0d\x0a" -#define ngx_abs(value) (((value) >= 0) ? (value) : - (value)) +#define ngx_abs(value) (((value) >= 0) ? (value) : - (value)) +#define ngx_max(val1, val2) ((val1 < val2) ? (val2) : (val1)) +#define ngx_min(val1, val2) ((val1 > val2) ? (val2) : (val1)) void ngx_cpuinfo(void); diff --git a/src/core/ngx_palloc.c b/src/core/ngx_palloc.c --- a/src/core/ngx_palloc.c +++ b/src/core/ngx_palloc.c @@ -17,7 +17,7 @@ ngx_create_pool(size_t size, ngx_log_t * { ngx_pool_t *p; - p = ngx_memalign(ngx_pagesize, size, log); + p = ngx_memalign(ngx_min(ngx_pagesize, size), size, log); if (p == NULL) { return NULL; } @@ -181,7 +181,7 @@ ngx_palloc_block(ngx_pool_t *pool, size_ psize = (size_t) (pool->d.end - (u_char *) pool); - m = ngx_memalign(ngx_pagesize, psize, pool->log); + m = ngx_memalign(ngx_min(ngx_pagesize, psize), psize, pool->log); if (m == NULL) { return NULL; } @@ -219,7 +219,7 @@ ngx_palloc_large(ngx_pool_t *pool, size_ ngx_uint_t n; ngx_pool_large_t *large; - p = ngx_memalign(ngx_pagesize, size, pool->log); + p = ngx_alloc(size, pool->log); if (p == NULL) { return NULL; } diff --git a/src/core/ngx_regex.c b/src/core/ngx_regex.c --- a/src/core/ngx_regex.c +++ b/src/core/ngx_regex.c @@ -23,25 +23,16 @@ ngx_regex_init(void) } -ngx_regex_t * -ngx_regex_compile(ngx_str_t *pattern, ngx_int_t options, ngx_pool_t *pool, - ngx_str_t *err) +static ngx_inline void +ngx_regex_malloc_init(ngx_pool_t *pool) { - int erroff; - const char *errstr; - ngx_regex_t *re; #if (NGX_THREADS) ngx_core_tls_t *tls; -#if (NGX_SUPPRESS_WARN) - tls = NULL; -#endif - if (ngx_threaded) { tls = ngx_thread_get_tls(ngx_core_tls_key); tls->pool = pool; - } else { - ngx_pcre_pool = pool; + return; } #else @@ -49,35 +40,103 @@ ngx_regex_compile(ngx_str_t *pattern, ng ngx_pcre_pool = pool; #endif +} - re = pcre_compile((const char *) pattern->data, (int) options, + +static ngx_inline void +ngx_regex_malloc_done(void) +{ +#if (NGX_THREADS) + ngx_core_tls_t *tls; + + if (ngx_threaded) { + tls = ngx_thread_get_tls(ngx_core_tls_key); + tls->pool = NULL; + return; + } + +#else + + ngx_pcre_pool = NULL; + +#endif +} + + +ngx_int_t +ngx_regex_compile(ngx_regex_compile_t *rc) +{ + int n, erroff; + char *p; + const char *errstr; + ngx_regex_t *re; + + ngx_regex_malloc_init(rc->pool); + + re = pcre_compile((const char *) rc->pattern.data, (int) rc->options, &errstr, &erroff, NULL); + /* ensure that there is no current pool */ + ngx_regex_malloc_done(); + if (re == NULL) { - if ((size_t) erroff == pattern->len) { - ngx_snprintf(err->data, err->len - 1, - "pcre_compile() failed: %s in \"%s\"%Z", - errstr, pattern->data); + if ((size_t) erroff == rc->pattern.len) { + rc->err.len = ngx_snprintf(rc->err.data, rc->err.len, + "pcre_compile() failed: %s in \"%V\"", + errstr, &rc->pattern) + - rc->err.data; + } else { - ngx_snprintf(err->data, err->len - 1, - "pcre_compile() failed: %s in \"%s\" at \"%s\"%Z", - errstr, pattern->data, pattern->data + erroff); + rc->err.len = ngx_snprintf(rc->err.data, rc->err.len, + "pcre_compile() failed: %s in \"%V\" at \"%s\"", + errstr, &rc->pattern, rc->pattern.data + erroff) + - rc->err.data; } + + return NGX_ERROR; + } + + rc->regex = re; + + n = pcre_fullinfo(re, NULL, PCRE_INFO_CAPTURECOUNT, &rc->captures); + if (n < 0) { + p = "pcre_fullinfo(\"%V\", PCRE_INFO_CAPTURECOUNT) failed: %d"; + goto failed; + } + + if (rc->captures == 0) { + return NGX_OK; } - /* ensure that there is no current pool */ + n = pcre_fullinfo(re, NULL, PCRE_INFO_NAMECOUNT, &rc->named_captures); + if (n < 0) { + p = "pcre_fullinfo(\"%V\", PCRE_INFO_NAMECOUNT) failed: %d"; + goto failed; + } + + if (rc->named_captures == 0) { + return NGX_OK; + } -#if (NGX_THREADS) - if (ngx_threaded) { - tls->pool = NULL; - } else { - ngx_pcre_pool = NULL; + n = pcre_fullinfo(re, NULL, PCRE_INFO_NAMEENTRYSIZE, &rc->name_size); + if (n < 0) { + p = "pcre_fullinfo(\"%V\", PCRE_INFO_NAMEENTRYSIZE) failed: %d"; + goto failed; } -#else - ngx_pcre_pool = NULL; -#endif + + n = pcre_fullinfo(re, NULL, PCRE_INFO_NAMETABLE, &rc->names); + if (n < 0) { + p = "pcre_fullinfo(\"%V\", PCRE_INFO_NAMETABLE) failed: %d"; + goto failed; + } - return re; + return NGX_OK; + +failed: + + rc->err.len = ngx_snprintf(rc->err.data, rc->err.len, p, &rc->pattern, n) + - rc->err.data; + return NGX_OK; } @@ -99,22 +158,6 @@ ngx_regex_capture_count(ngx_regex_t *re) ngx_int_t -ngx_regex_exec(ngx_regex_t *re, ngx_str_t *s, int *captures, ngx_int_t size) -{ - int rc; - - rc = pcre_exec(re, NULL, (const char *) s->data, s->len, 0, 0, - captures, size); - - if (rc == -1) { - return NGX_REGEX_NO_MATCHED; - } - - return rc; -} - - -ngx_int_t ngx_regex_exec_array(ngx_array_t *a, ngx_str_t *s, ngx_log_t *log) { ngx_int_t n; @@ -133,7 +176,7 @@ ngx_regex_exec_array(ngx_array_t *a, ngx if (n < 0) { ngx_log_error(NGX_LOG_ALERT, log, 0, - ngx_regex_exec_n " failed: %d on \"%V\" using \"%s\"", + ngx_regex_exec_n " failed: %i on \"%V\" using \"%s\"", n, s, re[i].name); return NGX_ERROR; } @@ -157,11 +200,15 @@ ngx_regex_malloc(size_t size) if (ngx_threaded) { tls = ngx_thread_get_tls(ngx_core_tls_key); pool = tls->pool; + } else { pool = ngx_pcre_pool; } + #else + pool = ngx_pcre_pool; + #endif if (pool) { diff --git a/src/core/ngx_regex.h b/src/core/ngx_regex.h --- a/src/core/ngx_regex.h +++ b/src/core/ngx_regex.h @@ -14,29 +14,42 @@ #include -#define NGX_REGEX_NO_MATCHED -1000 +#define NGX_REGEX_NO_MATCHED PCRE_ERROR_NOMATCH /* -1 */ #define NGX_REGEX_CASELESS PCRE_CASELESS typedef pcre ngx_regex_t; + typedef struct { - ngx_regex_t *regex; - u_char *name; + ngx_str_t pattern; + ngx_pool_t *pool; + ngx_int_t options; + + ngx_regex_t *regex; + int captures; + int named_captures; + int name_size; + u_char *names; + ngx_str_t err; +} ngx_regex_compile_t; + + +typedef struct { + ngx_regex_t *regex; + u_char *name; } ngx_regex_elt_t; void ngx_regex_init(void); -ngx_regex_t *ngx_regex_compile(ngx_str_t *pattern, ngx_int_t options, - ngx_pool_t *pool, ngx_str_t *err); -ngx_int_t ngx_regex_capture_count(ngx_regex_t *re); -ngx_int_t ngx_regex_exec(ngx_regex_t *re, ngx_str_t *s, int *captures, - ngx_int_t size); +ngx_int_t ngx_regex_compile(ngx_regex_compile_t *rc); + +#define ngx_regex_exec(re, s, captures, size) \ + pcre_exec(re, NULL, (const char *) (s)->data, (s)->len, 0, 0, \ + captures, size) +#define ngx_regex_exec_n "pcre_exec()" + ngx_int_t ngx_regex_exec_array(ngx_array_t *a, ngx_str_t *s, ngx_log_t *log); -#define ngx_regex_exec_n "pcre_exec()" -#define ngx_regex_capture_count_n "pcre_fullinfo()" - - #endif /* _NGX_REGEX_H_INCLUDED_ */ diff --git a/src/http/modules/ngx_http_degradation_module.c b/src/http/modules/ngx_http_degradation_module.c new file mode 100644 --- /dev/null +++ b/src/http/modules/ngx_http_degradation_module.c @@ -0,0 +1,223 @@ + +/* + * Copyright (C) Igor Sysoev + */ + + +#include +#include +#include + + +typedef struct { + size_t sbrk_size; +} ngx_http_degradation_main_conf_t; + + +typedef struct { + ngx_uint_t degrade; +} ngx_http_degradation_loc_conf_t; + + +static ngx_conf_enum_t ngx_http_degrade[] = { + { ngx_string("204"), 204 }, + { ngx_string("444"), 444 }, + { ngx_null_string, 0 } +}; + + +static void *ngx_http_degradation_create_main_conf(ngx_conf_t *cf); +static void *ngx_http_degradation_create_loc_conf(ngx_conf_t *cf); +static char *ngx_http_degradation_merge_loc_conf(ngx_conf_t *cf, void *parent, + void *child); +static char *ngx_http_degradation(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); +static ngx_int_t ngx_http_degradation_init(ngx_conf_t *cf); + + +static ngx_command_t ngx_http_degradation_commands[] = { + + { ngx_string("degradation"), + NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, + ngx_http_degradation, + NGX_HTTP_MAIN_CONF_OFFSET, + 0, + NULL }, + + { ngx_string("degrade"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_enum_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_degradation_loc_conf_t, degrade), + &ngx_http_degrade }, + + ngx_null_command +}; + + +static ngx_http_module_t ngx_http_degradation_module_ctx = { + NULL, /* preconfiguration */ + ngx_http_degradation_init, /* postconfiguration */ + + ngx_http_degradation_create_main_conf, /* create main configuration */ + NULL, /* init main configuration */ + + NULL, /* create server configuration */ + NULL, /* merge server configuration */ + + ngx_http_degradation_create_loc_conf, /* create location configuration */ + ngx_http_degradation_merge_loc_conf /* merge location configuration */ +}; + + +ngx_module_t ngx_http_degradation_module = { + NGX_MODULE_V1, + &ngx_http_degradation_module_ctx, /* module context */ + ngx_http_degradation_commands, /* module directives */ + NGX_HTTP_MODULE, /* module type */ + NULL, /* init master */ + NULL, /* init module */ + NULL, /* init process */ + NULL, /* init thread */ + NULL, /* exit thread */ + NULL, /* exit process */ + NULL, /* exit master */ + NGX_MODULE_V1_PADDING +}; + + +static ngx_int_t +ngx_http_degradation_handler(ngx_http_request_t *r) +{ + time_t now; + static size_t sbrk_size; + static time_t sbrk_time; + ngx_http_degradation_loc_conf_t *dlcf; + ngx_http_degradation_main_conf_t *dmcf; + + dlcf = ngx_http_get_module_loc_conf(r, ngx_http_degradation_module); + + if (dlcf->degrade == 0) { + return NGX_DECLINED; + } + + dmcf = ngx_http_get_module_main_conf(r, ngx_http_degradation_module); + + if (dmcf->sbrk_size) { + + now = ngx_time(); + + /* lock mutex */ + + if (now != sbrk_time) { + + /* + * ELF/i386 is loaded at 0x08000000, 128M + * ELF/amd64 is loaded at 0x00400000, 4M + * + * use a function address to substract the loading address + */ + + sbrk_size = (size_t) sbrk(0) - ((uintptr_t) ngx_palloc & ~0x3FFFFF); + sbrk_time = now; + } + + /* unlock mutex */ + + if (sbrk_size >= dmcf->sbrk_size) { + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "degradation sbrk: %uz", sbrk_size); + + return dlcf->degrade; + } + } + + return NGX_DECLINED; +} + + +static void * +ngx_http_degradation_create_main_conf(ngx_conf_t *cf) +{ + ngx_http_degradation_main_conf_t *dmcf; + + dmcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_degradation_main_conf_t)); + if (dmcf == NULL) { + return NULL; + } + + return dmcf; +} + + +static void * +ngx_http_degradation_create_loc_conf(ngx_conf_t *cf) +{ + ngx_http_degradation_loc_conf_t *conf; + + conf = ngx_palloc(cf->pool, sizeof(ngx_http_degradation_loc_conf_t)); + if (conf == NULL) { + return NULL; + } + + conf->degrade = NGX_CONF_UNSET_UINT; + + return conf; +} + + +static char * +ngx_http_degradation_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) +{ + ngx_http_degradation_loc_conf_t *prev = parent; + ngx_http_degradation_loc_conf_t *conf = child; + + ngx_conf_merge_uint_value(conf->degrade, prev->degrade, 0); + + return NGX_CONF_OK; +} + + +static char * +ngx_http_degradation(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_http_degradation_main_conf_t *dmcf = conf; + + ngx_str_t *value, s; + + value = cf->args->elts; + + if (ngx_strncmp(value[1].data, "sbrk=", 5) == 0) { + + s.len = value[1].len - 5; + s.data = value[1].data + 5; + + dmcf->sbrk_size = ngx_parse_size(&s); + if (dmcf->sbrk_size == (size_t) NGX_ERROR) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid sbrk size \"%V\"", &value[1]); + return NGX_CONF_ERROR; + } + } + + return NGX_CONF_OK; +} + + +static ngx_int_t +ngx_http_degradation_init(ngx_conf_t *cf) +{ + ngx_http_handler_pt *h; + ngx_http_core_main_conf_t *cmcf; + + cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); + + h = ngx_array_push(&cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers); + if (h == NULL) { + return NGX_ERROR; + } + + *h = ngx_http_degradation_handler; + + return NGX_OK; +} diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c --- a/src/http/modules/ngx_http_fastcgi_module.c +++ b/src/http/modules/ngx_http_fastcgi_module.c @@ -2407,27 +2407,25 @@ ngx_http_fastcgi_split(ngx_http_request_ n = ngx_regex_exec(flcf->split_regex, &r->uri, captures, (1 + 2) * 3); + if (n >= 0) { /* match */ + f->script_name.len = captures[3] - captures[2]; + f->script_name.data = r->uri.data; + + f->path_info.len = captures[5] - captures[4]; + f->path_info.data = r->uri.data + f->script_name.len; + + return f; + } + if (n == NGX_REGEX_NO_MATCHED) { f->script_name = r->uri; return f; } - if (n < 0) { - ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, - ngx_regex_exec_n " failed: %d on \"%V\" using \"%V\"", - n, &r->uri, &flcf->split_name); - return NULL; - } - - /* match */ - - f->script_name.len = captures[3] - captures[2]; - f->script_name.data = r->uri.data; - - f->path_info.len = captures[5] - captures[4]; - f->path_info.data = r->uri.data + f->script_name.len; - - return f; + ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, + ngx_regex_exec_n " failed: %i on \"%V\" using \"%V\"", + n, &r->uri, &flcf->split_name); + return NULL; #else @@ -2518,39 +2516,34 @@ ngx_http_fastcgi_split_path_info(ngx_con #if (NGX_PCRE) ngx_http_fastcgi_loc_conf_t *flcf = conf; - ngx_int_t n; - ngx_str_t *value, err; - u_char errstr[NGX_MAX_CONF_ERRSTR]; + ngx_str_t *value; + ngx_regex_compile_t rc; + u_char errstr[NGX_MAX_CONF_ERRSTR]; value = cf->args->elts; flcf->split_name = value[1]; - err.len = NGX_MAX_CONF_ERRSTR; - err.data = errstr; - - flcf->split_regex = ngx_regex_compile(&value[1], 0, cf->pool, &err); - - if (flcf->split_regex == NULL) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data); + ngx_memzero(&rc, sizeof(ngx_regex_compile_t)); + + rc.pattern = value[1]; + rc.pool = cf->pool; + rc.err.len = NGX_MAX_CONF_ERRSTR; + rc.err.data = errstr; + + if (ngx_regex_compile(&rc) != NGX_OK) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &rc.err); return NGX_CONF_ERROR; } - n = ngx_regex_capture_count(flcf->split_regex); - - if (n < 0) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - ngx_regex_capture_count_n " failed for " - "pattern \"%V\"", &value[1]); - return NGX_CONF_ERROR; - } - - if (n != 2) { + if (rc.captures != 2) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "pattern \"%V\" must have 2 captures", &value[1]); return NGX_CONF_ERROR; } + flcf->split_regex = rc.regex; + return NGX_CONF_OK; #else diff --git a/src/http/modules/ngx_http_gzip_filter_module.c b/src/http/modules/ngx_http_gzip_filter_module.c --- a/src/http/modules/ngx_http_gzip_filter_module.c +++ b/src/http/modules/ngx_http_gzip_filter_module.c @@ -243,20 +243,30 @@ ngx_http_gzip_header_filter(ngx_http_req conf = ngx_http_get_module_loc_conf(r, ngx_http_gzip_filter_module); if (!conf->enable + || r->header_only || (r->headers_out.status != NGX_HTTP_OK && r->headers_out.status != NGX_HTTP_FORBIDDEN && r->headers_out.status != NGX_HTTP_NOT_FOUND) - || r->header_only || (r->headers_out.content_encoding && r->headers_out.content_encoding->value.len) || (r->headers_out.content_length_n != -1 && r->headers_out.content_length_n < conf->min_length) - || ngx_http_test_content_type(r, &conf->types) == NULL - || ngx_http_gzip_ok(r) != NGX_OK) + || ngx_http_test_content_type(r, &conf->types) == NULL) { return ngx_http_next_header_filter(r); } + r->gzip_vary = 1; + + if (!r->gzip_tested) { + if (ngx_http_gzip_ok(r) != NGX_OK) { + return ngx_http_next_header_filter(r); + } + + } else if (!r->gzip_ok) { + return ngx_http_next_header_filter(r); + } + ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_gzip_ctx_t)); if (ctx == NULL) { return NGX_ERROR; diff --git a/src/http/modules/ngx_http_gzip_static_module.c b/src/http/modules/ngx_http_gzip_static_module.c --- a/src/http/modules/ngx_http_gzip_static_module.c +++ b/src/http/modules/ngx_http_gzip_static_module.c @@ -99,9 +99,11 @@ ngx_http_gzip_static_handler(ngx_http_re return NGX_DECLINED; } + rc = ngx_http_gzip_ok(r); + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); - if (clcf->gzip_vary && ngx_http_gzip_ok(r) != NGX_OK) { + if (!clcf->gzip_vary && rc != NGX_OK) { return NGX_DECLINED; } @@ -143,7 +145,6 @@ ngx_http_gzip_static_handler(ngx_http_re case NGX_ENOTDIR: case NGX_ENAMETOOLONG: - r->gzip = 0; return NGX_DECLINED; case NGX_EACCES: @@ -163,6 +164,12 @@ ngx_http_gzip_static_handler(ngx_http_re return NGX_DECLINED; } + r->gzip_vary = 1; + + if (rc != NGX_OK) { + return NGX_DECLINED; + } + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http static fd: %d", of.fd); if (of.is_dir) { 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 @@ -724,17 +724,22 @@ ngx_http_proxy_eval(ngx_http_request_t * return NGX_ERROR; } - if (url.uri.len && url.uri.data[0] == '?') { - p = ngx_pnalloc(r->pool, url.uri.len + 1); - if (p == NULL) { - return NGX_ERROR; + if (url.uri.len) { + if (url.uri.data[0] == '?') { + p = ngx_pnalloc(r->pool, url.uri.len + 1); + if (p == NULL) { + return NGX_ERROR; + } + + *p++ = '/'; + ngx_memcpy(p, url.uri.data, url.uri.len); + + url.uri.len++; + url.uri.data = p - 1; } - *p++ = '/'; - ngx_memcpy(p, url.uri.data, url.uri.len); - - url.uri.len++; - url.uri.data = p - 1; + } else { + url.uri = r->unparsed_uri; } ctx->vars.key_start = u->schema; diff --git a/src/http/modules/ngx_http_referer_module.c b/src/http/modules/ngx_http_referer_module.c --- a/src/http/modules/ngx_http_referer_module.c +++ b/src/http/modules/ngx_http_referer_module.c @@ -412,7 +412,7 @@ ngx_http_valid_referers(ngx_conf_t *cf, if (sn[n].regex) { if (ngx_http_add_regex_referer(cf, rlcf, &sn[n].name, - sn[n].regex) + sn[n].regex->regex) != NGX_OK) { return NGX_CONF_ERROR; @@ -502,9 +502,9 @@ ngx_http_add_regex_referer(ngx_conf_t *c ngx_str_t *name, ngx_regex_t *regex) { #if (NGX_PCRE) - ngx_str_t err; - ngx_regex_elt_t *re; - u_char errstr[NGX_MAX_CONF_ERRSTR]; + ngx_regex_elt_t *re; + ngx_regex_compile_t rc; + u_char errstr[NGX_MAX_CONF_ERRSTR]; if (name->len == 1) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "empty regex in \"%V\"", name); @@ -530,19 +530,23 @@ ngx_http_add_regex_referer(ngx_conf_t *c return NGX_CONF_OK; } - err.len = NGX_MAX_CONF_ERRSTR; - err.data = errstr; - name->len--; name->data++; - re->regex = ngx_regex_compile(name, NGX_REGEX_CASELESS, cf->pool, &err); + ngx_memzero(&rc, sizeof(ngx_regex_compile_t)); - if (re->regex == NULL) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data); + rc.pattern = *name; + rc.pool = cf->pool; + rc.options = NGX_REGEX_CASELESS; + rc.err.len = NGX_MAX_CONF_ERRSTR; + rc.err.data = errstr; + + if (ngx_regex_compile(&rc) != NGX_OK) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &rc.err); return NGX_CONF_ERROR; } + re->regex = rc.regex; re->name = name->data; return NGX_CONF_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 @@ -294,9 +294,9 @@ ngx_http_rewrite(ngx_conf_t *cf, ngx_com { ngx_http_rewrite_loc_conf_t *lcf = conf; - ngx_str_t *value, err; - ngx_int_t n; + ngx_str_t *value; ngx_uint_t last; + ngx_regex_compile_t rc; ngx_http_script_code_pt *code; ngx_http_script_compile_t sc; ngx_http_script_regex_code_t *regex; @@ -313,15 +313,16 @@ ngx_http_rewrite(ngx_conf_t *cf, ngx_com value = cf->args->elts; - err.len = NGX_MAX_CONF_ERRSTR; - err.data = errstr; + ngx_memzero(&rc, sizeof(ngx_regex_compile_t)); + + rc.pattern = value[1]; + rc.err.len = NGX_MAX_CONF_ERRSTR; + rc.err.data = errstr; /* TODO: NGX_REGEX_CASELESS */ - regex->regex = ngx_regex_compile(&value[1], 0, cf->pool, &err); - + regex->regex = ngx_http_regex_compile(cf, &rc); if (regex->regex == NULL) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data); return NGX_CONF_ERROR; } @@ -394,7 +395,6 @@ ngx_http_rewrite(ngx_conf_t *cf, ngx_com regex = sc.main; - regex->ncaptures = sc.ncaptures; regex->size = sc.size; regex->args = sc.args; @@ -402,31 +402,6 @@ ngx_http_rewrite(ngx_conf_t *cf, ngx_com regex->lengths = NULL; } - n = ngx_regex_capture_count(regex->regex); - - if (n < 0) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - ngx_regex_capture_count_n " failed for " - "pattern \"%V\"", &value[1]); - return NGX_CONF_ERROR; - } - - if (regex->ncaptures > (ngx_uint_t) n) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "pattern \"%V\" has less captures " - "than referrenced in substitution \"%V\"", - &value[1], &value[2]); - return NGX_CONF_ERROR; - } - - if (regex->ncaptures < (ngx_uint_t) n) { - regex->ncaptures = (ngx_uint_t) n; - } - - if (regex->ncaptures) { - regex->ncaptures = (regex->ncaptures + 1) * 3; - } - regex_end = ngx_http_script_add_code(lcf->codes, sizeof(ngx_http_script_regex_end_code_t), ®ex); @@ -624,8 +599,9 @@ ngx_http_rewrite_if_condition(ngx_conf_t { u_char *p; size_t len; - ngx_str_t *value, err; - ngx_uint_t cur, last, n; + ngx_str_t *value; + ngx_uint_t cur, last; + ngx_regex_compile_t rc; ngx_http_script_code_pt *code; ngx_http_script_file_code_t *fop; ngx_http_script_regex_code_t *regex; @@ -733,15 +709,15 @@ ngx_http_rewrite_if_condition(ngx_conf_t ngx_memzero(regex, sizeof(ngx_http_script_regex_code_t)); - err.len = NGX_MAX_CONF_ERRSTR; - err.data = errstr; + ngx_memzero(&rc, sizeof(ngx_regex_compile_t)); - regex->regex = ngx_regex_compile(&value[last], - (p[len - 1] == '*') ? NGX_REGEX_CASELESS : 0, - cf->pool, &err); + rc.pattern = value[last]; + rc.options = (p[len - 1] == '*') ? NGX_REGEX_CASELESS : 0; + rc.err.len = NGX_MAX_CONF_ERRSTR; + rc.err.data = errstr; + regex->regex = ngx_http_regex_compile(cf, &rc); if (regex->regex == NULL) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data); return NGX_CONF_ERROR; } @@ -753,12 +729,6 @@ ngx_http_rewrite_if_condition(ngx_conf_t } regex->name = value[last]; - n = ngx_regex_capture_count(regex->regex); - - if (n) { - regex->ncaptures = (n + 1) * 3; - } - return NGX_CONF_OK; } diff --git a/src/http/modules/ngx_http_ssi_filter_module.c b/src/http/modules/ngx_http_ssi_filter_module.c --- a/src/http/modules/ngx_http_ssi_filter_module.c +++ b/src/http/modules/ngx_http_ssi_filter_module.c @@ -2450,27 +2450,28 @@ ngx_http_ssi_if(ngx_http_request_t *r, n } else { #if (NGX_PCRE) - ngx_str_t err; - ngx_regex_t *regex; - u_char errstr[NGX_MAX_CONF_ERRSTR]; - - err.len = NGX_MAX_CONF_ERRSTR; - err.data = errstr; + ngx_regex_compile_t rgc; + u_char errstr[NGX_MAX_CONF_ERRSTR]; right.data[right.len] = '\0'; - regex = ngx_regex_compile(&right, 0, r->pool, &err); - - if (regex == NULL) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%s", err.data); + ngx_memzero(&rgc, sizeof(ngx_regex_compile_t)); + + rgc.pattern = right; + rgc.pool = r->pool; + rgc.err.len = NGX_MAX_CONF_ERRSTR; + rgc.err.data = errstr; + + if (ngx_regex_compile(&rgc) != NGX_OK) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%V", &rgc.err); return NGX_HTTP_SSI_ERROR; } - rc = ngx_regex_exec(regex, &left, NULL, 0); - - if (rc != NGX_REGEX_NO_MATCHED && rc < 0) { + rc = ngx_regex_exec(rgc.regex, &left, NULL, 0); + + if (rc < NGX_REGEX_NO_MATCHED) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, - ngx_regex_exec_n " failed: %d on \"%V\" using \"%V\"", + ngx_regex_exec_n " failed: %i on \"%V\" using \"%V\"", rc, &left, &right); return NGX_HTTP_SSI_ERROR; } 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 @@ -47,7 +47,7 @@ our @EXPORT = qw( HTTP_INSUFFICIENT_STORAGE ); -our $VERSION = '0.8.24'; +our $VERSION = '0.8.25'; 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 @@ -902,9 +902,6 @@ variable(r, name, value = NULL) XSRETURN_UNDEF; } - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "variable \"%V\" not found", &var); - XSRETURN_UNDEF; } 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 @@ -812,7 +812,11 @@ ngx_http_handler(ngx_http_request_t *r) } r->valid_location = 1; - r->gzip = 0; +#if (NGX_HTTP_GZIP) + r->gzip_tested = 0; + r->gzip_ok = 0; + r->gzip_vary = 0; +#endif r->write_event_handler = ngx_http_core_run_phases; ngx_http_core_run_phases(r); @@ -1416,7 +1420,7 @@ ngx_http_core_find_location(ngx_http_req ngx_int_t rc; ngx_http_core_loc_conf_t *pclcf; #if (NGX_PCRE) - ngx_int_t n, len; + ngx_int_t n; ngx_uint_t noregex; ngx_http_core_loc_conf_t *clcf, **clcfp; @@ -1450,51 +1454,28 @@ ngx_http_core_find_location(ngx_http_req if (noregex == 0 && pclcf->regex_locations) { - len = 0; - for (clcfp = pclcf->regex_locations; *clcfp; clcfp++) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "test location: ~ \"%V\"", &(*clcfp)->name); - if ((*clcfp)->captures) { - - len = (NGX_HTTP_MAX_CAPTURES + 1) * 3; - - if (r->captures == NULL) { - r->captures = ngx_palloc(r->pool, len * sizeof(int)); - if (r->captures == NULL) { - return NGX_ERROR; - } - } + n = ngx_http_regex_exec(r, (*clcfp)->regex, &r->uri); + + if (n == NGX_OK) { + r->loc_conf = (*clcfp)->loc_conf; + + /* look up nested locations */ + + rc = ngx_http_core_find_location(r); + + return (rc == NGX_ERROR) ? rc : NGX_OK; } - n = ngx_regex_exec((*clcfp)->regex, &r->uri, r->captures, len); - - if (n == NGX_REGEX_NO_MATCHED) { + if (n == NGX_DECLINED) { continue; } - if (n < 0) { - ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, - ngx_regex_exec_n - " failed: %d on \"%V\" using \"%V\"", - n, &r->uri, &(*clcfp)->name); - return NGX_ERROR; - } - - /* match */ - - r->loc_conf = (*clcfp)->loc_conf; - - r->ncaptures = len; - r->captures_data = r->uri.data; - - /* look up nested locations */ - - rc = ngx_http_core_find_location(r); - - return (rc == NGX_ERROR) ? rc : NGX_OK; + return NGX_ERROR; } } #endif @@ -1774,7 +1755,7 @@ ngx_http_map_uri_to_path(ngx_http_reques #if (NGX_PCRE) ngx_uint_t captures; - captures = alias && clcf->captures; + captures = alias && clcf->regex; reserved += captures ? 1 : r->uri.len - alias + 1; #else reserved += r->uri.len - alias + 1; @@ -1891,15 +1872,7 @@ ngx_http_gzip_ok(ngx_http_request_t *r) ngx_table_elt_t *e, *d; ngx_http_core_loc_conf_t *clcf; - if (r->gzip == 1) { - return NGX_OK; - } - - if (r->gzip == 2) { - return NGX_DECLINED; - } - - r->gzip = 2; + r->gzip_tested = 1; if (r != r->main || r->headers_in.accept_encoding == NULL @@ -2034,7 +2007,7 @@ ok: #endif - r->gzip = 1; + r->gzip_ok = 1; return NGX_OK; } @@ -2600,26 +2573,25 @@ ngx_http_core_regex_location(ngx_conf_t ngx_str_t *regex, ngx_uint_t caseless) { #if (NGX_PCRE) - ngx_str_t err; - u_char errstr[NGX_MAX_CONF_ERRSTR]; - - err.len = NGX_MAX_CONF_ERRSTR; - err.data = errstr; + ngx_regex_compile_t rc; + u_char errstr[NGX_MAX_CONF_ERRSTR]; + + ngx_memzero(&rc, sizeof(ngx_regex_compile_t)); + + rc.pattern = *regex; + rc.err.len = NGX_MAX_CONF_ERRSTR; + rc.err.data = errstr; #if (NGX_HAVE_CASELESS_FILESYSTEM) - caseless = 1; + rc.options = NGX_REGEX_CASELESS; #endif - clcf->regex = ngx_regex_compile(regex, caseless ? NGX_REGEX_CASELESS: 0, - cf->pool, &err); - + clcf->regex = ngx_http_regex_compile(cf, &rc); if (clcf->regex == NULL) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data); return NGX_ERROR; } clcf->name = *regex; - clcf->captures = (ngx_regex_capture_count(clcf->regex) > 0); return NGX_OK; @@ -2637,14 +2609,14 @@ ngx_http_core_regex_location(ngx_conf_t static char * ngx_http_core_types(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { - ngx_http_core_loc_conf_t *lcf = conf; + ngx_http_core_loc_conf_t *clcf = conf; char *rv; ngx_conf_t save; - if (lcf->types == NULL) { - lcf->types = ngx_array_create(cf->pool, 64, sizeof(ngx_hash_key_t)); - if (lcf->types == NULL) { + if (clcf->types == NULL) { + clcf->types = ngx_array_create(cf->pool, 64, sizeof(ngx_hash_key_t)); + if (clcf->types == NULL) { return NGX_CONF_ERROR; } } @@ -2664,7 +2636,7 @@ ngx_http_core_types(ngx_conf_t *cf, ngx_ static char * ngx_http_core_type(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) { - ngx_http_core_loc_conf_t *lcf = conf; + ngx_http_core_loc_conf_t *clcf = conf; ngx_str_t *value, *content_type, *old, file; ngx_uint_t i, n, hash; @@ -2695,8 +2667,8 @@ ngx_http_core_type(ngx_conf_t *cf, ngx_c hash = ngx_hash_strlow(value[i].data, value[i].data, value[i].len); - type = lcf->types->elts; - for (n = 0; n < lcf->types->nelts; n++) { + type = clcf->types->elts; + for (n = 0; n < clcf->types->nelts; n++) { if (ngx_strcmp(value[i].data, type[n].key.data) == 0) { old = type[n].value; type[n].value = content_type; @@ -2711,7 +2683,7 @@ ngx_http_core_type(ngx_conf_t *cf, ngx_c } - type = ngx_array_push(lcf->types); + type = ngx_array_push(clcf->types); if (type == NULL) { return NGX_CONF_ERROR; } @@ -2916,89 +2888,89 @@ ngx_http_core_merge_srv_conf(ngx_conf_t static void * ngx_http_core_create_loc_conf(ngx_conf_t *cf) { - ngx_http_core_loc_conf_t *lcf; - - lcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_core_loc_conf_t)); - if (lcf == NULL) { + ngx_http_core_loc_conf_t *clcf; + + clcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_core_loc_conf_t)); + if (clcf == NULL) { return NULL; } /* * set by ngx_pcalloc(): * - * lcf->root = { 0, NULL }; - * lcf->limit_except = 0; - * lcf->post_action = { 0, NULL }; - * lcf->types = NULL; - * lcf->default_type = { 0, NULL }; - * lcf->error_log = NULL; - * lcf->error_pages = NULL; - * lcf->try_files = NULL; - * lcf->client_body_path = NULL; - * lcf->regex = NULL; - * lcf->exact_match = 0; - * lcf->auto_redirect = 0; - * lcf->alias = 0; - * lcf->gzip_proxied = 0; + * clcf->root = { 0, NULL }; + * clcf->limit_except = 0; + * clcf->post_action = { 0, NULL }; + * clcf->types = NULL; + * clcf->default_type = { 0, NULL }; + * clcf->error_log = NULL; + * clcf->error_pages = NULL; + * clcf->try_files = NULL; + * clcf->client_body_path = NULL; + * clcf->regex = NULL; + * clcf->exact_match = 0; + * clcf->auto_redirect = 0; + * clcf->alias = 0; + * clcf->gzip_proxied = 0; */ - lcf->client_max_body_size = NGX_CONF_UNSET; - lcf->client_body_buffer_size = NGX_CONF_UNSET_SIZE; - lcf->client_body_timeout = NGX_CONF_UNSET_MSEC; - lcf->satisfy = NGX_CONF_UNSET_UINT; - lcf->if_modified_since = NGX_CONF_UNSET_UINT; - lcf->client_body_in_file_only = NGX_CONF_UNSET_UINT; - lcf->client_body_in_single_buffer = NGX_CONF_UNSET; - lcf->internal = NGX_CONF_UNSET; - lcf->sendfile = NGX_CONF_UNSET; - lcf->sendfile_max_chunk = NGX_CONF_UNSET_SIZE; + clcf->client_max_body_size = NGX_CONF_UNSET; + clcf->client_body_buffer_size = NGX_CONF_UNSET_SIZE; + clcf->client_body_timeout = NGX_CONF_UNSET_MSEC; + clcf->satisfy = NGX_CONF_UNSET_UINT; + clcf->if_modified_since = NGX_CONF_UNSET_UINT; + clcf->client_body_in_file_only = NGX_CONF_UNSET_UINT; + clcf->client_body_in_single_buffer = NGX_CONF_UNSET; + clcf->internal = NGX_CONF_UNSET; + clcf->sendfile = NGX_CONF_UNSET; + clcf->sendfile_max_chunk = NGX_CONF_UNSET_SIZE; #if (NGX_HAVE_FILE_AIO) - lcf->aio = NGX_CONF_UNSET; + clcf->aio = NGX_CONF_UNSET; #endif - lcf->read_ahead = NGX_CONF_UNSET_SIZE; - lcf->directio = NGX_CONF_UNSET; - lcf->directio_alignment = NGX_CONF_UNSET; - lcf->tcp_nopush = NGX_CONF_UNSET; - lcf->tcp_nodelay = NGX_CONF_UNSET; - lcf->send_timeout = NGX_CONF_UNSET_MSEC; - lcf->send_lowat = NGX_CONF_UNSET_SIZE; - lcf->postpone_output = NGX_CONF_UNSET_SIZE; - lcf->limit_rate = NGX_CONF_UNSET_SIZE; - lcf->limit_rate_after = NGX_CONF_UNSET_SIZE; - lcf->keepalive_timeout = NGX_CONF_UNSET_MSEC; - lcf->keepalive_header = NGX_CONF_UNSET; - lcf->keepalive_requests = NGX_CONF_UNSET_UINT; - lcf->lingering_time = NGX_CONF_UNSET_MSEC; - lcf->lingering_timeout = NGX_CONF_UNSET_MSEC; - lcf->resolver_timeout = NGX_CONF_UNSET_MSEC; - lcf->reset_timedout_connection = NGX_CONF_UNSET; - lcf->server_name_in_redirect = NGX_CONF_UNSET; - lcf->port_in_redirect = NGX_CONF_UNSET; - lcf->msie_padding = NGX_CONF_UNSET; - lcf->msie_refresh = NGX_CONF_UNSET; - lcf->log_not_found = NGX_CONF_UNSET; - lcf->log_subrequest = NGX_CONF_UNSET; - lcf->recursive_error_pages = NGX_CONF_UNSET; - lcf->server_tokens = NGX_CONF_UNSET; - lcf->types_hash_max_size = NGX_CONF_UNSET_UINT; - lcf->types_hash_bucket_size = NGX_CONF_UNSET_UINT; - - lcf->open_file_cache = NGX_CONF_UNSET_PTR; - lcf->open_file_cache_valid = NGX_CONF_UNSET; - lcf->open_file_cache_min_uses = NGX_CONF_UNSET_UINT; - lcf->open_file_cache_errors = NGX_CONF_UNSET; - lcf->open_file_cache_events = NGX_CONF_UNSET; + clcf->read_ahead = NGX_CONF_UNSET_SIZE; + clcf->directio = NGX_CONF_UNSET; + clcf->directio_alignment = NGX_CONF_UNSET; + clcf->tcp_nopush = NGX_CONF_UNSET; + clcf->tcp_nodelay = NGX_CONF_UNSET; + clcf->send_timeout = NGX_CONF_UNSET_MSEC; + clcf->send_lowat = NGX_CONF_UNSET_SIZE; + clcf->postpone_output = NGX_CONF_UNSET_SIZE; + clcf->limit_rate = NGX_CONF_UNSET_SIZE; + clcf->limit_rate_after = NGX_CONF_UNSET_SIZE; + clcf->keepalive_timeout = NGX_CONF_UNSET_MSEC; + clcf->keepalive_header = NGX_CONF_UNSET; + clcf->keepalive_requests = NGX_CONF_UNSET_UINT; + clcf->lingering_time = NGX_CONF_UNSET_MSEC; + clcf->lingering_timeout = NGX_CONF_UNSET_MSEC; + clcf->resolver_timeout = NGX_CONF_UNSET_MSEC; + clcf->reset_timedout_connection = NGX_CONF_UNSET; + clcf->server_name_in_redirect = NGX_CONF_UNSET; + clcf->port_in_redirect = NGX_CONF_UNSET; + clcf->msie_padding = NGX_CONF_UNSET; + clcf->msie_refresh = NGX_CONF_UNSET; + clcf->log_not_found = NGX_CONF_UNSET; + clcf->log_subrequest = NGX_CONF_UNSET; + clcf->recursive_error_pages = NGX_CONF_UNSET; + clcf->server_tokens = NGX_CONF_UNSET; + clcf->types_hash_max_size = NGX_CONF_UNSET_UINT; + clcf->types_hash_bucket_size = NGX_CONF_UNSET_UINT; + + clcf->open_file_cache = NGX_CONF_UNSET_PTR; + clcf->open_file_cache_valid = NGX_CONF_UNSET; + clcf->open_file_cache_min_uses = NGX_CONF_UNSET_UINT; + clcf->open_file_cache_errors = NGX_CONF_UNSET; + clcf->open_file_cache_events = NGX_CONF_UNSET; #if (NGX_HTTP_GZIP) - lcf->gzip_vary = NGX_CONF_UNSET; - lcf->gzip_http_version = NGX_CONF_UNSET_UINT; + clcf->gzip_vary = NGX_CONF_UNSET; + clcf->gzip_http_version = NGX_CONF_UNSET_UINT; #if (NGX_PCRE) - lcf->gzip_disable = NGX_CONF_UNSET_PTR; - lcf->gzip_disable_msie6 = 3; + clcf->gzip_disable = NGX_CONF_UNSET_PTR; + clcf->gzip_disable_msie6 = 3; #endif #endif - return lcf; + return clcf; } @@ -3539,8 +3511,8 @@ ngx_http_core_server_name(ngx_conf_t *cf #if (NGX_PCRE) { - ngx_str_t err; - u_char errstr[NGX_MAX_CONF_ERRSTR]; + ngx_regex_compile_t rc; + u_char errstr[NGX_MAX_CONF_ERRSTR]; if (value[i].len == 1) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, @@ -3548,21 +3520,22 @@ ngx_http_core_server_name(ngx_conf_t *cf return NGX_CONF_ERROR; } - err.len = NGX_MAX_CONF_ERRSTR; - err.data = errstr; - value[i].len--; value[i].data++; - sn->regex = ngx_regex_compile(&value[i], 0, cf->pool, &err); - + ngx_memzero(&rc, sizeof(ngx_regex_compile_t)); + + rc.pattern = value[i]; + rc.err.len = NGX_MAX_CONF_ERRSTR; + rc.err.data = errstr; + + sn->regex = ngx_http_regex_compile(cf, &rc); if (sn->regex == NULL) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data); return NGX_CONF_ERROR; } sn->name = value[i]; - cscf->captures = (ngx_regex_capture_count(sn->regex) > 0); + cscf->captures = (rc.captures > 0); } #else ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, @@ -3580,7 +3553,7 @@ ngx_http_core_server_name(ngx_conf_t *cf static char * ngx_http_core_root(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { - ngx_http_core_loc_conf_t *lcf = conf; + ngx_http_core_loc_conf_t *clcf = conf; ngx_str_t *value; ngx_uint_t alias, n; @@ -3588,11 +3561,11 @@ ngx_http_core_root(ngx_conf_t *cf, ngx_c alias = (cmd->name.len == sizeof("alias") - 1) ? 1 : 0; - if (lcf->root.data) { + if (clcf->root.data) { /* the (ngx_uint_t) cast is required by gcc 2.7.2.3 */ - if ((ngx_uint_t) lcf->alias == alias) { + if ((ngx_uint_t) clcf->alias == alias) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "\"%V\" directive is duplicate", &cmd->name); @@ -3600,13 +3573,13 @@ ngx_http_core_root(ngx_conf_t *cf, ngx_c ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "\"%V\" directive is duplicate, " "\"%s\" directive is specified before", - &cmd->name, lcf->alias ? "alias" : "root"); + &cmd->name, clcf->alias ? "alias" : "root"); } return NGX_CONF_ERROR; } - if (lcf->named && alias) { + if (clcf->named && alias) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "the \"alias\" directive may not be used " "inside named location"); @@ -3638,28 +3611,28 @@ ngx_http_core_root(ngx_conf_t *cf, ngx_c return NGX_CONF_ERROR; } - lcf->alias = alias; - lcf->root = value[1]; - - if (!alias && lcf->root.data[lcf->root.len - 1] == '/') { - lcf->root.len--; + clcf->alias = alias; + clcf->root = value[1]; + + if (!alias && clcf->root.data[clcf->root.len - 1] == '/') { + clcf->root.len--; } - if (lcf->root.data[0] != '$') { - if (ngx_conf_full_name(cf->cycle, &lcf->root, 0) != NGX_OK) { + if (clcf->root.data[0] != '$') { + if (ngx_conf_full_name(cf->cycle, &clcf->root, 0) != NGX_OK) { return NGX_CONF_ERROR; } } - n = ngx_http_script_variables_count(&lcf->root); + n = ngx_http_script_variables_count(&clcf->root); ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); if (n) { sc.cf = cf; - sc.source = &lcf->root; - sc.lengths = &lcf->root_lengths; - sc.values = &lcf->root_values; + sc.source = &clcf->root; + sc.lengths = &clcf->root_lengths; + sc.values = &clcf->root_values; sc.variables = n; sc.complete_lengths = 1; sc.complete_values = 1; @@ -3669,20 +3642,6 @@ ngx_http_core_root(ngx_conf_t *cf, ngx_c } } -#if (NGX_PCRE) - - if (alias && lcf->regex - && (ngx_regex_capture_count(lcf->regex) <= 0 || sc.ncaptures == 0)) - { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "the \"alias\" directive must use captures " - "inside location given by regular expression"); - - return NGX_CONF_ERROR; - } - -#endif - return NGX_CONF_OK; } @@ -3834,7 +3793,7 @@ ngx_http_core_directio(ngx_conf_t *cf, n static char * ngx_http_core_error_page(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { - ngx_http_core_loc_conf_t *lcf = conf; + ngx_http_core_loc_conf_t *clcf = conf; u_char *p; ngx_int_t overwrite; @@ -3844,10 +3803,10 @@ ngx_http_core_error_page(ngx_conf_t *cf, ngx_http_complex_value_t cv; ngx_http_compile_complex_value_t ccv; - if (lcf->error_pages == NULL) { - lcf->error_pages = ngx_array_create(cf->pool, 4, - sizeof(ngx_http_err_page_t)); - if (lcf->error_pages == NULL) { + if (clcf->error_pages == NULL) { + clcf->error_pages = ngx_array_create(cf->pool, 4, + sizeof(ngx_http_err_page_t)); + if (clcf->error_pages == NULL) { return NGX_CONF_ERROR; } } @@ -3911,7 +3870,7 @@ ngx_http_core_error_page(ngx_conf_t *cf, } for (i = 1; i < cf->args->nelts - n; i++) { - err = ngx_array_push(lcf->error_pages); + err = ngx_array_push(clcf->error_pages); if (err == NULL) { return NGX_CONF_ERROR; } @@ -4039,14 +3998,14 @@ ngx_http_core_try_files(ngx_conf_t *cf, static char * ngx_http_core_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { - ngx_http_core_loc_conf_t *lcf = conf; + ngx_http_core_loc_conf_t *clcf = conf; time_t inactive; ngx_str_t *value, s; ngx_int_t max; ngx_uint_t i; - if (lcf->open_file_cache != NGX_CONF_UNSET_PTR) { + if (clcf->open_file_cache != NGX_CONF_UNSET_PTR) { return "is duplicate"; } @@ -4082,7 +4041,7 @@ ngx_http_core_open_file_cache(ngx_conf_t if (ngx_strcmp(value[i].data, "off") == 0) { - lcf->open_file_cache = NULL; + clcf->open_file_cache = NULL; continue; } @@ -4095,7 +4054,7 @@ ngx_http_core_open_file_cache(ngx_conf_t return NGX_CONF_ERROR; } - if (lcf->open_file_cache == NULL) { + if (clcf->open_file_cache == NULL) { return NGX_CONF_OK; } @@ -4105,8 +4064,8 @@ ngx_http_core_open_file_cache(ngx_conf_t return NGX_CONF_ERROR; } - lcf->open_file_cache = ngx_open_file_cache_init(cf->pool, max, inactive); - if (lcf->open_file_cache) { + clcf->open_file_cache = ngx_open_file_cache_init(cf->pool, max, inactive); + if (clcf->open_file_cache) { return NGX_CONF_OK; } @@ -4117,50 +4076,50 @@ ngx_http_core_open_file_cache(ngx_conf_t static char * ngx_http_core_error_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { - ngx_http_core_loc_conf_t *lcf = conf; + ngx_http_core_loc_conf_t *clcf = conf; ngx_str_t *value; - if (lcf->error_log) { + if (clcf->error_log) { return "is duplicate"; } value = cf->args->elts; - lcf->error_log = ngx_log_create(cf->cycle, &value[1]); - if (lcf->error_log == NULL) { + clcf->error_log = ngx_log_create(cf->cycle, &value[1]); + if (clcf->error_log == NULL) { return NGX_CONF_ERROR; } if (cf->args->nelts == 2) { - lcf->error_log->log_level = NGX_LOG_ERR; + clcf->error_log->log_level = NGX_LOG_ERR; return NGX_CONF_OK; } - return ngx_log_set_levels(cf, lcf->error_log); + return ngx_log_set_levels(cf, clcf->error_log); } static char * ngx_http_core_keepalive(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { - ngx_http_core_loc_conf_t *lcf = conf; + ngx_http_core_loc_conf_t *clcf = conf; ngx_str_t *value; - if (lcf->keepalive_timeout != NGX_CONF_UNSET_MSEC) { + if (clcf->keepalive_timeout != NGX_CONF_UNSET_MSEC) { return "is duplicate"; } value = cf->args->elts; - lcf->keepalive_timeout = ngx_parse_time(&value[1], 0); - - if (lcf->keepalive_timeout == (ngx_msec_t) NGX_ERROR) { + clcf->keepalive_timeout = ngx_parse_time(&value[1], 0); + + if (clcf->keepalive_timeout == (ngx_msec_t) NGX_ERROR) { return "invalid value"; } - if (lcf->keepalive_timeout == (ngx_msec_t) NGX_PARSE_LARGE_TIME) { + if (clcf->keepalive_timeout == (ngx_msec_t) NGX_PARSE_LARGE_TIME) { return "value must be less than 597 hours"; } @@ -4168,13 +4127,13 @@ ngx_http_core_keepalive(ngx_conf_t *cf, return NGX_CONF_OK; } - lcf->keepalive_header = ngx_parse_time(&value[2], 1); - - if (lcf->keepalive_header == NGX_ERROR) { + clcf->keepalive_header = ngx_parse_time(&value[2], 1); + + if (clcf->keepalive_header == NGX_ERROR) { return "invalid value"; } - if (lcf->keepalive_header == NGX_PARSE_LARGE_TIME) { + if (clcf->keepalive_header == NGX_PARSE_LARGE_TIME) { return "value must be less than 68 years"; } @@ -4185,13 +4144,13 @@ ngx_http_core_keepalive(ngx_conf_t *cf, static char * ngx_http_core_internal(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { - ngx_http_core_loc_conf_t *lcf = conf; - - if (lcf->internal != NGX_CONF_UNSET) { + ngx_http_core_loc_conf_t *clcf = conf; + + if (clcf->internal != NGX_CONF_UNSET) { return "is duplicate"; } - lcf->internal = 1; + clcf->internal = 1; return NGX_CONF_OK; } @@ -4239,10 +4198,11 @@ ngx_http_gzip_disable(ngx_conf_t *cf, ng #if (NGX_PCRE) - ngx_str_t err, *value; - ngx_uint_t i; - ngx_regex_elt_t *re; - u_char errstr[NGX_MAX_CONF_ERRSTR]; + ngx_str_t *value; + ngx_uint_t i; + ngx_regex_elt_t *re; + ngx_regex_compile_t rc; + u_char errstr[NGX_MAX_CONF_ERRSTR]; if (clcf->gzip_disable == NGX_CONF_UNSET_PTR) { clcf->gzip_disable = ngx_array_create(cf->pool, 2, @@ -4254,8 +4214,11 @@ ngx_http_gzip_disable(ngx_conf_t *cf, ng value = cf->args->elts; - err.len = NGX_MAX_CONF_ERRSTR; - err.data = errstr; + ngx_memzero(&rc, sizeof(ngx_regex_compile_t)); + + rc.pool = cf->pool; + rc.err.len = NGX_MAX_CONF_ERRSTR; + rc.err.data = errstr; for (i = 1; i < cf->args->nelts; i++) { @@ -4269,14 +4232,15 @@ ngx_http_gzip_disable(ngx_conf_t *cf, ng return NGX_CONF_ERROR; } - re->regex = ngx_regex_compile(&value[i], NGX_REGEX_CASELESS, cf->pool, - &err); - - if (re->regex == NULL) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data); + rc.pattern = value[1]; + rc.options = NGX_REGEX_CASELESS; + + if (ngx_regex_compile(&rc) != NGX_OK) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &rc.err); return NGX_CONF_ERROR; } + re->regex = rc.regex; re->name = value[i].data; } 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 @@ -126,6 +126,7 @@ typedef struct { ngx_hash_t variables_hash; ngx_array_t variables; /* ngx_http_variable_t */ + ngx_uint_t ncaptures; ngx_uint_t server_names_hash_max_size; ngx_uint_t server_names_hash_bucket_size; @@ -238,7 +239,7 @@ typedef struct { struct ngx_http_server_name_s { #if (NGX_PCRE) - ngx_regex_t *regex; + ngx_http_regex_t *regex; #endif ngx_http_core_srv_conf_t *server; /* virtual name server conf */ ngx_str_t name; @@ -267,9 +268,7 @@ struct ngx_http_core_loc_conf_s { ngx_str_t name; /* location name */ #if (NGX_PCRE) - ngx_regex_t *regex; - - unsigned captures:1; + ngx_http_regex_t *regex; #endif unsigned noname:1; /* "if () {}" block or limit_except */ diff --git a/src/http/ngx_http_header_filter_module.c b/src/http/ngx_http_header_filter_module.c --- a/src/http/ngx_http_header_filter_module.c +++ b/src/http/ngx_http_header_filter_module.c @@ -399,8 +399,13 @@ ngx_http_header_filter(ngx_http_request_ } #if (NGX_HTTP_GZIP) - if (r->gzip && clcf->gzip_vary) { - len += sizeof("Vary: Accept-Encoding" CRLF) - 1; + if (r->gzip_vary) { + if (clcf->gzip_vary) { + len += sizeof("Vary: Accept-Encoding" CRLF) - 1; + + } else { + r->gzip_vary = 0; + } } #endif @@ -559,7 +564,7 @@ ngx_http_header_filter(ngx_http_request_ } #if (NGX_HTTP_GZIP) - if (r->gzip && clcf->gzip_vary) { + if (r->gzip_vary) { b->last = ngx_cpymem(b->last, "Vary: Accept-Encoding" CRLF, sizeof("Vary: Accept-Encoding" CRLF) - 1); } 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 @@ -1445,6 +1445,9 @@ ngx_http_process_user_agent(ngx_http_req if (ngx_strstrn(user_agent, "Gecko/", 6 - 1)) { r->headers_in.gecko = 1; + } else if (ngx_strstrn(user_agent, "Chrome/", 7 - 1)) { + r->headers_in.chrome = 1; + } else if (ngx_strstrn(user_agent, "Konqueror", 9 - 1)) { r->headers_in.konqueror = 1; } @@ -1697,7 +1700,6 @@ ngx_http_find_virtual_server(ngx_http_re #if (NGX_PCRE) if (len && r->virtual_names->nregex) { - size_t ncaptures; ngx_int_t n; ngx_uint_t i; ngx_str_t name; @@ -1706,44 +1708,22 @@ ngx_http_find_virtual_server(ngx_http_re name.len = len; name.data = host; - ncaptures = 0; - sn = r->virtual_names->regex; for (i = 0; i < r->virtual_names->nregex; i++) { - if (sn[i].server->captures && r->captures == NULL) { - - ncaptures = (NGX_HTTP_MAX_CAPTURES + 1) * 3; - - r->captures = ngx_palloc(r->pool, ncaptures * sizeof(int)); - if (r->captures == NULL) { - return NGX_ERROR; - } + n = ngx_http_regex_exec(r, sn[i].regex, &name); + + if (n == NGX_OK) { + cscf = sn[i].server; + goto found; } - n = ngx_regex_exec(sn[i].regex, &name, r->captures, ncaptures); - - if (n == NGX_REGEX_NO_MATCHED) { + if (n == NGX_DECLINED) { continue; } - if (n < 0) { - ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, - ngx_regex_exec_n - " failed: %d on \"%V\" using \"%V\"", - n, &name, &sn[i].name); - return NGX_ERROR; - } - - /* match */ - - cscf = sn[i].server; - - r->ncaptures = ncaptures; - r->captures_data = host; - - goto found; + return NGX_ERROR; } } diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h --- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -10,7 +10,6 @@ #define NGX_HTTP_MAX_URI_CHANGES 10 #define NGX_HTTP_MAX_SUBREQUESTS 50 -#define NGX_HTTP_MAX_CAPTURES 9 /* must be 2^n */ #define NGX_HTTP_LC_HEADER_LEN 32 @@ -220,6 +219,7 @@ typedef struct { unsigned msie6:1; unsigned opera:1; unsigned gecko:1; + unsigned chrome:1; unsigned konqueror:1; } ngx_http_headers_in_t; @@ -457,7 +457,12 @@ struct ngx_http_request_s { #if (NGX_HTTP_CACHE) unsigned cached:1; #endif - unsigned gzip:2; + +#if (NGX_HTTP_GZIP) + unsigned gzip_tested:1; + unsigned gzip_ok:1; + unsigned gzip_vary:1; +#endif unsigned proxy:1; unsigned bypass_cache:1; 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 @@ -251,8 +251,6 @@ ngx_http_script_compile(ngx_http_script_ { ngx_uint_t n; - /* NGX_HTTP_MAX_CAPTURES is 9 */ - if (sc->source->data[i] >= '1' && sc->source->data[i] <= '9') { n = sc->source->data[i] - '0'; @@ -828,20 +826,9 @@ ngx_http_script_regex_start_code(ngx_htt e->line.data = e->sp->data; } - if (code->ncaptures && r->captures == NULL) { + rc = ngx_http_regex_exec(r, code->regex, &e->line); - r->captures = ngx_palloc(r->pool, - (NGX_HTTP_MAX_CAPTURES + 1) * 3 * sizeof(int)); - if (r->captures == NULL) { - e->ip = ngx_http_script_exit; - e->status = NGX_HTTP_INTERNAL_SERVER_ERROR; - return; - } - } - - rc = ngx_regex_exec(code->regex, &e->line, r->captures, code->ncaptures); - - if (rc == NGX_REGEX_NO_MATCHED) { + if (rc == NGX_DECLINED) { if (e->log || (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP)) { ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0, "\"%V\" does not match \"%V\"", @@ -870,11 +857,7 @@ ngx_http_script_regex_start_code(ngx_htt return; } - if (rc < 0) { - ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, - ngx_regex_exec_n " failed: %d on \"%V\" using \"%V\"", - rc, &e->line, &code->name); - + if (rc == NGX_ERROR) { e->ip = ngx_http_script_exit; e->status = NGX_HTTP_INTERNAL_SERVER_ERROR; return; @@ -885,9 +868,6 @@ ngx_http_script_regex_start_code(ngx_htt "\"%V\" matches \"%V\"", &code->name, &e->line); } - r->ncaptures = code->ncaptures; - r->captures_data = e->line.data; - if (code->test) { if (code->negative_test) { e->sp->len = 0; diff --git a/src/http/ngx_http_script.h b/src/http/ngx_http_script.h --- a/src/http/ngx_http_script.h +++ b/src/http/ngx_http_script.h @@ -114,10 +114,9 @@ typedef struct { typedef struct { ngx_http_script_code_pt code; - ngx_regex_t *regex; + ngx_http_regex_t *regex; ngx_array_t *lengths; uintptr_t size; - uintptr_t ncaptures; uintptr_t status; uintptr_t next; 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 @@ -31,13 +31,13 @@ static u_char ngx_http_error_tail[] = ; -static u_char ngx_http_msie_stub[] = -"" CRLF -"" CRLF -"" CRLF -"" CRLF -"" CRLF -"" CRLF +static u_char ngx_http_msie_padding[] = +"" CRLF +"" CRLF +"" CRLF +"" CRLF +"" CRLF +"" CRLF ; @@ -598,12 +598,12 @@ ngx_http_send_special_response(ngx_http_ r->headers_out.content_length_n = ngx_http_error_pages[err].len + len; if (clcf->msie_padding - && r->headers_in.msie + && (r->headers_in.msie || r->headers_in.chrome) && r->http_version >= NGX_HTTP_VERSION_10 && err >= NGX_HTTP_LEVEL_300) { r->headers_out.content_length_n += - sizeof(ngx_http_msie_stub) - 1; + sizeof(ngx_http_msie_padding) - 1; msie_padding = 1; } @@ -671,8 +671,8 @@ ngx_http_send_special_response(ngx_http_ } b->memory = 1; - b->pos = ngx_http_msie_stub; - b->last = ngx_http_msie_stub + sizeof(ngx_http_msie_stub) - 1; + b->pos = ngx_http_msie_padding; + b->last = ngx_http_msie_padding + sizeof(ngx_http_msie_padding) - 1; out[1].next = &out[2]; out[2].buf = b; diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c --- a/src/http/ngx_http_variables.c +++ b/src/http/ngx_http_variables.c @@ -1666,6 +1666,157 @@ ngx_http_variable_pid(ngx_http_request_t } +static ngx_int_t +ngx_http_variable_not_found(ngx_http_request_t *r, ngx_http_variable_value_t *v, + uintptr_t data) +{ + v->not_found = 1; + return NGX_OK; +} + + +ngx_http_regex_t * +ngx_http_regex_compile(ngx_conf_t *cf, ngx_regex_compile_t *rc) +{ + u_char *p; + size_t size; + ngx_str_t name; + ngx_uint_t i, n; + ngx_http_variable_t *v; + ngx_http_regex_t *re; + ngx_http_regex_variable_t *rv; + ngx_http_core_main_conf_t *cmcf; + + rc->pool = cf->pool; + + if (ngx_regex_compile(rc) != NGX_OK) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &rc->err); + return NULL; + } + + re = ngx_pcalloc(cf->pool, sizeof(ngx_http_regex_t)); + if (re == NULL) { + return NULL; + } + + re->regex = rc->regex; + re->ncaptures = rc->captures; + + cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); + cmcf->ncaptures = ngx_max(cmcf->ncaptures, re->ncaptures); + + n = (ngx_uint_t) rc->named_captures; + + if (n == 0) { + return re; + } + + rv = ngx_palloc(rc->pool, n * sizeof(ngx_http_regex_variable_t)); + if (rv == NULL) { + return NULL; + } + + re->variables = rv; + re->nvariables = n; + re->name = rc->pattern; + + size = rc->name_size; + p = rc->names; + + for (i = 0; i < n; i++) { + rv[i].capture = 2 * ((p[0] << 8) + p[1]); + + name.data = &p[2]; + name.len = ngx_strlen(name.data); + + v = ngx_http_add_variable(cf, &name, NGX_HTTP_VAR_CHANGEABLE); + if (v == NULL) { + return NULL; + } + + rv[i].index = ngx_http_get_variable_index(cf, &name); + if (rv[i].index == NGX_ERROR) { + return NULL; + } + + v->get_handler = ngx_http_variable_not_found; + + p += i + size; + } + + return re; +} + + +ngx_int_t +ngx_http_regex_exec(ngx_http_request_t *r, ngx_http_regex_t *re, ngx_str_t *s) +{ + ngx_int_t rc, index; + ngx_uint_t i, n, len; + ngx_http_variable_value_t *vv; + ngx_http_core_main_conf_t *cmcf; + + cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); + + if (re->ncaptures) { + len = (cmcf->ncaptures + 1) * 3; + + if (r->captures == NULL) { + r->captures = ngx_palloc(r->pool, len * sizeof(int)); + if (r->captures == NULL) { + return NGX_ERROR; + } + } + + } else { + len = 0; + } + + rc = ngx_regex_exec(re->regex, s, r->captures, len); + + if (rc == NGX_REGEX_NO_MATCHED) { + return NGX_DECLINED; + } + + if (rc < 0) { + ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, + ngx_regex_exec_n " failed: %i on \"%V\" using \"%V\"", + rc, s, &re->name); + return NGX_ERROR; + } + + for (i = 0; i < re->nvariables; i++) { + + n = re->variables[i].capture; + index = re->variables[i].index; + vv = &r->variables[index]; + + vv->len = r->captures[n + 1] - r->captures[n]; + vv->valid = 1; + vv->no_cacheable = 0; + vv->not_found = 0; + vv->data = &s->data[r->captures[n]]; + +#if (NGX_DEBUG) + { + ngx_http_variable_t *v; + + v = cmcf->variables.elts; + + ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http regex set $%V to \"%*s\"", + &v[index].name, vv->len, vv->data); + } +#endif + } + + r->ncaptures = len; + r->captures_data = s->data; + + return NGX_OK; +} + + ngx_int_t ngx_http_variables_add_core_vars(ngx_conf_t *cf) { diff --git a/src/http/ngx_http_variables.h b/src/http/ngx_http_variables.h --- a/src/http/ngx_http_variables.h +++ b/src/http/ngx_http_variables.h @@ -41,6 +41,21 @@ struct ngx_http_variable_s { }; +typedef struct { + ngx_uint_t capture; + ngx_int_t index; +} ngx_http_regex_variable_t; + + +typedef struct { + ngx_regex_t *regex; + ngx_uint_t ncaptures; + ngx_http_regex_variable_t *variables; + ngx_uint_t nvariables; + ngx_str_t name; +} ngx_http_regex_t; + + ngx_http_variable_t *ngx_http_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags); ngx_int_t ngx_http_get_variable_index(ngx_conf_t *cf, ngx_str_t *name); @@ -59,6 +74,12 @@ ngx_int_t ngx_http_variable_unknown_head #define ngx_http_clear_variable(r, index) r->variables0[index].text.data = NULL; +ngx_http_regex_t *ngx_http_regex_compile(ngx_conf_t *cf, + ngx_regex_compile_t *rc); +ngx_int_t ngx_http_regex_exec(ngx_http_request_t *r, ngx_http_regex_t *re, + ngx_str_t *s); + + ngx_int_t ngx_http_variables_add_core_vars(ngx_conf_t *cf); ngx_int_t ngx_http_variables_init_vars(ngx_conf_t *cf); diff --git a/src/os/unix/ngx_alloc.c b/src/os/unix/ngx_alloc.c --- a/src/os/unix/ngx_alloc.c +++ b/src/os/unix/ngx_alloc.c @@ -21,7 +21,7 @@ ngx_alloc(size_t size, ngx_log_t *log) p = malloc(size); if (p == NULL) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, - "malloc() %uz bytes failed", size); + "malloc(%uz) failed", size); } ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, log, 0, "malloc: %p:%uz", p, size); @@ -51,15 +51,18 @@ void * ngx_memalign(size_t alignment, size_t size, ngx_log_t *log) { void *p; + int err; - if (posix_memalign(&p, alignment, size) == -1) { - ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, - "posix_memalign() %uz bytes aligned to %uz failed", - size, alignment); + err = posix_memalign(&p, alignment, size); + + if (err) { + ngx_log_error(NGX_LOG_EMERG, log, err, + "posix_memalign(%uz, %uz) failed", alignment, size); + p = NULL; } ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, log, 0, - "posix_memalign: %p:%uz", p, size); + "posix_memalign: %p:%uz @%uz", p, size, alignment); return p; } @@ -74,12 +77,11 @@ ngx_memalign(size_t alignment, size_t si p = memalign(alignment, size); if (p == NULL) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, - "memalign() %uz bytes aligned to %uz failed", - size, alignment); + "memalign(%uz, %uz) failed", alignment, size); } ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, log, 0, - "memalign: %p:%uz", p, size); + "memalign: %p:%uz @%uz", p, size, alignment); return p; } diff --git a/src/os/unix/ngx_files.c b/src/os/unix/ngx_files.c --- a/src/os/unix/ngx_files.c +++ b/src/os/unix/ngx_files.c @@ -402,6 +402,26 @@ ngx_unlock_fd(ngx_fd_t fd) } +#if (NGX_HAVE_POSIX_FADVISE) + +ngx_int_t +ngx_read_ahead(ngx_fd_t fd, size_t n) +{ + int err; + + err = posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL); + + if (err == 0) { + return 0; + } + + ngx_set_errno(err); + return NGX_FILE_ERROR; +} + +#endif + + #if (NGX_HAVE_O_DIRECT) ngx_int_t diff --git a/src/os/unix/ngx_files.h b/src/os/unix/ngx_files.h --- a/src/os/unix/ngx_files.h +++ b/src/os/unix/ngx_files.h @@ -264,7 +264,7 @@ ngx_err_t ngx_unlock_fd(ngx_fd_t fd); #define NGX_HAVE_READ_AHEAD 1 -#define ngx_read_ahead(fd, n) posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL) +ngx_int_t ngx_read_ahead(ngx_fd_t fd, size_t n); #define ngx_read_ahead_n "posix_fadvise(POSIX_FADV_SEQUENTIAL)" #else