summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2005-12-18 15:59:13 +0000
committerJonathan Kolb <jon@b0g.us>2005-12-18 15:59:13 +0000
commit995b39e3197cda659cbe4496b6496a727d1dd9a0 (patch)
treefc0d512ce829a25d02b91220aa9b390bf50f3f27
parenta961a379f965ff05abd2be69c6e1090b501bd1c8 (diff)
downloadnginx-995b39e3197cda659cbe4496b6496a727d1dd9a0.tar.gz
Changes with nginx 0.3.17 18 Dec 2005v0.3.17
*) Change: now on Linux configure checks the presence of epoll and sendfile64() in kernel. *) Feature: the "map" directive supports domain names in the ".domain.tld" form. *) Bugfix: the timeouts were not used in SSL handshake. *) Bugfix: in the HTTP protocol in the "proxy_pass" directive. *) Bugfix: when the HTTP protocol was used in the "proxy_pass" directive the port 80 was used by default.
-rw-r--r--CHANGES18
-rw-r--r--CHANGES.ru16
-rw-r--r--auto/os/linux18
-rw-r--r--auto/sources1
-rw-r--r--src/core/nginx.h2
-rw-r--r--src/core/ngx_hash.c42
-rw-r--r--src/event/ngx_event_openssl.c17
-rw-r--r--src/http/modules/ngx_http_map_module.c241
-rw-r--r--src/http/modules/ngx_http_proxy_module.c9
-rw-r--r--src/http/ngx_http_config.c214
-rw-r--r--src/http/ngx_http_config.h26
-rw-r--r--src/http/ngx_http_upstream.c88
12 files changed, 447 insertions, 245 deletions
diff --git a/CHANGES b/CHANGES
index 0167eb968..0172d25c3 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,20 @@
+Changes with nginx 0.3.17 18 Dec 2005
+
+ *) Change: now on Linux configure checks the presence of epoll and
+ sendfile64() in kernel.
+
+ *) Feature: the "map" directive supports domain names in the
+ ".domain.tld" form.
+
+ *) Bugfix: the timeouts were not used in SSL handshake.
+
+ *) Bugfix: in the HTTP protocol in the "proxy_pass" directive.
+
+ *) Bugfix: when the HTTP protocol was used in the "proxy_pass"
+ directive the port 80 was used by default.
+
+
Changes with nginx 0.3.16 16 Dec 2005
*) Feature: the ngx_http_map_module.
@@ -113,7 +129,7 @@ Changes with nginx 0.3.10 15 Nov 2005
*) Feature: the "if" directive supports the "=" and "!=" operations.
- *) Feature: the "proxy_set_body" directive supports the HTTPS protocol.
+ *) Feature: the "proxy_pass" directive supports the HTTPS protocol.
*) Feature: the "proxy_set_body" directive.
diff --git a/CHANGES.ru b/CHANGES.ru
index 8155aed42..884cfdea6 100644
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,20 @@
+Изменения в nginx 0.3.17 18.12.2005
+
+ *) Изменение: на Linux configure теперь проверяет наличие epoll и
+ sendfile64() в ядре.
+
+ *) Добавление: директива map поддерживает доменные имена в формате
+ ".domain.tld".
+
+ *) Исправление: во время SSL handshake не иcпользовались таймауты.
+
+ *) Исправление: в использовании протокола HTTPS в директиве proxy_pass.
+
+ *) Исправление: при использовании протокола HTTPS в директиве
+ proxy_pass по умолчанию использовался порт 80.
+
+
Изменения в nginx 0.3.16 16.12.2005
*) Добавление: модуль ngx_http_map_module.
diff --git a/auto/os/linux b/auto/os/linux
index 39027b370..a7a8d713d 100644
--- a/auto/os/linux
+++ b/auto/os/linux
@@ -38,7 +38,7 @@ fi
ngx_feature="epoll"
ngx_feature_name="NGX_HAVE_EPOLL"
-ngx_feature_run=no
+ngx_feature_run=yes
ngx_feature_incs="#include <sys/epoll.h>"
ngx_feature_libs=
ngx_feature_test="int efd = 0, fd = 1, n;
@@ -62,12 +62,14 @@ fi
CC_AUX_FLAGS="-D_GNU_SOURCE"
ngx_feature="sendfile()"
ngx_feature_name="NGX_HAVE_SENDFILE"
-ngx_feature_run=no
-ngx_feature_incs="#include <sys/sendfile.h>"
+ngx_feature_run=yes
+ngx_feature_incs="#include <sys/sendfile.h>
+#include <errno.h>"
ngx_feature_libs=
ngx_feature_test="int s = 0, fd = 1;
ssize_t n; off_t off = 0;
- n = sendfile(s, fd, &off, 1)"
+ n = sendfile(s, fd, &off, 1);
+ if (n == -1 && errno == ENOSYS) return 1"
. auto/feature
if [ $ngx_found = yes ]; then
@@ -80,12 +82,14 @@ fi
CC_AUX_FLAGS="-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64"
ngx_feature="sendfile64()"
ngx_feature_name="NGX_HAVE_SENDFILE64"
-ngx_feature_run=no
-ngx_feature_incs="#include <sys/sendfile.h>"
+ngx_feature_run=yes
+ngx_feature_incs="#include <sys/sendfile.h>
+#include <errno.h>"
ngx_feature_libs=
ngx_feature_test="int s = 0, fd = 1;
ssize_t n; off_t off = 0;
- n = sendfile(s, fd, &off, 1)"
+ n = sendfile(s, fd, &off, 1);
+ if (n == -1 && errno == ENOSYS) return 1"
. auto/feature
diff --git a/auto/sources b/auto/sources
index b59808313..5eacc1ae2 100644
--- a/auto/sources
+++ b/auto/sources
@@ -266,6 +266,7 @@ HTTP_DEPS="src/http/ngx_http.h \
HTTP_SRCS="src/http/ngx_http.c \
src/http/ngx_http_core_module.c \
+ src/http/ngx_http_config.c \
src/http/ngx_http_special_response.c \
src/http/ngx_http_request.c \
src/http/ngx_http_parse.c \
diff --git a/src/core/nginx.h b/src/core/nginx.h
index ce9e59654..c6c562f17 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,7 +8,7 @@
#define _NGINX_H_INCLUDED_
-#define NGINX_VER "nginx/0.3.16"
+#define NGINX_VER "nginx/0.3.17"
#define NGINX_VAR "NGINX"
#define NGX_OLDPID_EXT ".oldbin"
diff --git a/src/core/ngx_hash.c b/src/core/ngx_hash.c
index 4decd42e9..dab19358a 100644
--- a/src/core/ngx_hash.c
+++ b/src/core/ngx_hash.c
@@ -76,10 +76,6 @@ ngx_hash_find_wildcard(ngx_hash_wildcard_t *hwc, u_char *name, size_t len)
n--;
}
- if (n == 0) {
- return NULL;
- }
-
key = 0;
for (i = n; i < len; i++) {
@@ -93,8 +89,28 @@ ngx_hash_find_wildcard(ngx_hash_wildcard_t *hwc, u_char *name, size_t len)
value = ngx_hash_find(&hwc->hash, key, &name[n], len - n);
if (value) {
+
+ /*
+ * the 2 low bits of value have the special meaning:
+ * 00 - value is data pointer,
+ * 01 - value is pointer to wildcard hash allowing
+ * "*.example.com" only,
+ * 11 - value is pointer to wildcard hash allowing
+ * both "example.com" and "*.example.com".
+ */
+
if ((uintptr_t) value & 1) {
- hwc = (ngx_hash_wildcard_t *) ((uintptr_t) value & (uintptr_t) ~1);
+
+ hwc = (ngx_hash_wildcard_t *) ((uintptr_t) value & (uintptr_t) ~3);
+
+ if (n == 0) {
+ if ((uintptr_t) value & 2) {
+ return hwc->value;
+
+ } else {
+ return NULL;
+ }
+ }
value = ngx_hash_find_wildcard(hwc, name, n - 1);
@@ -332,7 +348,7 @@ ngx_hash_wildcard_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names,
ngx_uint_t nelts)
{
size_t len;
- ngx_uint_t i, n;
+ ngx_uint_t i, n, dot;
ngx_array_t curr_names, next_names;
ngx_hash_key_t *name, *next_name;
ngx_hash_init_t h;
@@ -359,9 +375,11 @@ ngx_hash_wildcard_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names,
"wc0: \"%V\"", &names[n].key);
#endif
+ dot = 0;
+
for (len = 0; len < names[n].key.len; len++) {
if (names[n].key.data[len] == '.') {
- len++;
+ dot = 1;
break;
}
}
@@ -371,7 +389,7 @@ ngx_hash_wildcard_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names,
return NGX_ERROR;
}
- name->key.len = len - 1;
+ name->key.len = len;
name->key.data = names[n].key.data;
name->key_hash = hinit->key(name->key.data, name->key.len);
name->value = names[n].value;
@@ -381,6 +399,10 @@ ngx_hash_wildcard_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names,
"wc1: \"%V\"", &name->key);
#endif
+ if (dot) {
+ len++;
+ }
+
next_names.nelts = 0;
if (names[n].key.len != len) {
@@ -417,7 +439,7 @@ ngx_hash_wildcard_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names,
#if 0
ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0,
- "wc2: \"%V\"", &next_name->key);
+ "wc3: \"%V\"", &next_name->key);
#endif
}
@@ -442,7 +464,7 @@ ngx_hash_wildcard_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names,
#endif
}
- name->value = (void *) ((uintptr_t) wdc | 1);
+ name->value = (void *) ((uintptr_t) wdc | (dot ? 1 : 3));
}
}
diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c
index b343718e4..788463c3d 100644
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -334,6 +334,7 @@ ngx_ssl_handshake(ngx_connection_t *c)
if (sslerr == SSL_ERROR_WANT_READ) {
c->read->ready = 0;
c->read->handler = ngx_ssl_handshake_handler;
+ c->write->handler = ngx_ssl_handshake_handler;
if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) {
return NGX_ERROR;
@@ -344,6 +345,7 @@ ngx_ssl_handshake(ngx_connection_t *c)
if (sslerr == SSL_ERROR_WANT_WRITE) {
c->write->ready = 0;
+ c->read->handler = ngx_ssl_handshake_handler;
c->write->handler = ngx_ssl_handshake_handler;
if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) {
@@ -357,6 +359,7 @@ ngx_ssl_handshake(ngx_connection_t *c)
c->ssl->no_wait_shutdown = 1;
c->ssl->no_send_shutdown = 1;
+ c->read->eof = 1;
if (sslerr == SSL_ERROR_ZERO_RETURN || ERR_peek_error() == 0) {
ngx_log_error(NGX_LOG_INFO, c->log, err,
@@ -365,6 +368,8 @@ ngx_ssl_handshake(ngx_connection_t *c)
return NGX_ERROR;
}
+ c->read->error = 1;
+
ngx_ssl_connection_error(c, sslerr, err, "SSL_do_handshake() failed");
return NGX_ERROR;
@@ -381,6 +386,11 @@ ngx_ssl_handshake_handler(ngx_event_t *ev)
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
"SSL handshake handler: %d", ev->write);
+ if (ev->timedout) {
+ c->ssl->handler(c);
+ return;
+ }
+
if (ngx_ssl_handshake(c) == NGX_AGAIN) {
return;
}
@@ -548,6 +558,7 @@ ngx_ssl_handle_recv(ngx_connection_t *c, int n)
return NGX_DONE;
}
+ c->read->error = 1;
ngx_ssl_connection_error(c, sslerr, err, "SSL_read() failed");
return NGX_ERROR;
@@ -773,6 +784,7 @@ ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size)
c->ssl->no_wait_shutdown = 1;
c->ssl->no_send_shutdown = 1;
+ c->write->error = 1;
ngx_ssl_connection_error(c, sslerr, err, "SSL_write() failed");
@@ -795,6 +807,7 @@ ngx_int_t
ngx_ssl_shutdown(ngx_connection_t *c)
{
int n, sslerr, mode;
+ ngx_err_t err;
ngx_uint_t again;
if (c->timedout) {
@@ -866,7 +879,9 @@ ngx_ssl_shutdown(ngx_connection_t *c)
return NGX_AGAIN;
}
- ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_shutdown() failed");
+ err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
+
+ ngx_ssl_connection_error(c, sslerr, err, "SSL_shutdown() failed");
SSL_free(c->ssl->connection);
c->ssl = NULL;
diff --git a/src/http/modules/ngx_http_map_module.c b/src/http/modules/ngx_http_map_module.c
index 2769028d6..04e2e0ac7 100644
--- a/src/http/modules/ngx_http_map_module.c
+++ b/src/http/modules/ngx_http_map_module.c
@@ -9,8 +9,6 @@
#include <ngx_http.h>
-#define NGX_HTTP_MAP_HASH 10007
-
typedef struct {
ngx_uint_t hash_max_size;
ngx_uint_t hash_bucket_size;
@@ -18,13 +16,7 @@ typedef struct {
typedef struct {
- ngx_pool_t *pool;
-
- ngx_array_t keys;
- ngx_array_t *keys_hash;
-
- ngx_array_t dns_wildcards;
- ngx_array_t *dns_hash;
+ ngx_http_hash_conf_t hash;
ngx_array_t *values_hash;
@@ -253,40 +245,44 @@ ngx_http_map_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_ERROR;
}
- if (ngx_array_init(&ctx.keys, pool, 16384, sizeof(ngx_hash_key_t))
+ if (ngx_array_init(&ctx.hash.keys, pool, 16384, sizeof(ngx_hash_key_t))
!= NGX_OK)
{
ngx_destroy_pool(pool);
return NGX_CONF_ERROR;
}
- if (ngx_array_init(&ctx.dns_wildcards, pool, 16384, sizeof(ngx_hash_key_t))
+ if (ngx_array_init(&ctx.hash.dns_wildcards, pool, 16384,
+ sizeof(ngx_hash_key_t))
!= NGX_OK)
{
ngx_destroy_pool(pool);
return NGX_CONF_ERROR;
}
- ctx.keys_hash = ngx_pcalloc(pool, sizeof(ngx_array_t) * NGX_HTTP_MAP_HASH);
- if (ctx.keys_hash == NULL) {
+ ctx.hash.keys_hash = ngx_pcalloc(pool,
+ sizeof(ngx_array_t) * NGX_HTTP_CONFIG_HASH);
+ if (ctx.hash.keys_hash == NULL) {
ngx_destroy_pool(pool);
return NGX_CONF_ERROR;
}
- ctx.dns_hash = ngx_pcalloc(pool, sizeof(ngx_array_t) * NGX_HTTP_MAP_HASH);
- if (ctx.dns_hash == NULL) {
+ ctx.hash.dns_hash = ngx_pcalloc(pool,
+ sizeof(ngx_array_t) * NGX_HTTP_CONFIG_HASH);
+ if (ctx.hash.dns_hash == NULL) {
ngx_destroy_pool(pool);
return NGX_CONF_ERROR;
}
ctx.values_hash = ngx_pcalloc(pool,
- sizeof(ngx_array_t) * NGX_HTTP_MAP_HASH);
+ sizeof(ngx_array_t) * NGX_HTTP_CONFIG_HASH);
if (ctx.values_hash == NULL) {
ngx_destroy_pool(pool);
return NGX_CONF_ERROR;
}
- ctx.pool = cf->pool;
+ ctx.hash.pool = cf->pool;
+ ctx.hash.temp_pool = pool;
ctx.default_value = NULL;
ctx.hostnames = 0;
@@ -312,11 +308,13 @@ ngx_http_map_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
hash.name = "map_hash";
hash.pool = cf->pool;
- if (ctx.keys.nelts) {
+ if (ctx.hash.keys.nelts) {
hash.hash = &map->hash;
hash.temp_pool = NULL;
- if (ngx_hash_init(&hash, ctx.keys.elts, ctx.keys.nelts) != NGX_OK) {
+ if (ngx_hash_init(&hash, ctx.hash.keys.elts, ctx.hash.keys.nelts)
+ != NGX_OK)
+ {
return NGX_CONF_ERROR;
}
}
@@ -324,16 +322,17 @@ ngx_http_map_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
map->default_value = ctx.default_value ? ctx.default_value:
&ngx_http_variable_null_value;
- if (ctx.dns_wildcards.nelts) {
+ if (ctx.hash.dns_wildcards.nelts) {
- ngx_qsort(ctx.dns_wildcards.elts, (size_t) ctx.dns_wildcards.nelts,
+ ngx_qsort(ctx.hash.dns_wildcards.elts,
+ (size_t) ctx.hash.dns_wildcards.nelts,
sizeof(ngx_hash_key_t), ngx_http_map_cmp_dns_wildcards);
hash.hash = NULL;
hash.temp_pool = pool;
- if (ngx_hash_wildcard_init(&hash, ctx.dns_wildcards.elts,
- ctx.dns_wildcards.nelts)
+ if (ngx_hash_wildcard_init(&hash, ctx.hash.dns_wildcards.elts,
+ ctx.hash.dns_wildcards.nelts)
!= NGX_OK)
{
return NGX_CONF_ERROR;
@@ -363,13 +362,12 @@ ngx_http_map_cmp_dns_wildcards(const void *one, const void *two)
static char *
ngx_http_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
{
- size_t len;
- ngx_str_t *value, file, *name;
- ngx_uint_t i, n, key;
- ngx_hash_key_t *m;
+ u_char ch;
+ ngx_int_t rc;
+ ngx_str_t *value, file;
+ ngx_uint_t i, key, flags;
ngx_http_map_conf_ctx_t *ctx;
- ngx_http_variable_value_t *var, *old, **vp;
- u_char buf[2048];
+ ngx_http_variable_value_t *var, **vp;
ctx = cf->ctx;
@@ -410,7 +408,7 @@ ngx_http_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
key = ngx_hash(key, value[1].data[i]);
}
- key %= NGX_HTTP_MAP_HASH;
+ key %= NGX_HTTP_CONFIG_HASH;
vp = ctx->values_hash[key].elts;
@@ -435,13 +433,13 @@ ngx_http_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
}
}
- var = ngx_palloc(ctx->pool, sizeof(ngx_http_variable_value_t));
+ var = ngx_palloc(ctx->hash.pool, sizeof(ngx_http_variable_value_t));
if (var == NULL) {
return NGX_CONF_ERROR;
}
var->len = value[1].len;
- var->data = ngx_pstrdup(ctx->pool, &value[1]);
+ var->data = ngx_pstrdup(ctx->hash.pool, &value[1]);
if (var->data == NULL) {
return NGX_CONF_ERROR;
}
@@ -459,179 +457,54 @@ ngx_http_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
found:
- if (value[0].data[0] != '*' || ctx->hostnames == 0) {
-
- if (ngx_strcmp(value[0].data, "default") != 0) {
-
- if (value[0].len && value[0].data[0] == '!') {
- value[0].len--;
- value[0].data++;
- }
-
- key = 0;
-
- for (i = 0; i < value[0].len; i++) {
- value[0].data[i] = ngx_tolower(value[0].data[i]);
- key = ngx_hash(key, value[0].data[i]);
- }
+ ch = value[0].data[0];
- key %= NGX_HTTP_MAP_HASH;
+ if ((ch != '*' && ch != '.') || ctx->hostnames == 0) {
- name = ctx->keys_hash[key].elts;
+ if (ngx_strcmp(value[0].data, "default") == 0) {
- if (name) {
- for (i = 0; i < ctx->keys_hash[key].nelts; i++) {
- if (value[0].len != name[i].len) {
- continue;
- }
-
- if (ngx_strncmp(value[0].data, name[i].data, value[0].len)
- == 0)
- {
- m = ctx->keys.elts;
- for (i = 0; i < ctx->keys.nelts; i++) {
- if (ngx_strcmp(value[0].data, m[i].key.data) == 0) {
- old = m[i].value;
- m[i].value = var;
-
- goto duplicate;
- }
- }
- }
- }
-
- } else {
- if (ngx_array_init(&ctx->keys_hash[key], cf->pool, 4,
- sizeof(ngx_str_t))
- != NGX_OK)
- {
- return NGX_CONF_ERROR;
- }
- }
-
- name = ngx_array_push(&ctx->keys_hash[key]);
- if (name == NULL) {
- return NGX_CONF_ERROR;
- }
-
- *name = value[0];
-
- m = ngx_array_push(&ctx->keys);
- if (m == NULL) {
- return NGX_CONF_ERROR;
- }
-
- m->key = value[0];
- m->key_hash = ngx_hash_key(value[0].data, value[0].len);
- m->value = var;
-
- } else {
if (ctx->default_value) {
- old = ctx->default_value;
- ctx->default_value = var;
-
- goto duplicate;
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "duplicate default map parameter");
+ return NGX_CONF_ERROR;
}
ctx->default_value = var;
- }
- } else {
-
- if (value[0].len < 3 || value[0].data[1] != '.') {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid DNS wildcard \"%V\"", &value[0]);
- return NGX_CONF_ERROR;
- }
-
- key = 0;
-
- for (i = 2; i < value[0].len; i++) {
- value[0].data[i] = ngx_tolower(value[0].data[i]);
- key = ngx_hash(key, value[0].data[i]);
- }
-
- key %= NGX_HTTP_MAP_HASH;
-
- /* convert "*.example.com" into "com.example.\0" */
-
- len = 0;
- n = 0;
-
- for (i = value[0].len - 1; i; i--) {
- if (value[0].data[i] == '.') {
- ngx_memcpy(&buf[n], &value[0].data[i + 1], len);
- n += len;
- buf[n++] = '.';
- len = 0;
- continue;
- }
-
- len++;
+ return NGX_CONF_OK;
}
- buf[n] = '\0';
-
- name = ctx->dns_hash[key].elts;
-
- if (name) {
- for (i = 0; i < ctx->dns_hash[key].nelts; i++) {
- if (value[0].len != name[i].len) {
- continue;
- }
-
- if (ngx_strncmp(value[0].data, name[i].data, value[0].len)
- == 0)
- {
- m = ctx->dns_wildcards.elts;
- for (i = 0; i < ctx->dns_wildcards.nelts; i++) {
- if (ngx_strcmp(buf, m[i].key.data) == 0) {
- old = m[i].value;
- m[i].value = var;
-
- goto duplicate;
- }
- }
- }
- }
-
- } else {
- if (ngx_array_init(&ctx->dns_hash[key], cf->pool, 4,
- sizeof(ngx_str_t))
- != NGX_OK)
- {
- return NGX_CONF_ERROR;
- }
+ if (value[0].len && ch == '!') {
+ value[0].len--;
+ value[0].data++;
}
- name = ngx_array_push(&ctx->dns_hash[key]);
- if (name == NULL) {
- return NGX_CONF_ERROR;
- }
+ flags = 0;
- *name = value[0];
+ } else {
- ngx_memcpy(value[0].data, buf, value[0].len);
- value[0].len--;
+ if ((ch == '*' && (value[0].len < 3 || value[0].data[1] != '.'))
+ || (ch == '.' && value[0].len < 2))
+ {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "invalid DNS wildcard \"%V\"", &value[0]);
- m = ngx_array_push(&ctx->dns_wildcards);
- if (m == NULL) {
return NGX_CONF_ERROR;
}
- m->key = value[0];
- m->key_hash = 0;
- m->value = var;
+ flags = NGX_HTTP_WILDCARD_HASH;
}
- return NGX_CONF_OK;
+ rc = ngx_http_config_add_hash(&ctx->hash, &value[0], var, flags);
-duplicate:
+ if (rc == NGX_OK) {
+ return NGX_CONF_OK;
+ }
- ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
- "duplicate parameter \"%V\", value: \"%V\", "
- "old value: \"%V\"",
- &value[0], var, old);
+ if (rc == NGX_BUSY) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "conflicting parameter \"%V\"", &value[0]);
+ }
- return NGX_CONF_OK;
+ return NGX_CONF_ERROR;
}
diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c
index c39f32065..c2be2c44e 100644
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -1926,6 +1926,7 @@ ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
size_t add;
ngx_str_t *value, *url;
+ ngx_uint_t port;
ngx_inet_upstream_t inet_upstream;
ngx_http_core_loc_conf_t *clcf;
#if (NGX_HTTP_SSL)
@@ -1945,12 +1946,14 @@ ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
if (ngx_strncasecmp(url->data, "http://", 7) == 0) {
add = 7;
+ port = 80;
} else if (ngx_strncasecmp(url->data, "https://", 8) == 0) {
#if (NGX_HTTP_SSL)
add = 8;
+ port = 443;
plcf->upstream.ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t));
if (plcf->upstream.ssl == NULL) {
@@ -2019,7 +2022,7 @@ ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
inet_upstream.name = *url;
inet_upstream.url.len = url->len - add;
inet_upstream.url.data = url->data + add;
- inet_upstream.default_port_value = 80;
+ inet_upstream.default_port_value = port;
inet_upstream.uri_part = 1;
plcf->peers = ngx_inet_upstream_parse(cf, &inet_upstream);
@@ -2032,8 +2035,8 @@ ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
plcf->upstream.uri = inet_upstream.uri;
}
- plcf->upstream.schema.len = sizeof("http://") - 1;
- plcf->upstream.schema.data = (u_char *) "http://";
+ plcf->upstream.schema.len = add;
+ plcf->upstream.schema.data = url->data;
clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
diff --git a/src/http/ngx_http_config.c b/src/http/ngx_http_config.c
new file mode 100644
index 000000000..965625d64
--- /dev/null
+++ b/src/http/ngx_http_config.c
@@ -0,0 +1,214 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_event.h>
+#include <ngx_http.h>
+
+
+ngx_int_t
+ngx_http_config_add_hash(ngx_http_hash_conf_t *h, ngx_str_t *key, void *value,
+ ngx_uint_t flags)
+{
+ size_t len;
+ ngx_str_t *name;
+ ngx_uint_t i, k, n, skip;
+ ngx_hash_key_t *hk;
+ u_char buf[2048];
+
+ if (!(flags & NGX_HTTP_WILDCARD_HASH)) {
+
+ /* exact hash */
+
+ k = 0;
+
+ for (i = 0; i < key->len; i++) {
+ key->data[i] = ngx_tolower(key->data[i]);
+ k = ngx_hash(k, key->data[i]);
+ }
+
+ k %= NGX_HTTP_CONFIG_HASH;
+
+ /* check conflicts in exact hash */
+
+ name = h->keys_hash[k].elts;
+
+ if (name) {
+ for (i = 0; i < h->keys_hash[k].nelts; i++) {
+ if (key->len != name[i].len) {
+ continue;
+ }
+
+ if (ngx_strncmp(key->data, name[i].data, key->len) == 0) {
+ return NGX_BUSY;
+ }
+ }
+
+ } else {
+ if (ngx_array_init(&h->keys_hash[k], h->temp_pool, 4,
+ sizeof(ngx_str_t))
+ != NGX_OK)
+ {
+ return NGX_ERROR;
+ }
+ }
+
+ name = ngx_array_push(&h->keys_hash[k]);
+ if (name == NULL) {
+ return NGX_ERROR;
+ }
+
+ *name = *key;
+
+ hk = ngx_array_push(&h->keys);
+ if (hk == NULL) {
+ return NGX_ERROR;
+ }
+
+ hk->key = *key;
+ hk->key_hash = ngx_hash_key(key->data, key->len);
+ hk->value = value;
+
+ } else {
+
+ /* wildcard hash */
+
+ skip = (key->data[0] == '*') ? 2 : 1;
+ k = 0;
+
+ for (i = skip; i < key->len; i++) {
+ key->data[i] = ngx_tolower(key->data[i]);
+ k = ngx_hash(k, key->data[i]);
+ }
+
+ k %= NGX_HTTP_CONFIG_HASH;
+
+ if (skip == 1) {
+
+ /* check conflicts in exact hash for ".example.com" */
+
+ name = h->keys_hash[k].elts;
+
+ if (name) {
+ len = key->len - skip;
+
+ for (i = 0; i < h->keys_hash[k].nelts; i++) {
+ if (len != name[i].len) {
+ continue;
+ }
+
+ if (ngx_strncmp(&key->data[1], name[i].data, len) == 0) {
+ return NGX_BUSY;
+ }
+ }
+
+ } else {
+ if (ngx_array_init(&h->keys_hash[k], h->temp_pool, 4,
+ sizeof(ngx_str_t))
+ != NGX_OK)
+ {
+ return NGX_ERROR;
+ }
+ }
+
+ name = ngx_array_push(&h->keys_hash[k]);
+ if (name == NULL) {
+ return NGX_ERROR;
+ }
+
+ name->len = key->len - 1;
+ name->data = ngx_palloc(h->temp_pool, name->len);
+ if (name->data == NULL) {
+ return NGX_ERROR;
+ }
+
+ ngx_memcpy(name->data, &key->data[1], name->len);
+ }
+
+
+ /*
+ * convert "*.example.com" to "com.example.\0"
+ * and ".example.com" to "com.example\0"
+ */
+
+ len = 0;
+ n = 0;
+
+ for (i = key->len - 1; i; i--) {
+ if (key->data[i] == '.') {
+ ngx_memcpy(&buf[n], &key->data[i + 1], len);
+ n += len;
+ buf[n++] = '.';
+ len = 0;
+ continue;
+ }
+
+ len++;
+ }
+
+ if (len) {
+ ngx_memcpy(&buf[n], &key->data[1], len);
+ n += len;
+ }
+
+ buf[n] = '\0';
+
+
+ /* check conflicts in wildcard hash */
+
+ name = h->dns_hash[k].elts;
+
+ if (name) {
+ len = key->len - skip;
+
+ for (i = 0; i < h->dns_hash[k].nelts; i++) {
+ if (len != name[i].len) {
+ continue;
+ }
+
+ if (ngx_strncmp(key->data + skip, name[i].data, len) == 0) {
+ return NGX_BUSY;
+ }
+ }
+
+ } else {
+ if (ngx_array_init(&h->dns_hash[k], h->temp_pool, 4,
+ sizeof(ngx_str_t))
+ != NGX_OK)
+ {
+ return NGX_ERROR;
+ }
+ }
+
+ name = ngx_array_push(&h->dns_hash[k]);
+ if (name == NULL) {
+ return NGX_ERROR;
+ }
+
+ name->len = key->len - skip;
+ name->data = ngx_palloc(h->temp_pool, name->len);
+ if (name->data == NULL) {
+ return NGX_ERROR;
+ }
+ ngx_memcpy(name->data, key->data + skip, name->len);
+
+
+ ngx_memcpy(key->data, buf, key->len);
+ key->len--;
+
+ hk = ngx_array_push(&h->dns_wildcards);
+ if (hk == NULL) {
+ return NGX_ERROR;
+ }
+
+ hk->key = *key;
+ hk->key_hash = 0;
+ hk->value = value;
+ }
+
+ return NGX_OK;
+}
diff --git a/src/http/ngx_http_config.h b/src/http/ngx_http_config.h
index d034351d9..476808584 100644
--- a/src/http/ngx_http_config.h
+++ b/src/http/ngx_http_config.h
@@ -14,9 +14,9 @@
typedef struct {
- void **main_conf;
- void **srv_conf;
- void **loc_conf;
+ void **main_conf;
+ void **srv_conf;
+ void **loc_conf;
} ngx_http_conf_ctx_t;
@@ -72,5 +72,25 @@ typedef struct {
cycle->conf_ctx[ngx_http_module.index])->main_conf[module.ctx_index]
+#define NGX_HTTP_CONFIG_HASH 10007
+
+#define NGX_HTTP_WILDCARD_HASH 1
+
+typedef struct {
+ ngx_pool_t *pool;
+ ngx_pool_t *temp_pool;
+
+ ngx_array_t keys;
+ ngx_array_t *keys_hash;
+
+ ngx_array_t dns_wildcards;
+ ngx_array_t *dns_hash;
+} ngx_http_hash_conf_t;
+
+
+ngx_int_t ngx_http_config_add_hash(ngx_http_hash_conf_t *h, ngx_str_t *key,
+ void *value, ngx_uint_t flags);
+
+
#endif /* _NGX_HTTP_CONFIG_H_INCLUDED_ */
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index fc57fe47b..5711b4abf 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -90,6 +90,8 @@ static void *ngx_http_upstream_create_main_conf(ngx_conf_t *cf);
static char *ngx_http_core_init_main_conf(ngx_conf_t *cf, void *conf);
#if (NGX_HTTP_SSL)
+static void ngx_http_upstream_ssl_init_connection(ngx_http_request_t *,
+ ngx_http_upstream_t *u, ngx_connection_t *c);
static void ngx_http_upstream_ssl_handshake(ngx_connection_t *c);
static void ngx_http_upstream_ssl_shutdown(ngx_connection_t *c,
ngx_peer_t *peer);
@@ -498,9 +500,8 @@ ngx_http_upstream_check_broken_connection(ngx_http_request_t *r,
static void
ngx_http_upstream_connect(ngx_http_request_t *r, ngx_http_upstream_t *u)
{
- ngx_int_t rc;
- ngx_peer_t *peer;
- ngx_connection_t *c;
+ ngx_int_t rc;
+ ngx_connection_t *c;
r->connection->log->action = "connecting to upstream";
@@ -517,8 +518,7 @@ ngx_http_upstream_connect(ngx_http_request_t *r, ngx_http_upstream_t *u)
return;
}
- peer = &u->peer.peers->peer[u->peer.cur_peer];
- u->state->peer = &peer->name;
+ u->state->peer = &u->peer.peers->peer[u->peer.cur_peer].name;
if (rc == NGX_BUSY) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "no live upstreams");
@@ -534,6 +534,7 @@ ngx_http_upstream_connect(ngx_http_request_t *r, ngx_http_upstream_t *u)
c = u->peer.connection;
c->data = r;
+
c->write->handler = ngx_http_upstream_send_request_handler;
c->read->handler = ngx_http_upstream_process_header;
@@ -587,50 +588,57 @@ ngx_http_upstream_connect(ngx_http_request_t *r, ngx_http_upstream_t *u)
return;
}
- /* rc == NGX_OK */
-
#if (NGX_HTTP_SSL)
- if (u->conf->ssl) {
- if (c->ssl == NULL) {
+ if (u->conf->ssl && c->ssl == NULL) {
+ ngx_http_upstream_ssl_init_connection(r, u, c);
+ return;
+ }
- if (ngx_ssl_create_connection(u->conf->ssl, c,
- NGX_SSL_BUFFER|NGX_SSL_CLIENT)
- == NGX_ERROR)
- {
- ngx_http_upstream_finalize_request(r, u,
- NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
+#endif
- c->sendfile = 0;
- }
+ ngx_http_upstream_send_request(r, u);
+}
- if (ngx_ssl_set_session(c, peer->ssl_session) != NGX_OK) {
- ngx_http_upstream_finalize_request(r, u,
- NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
- rc = ngx_ssl_handshake(c);
+#if (NGX_HTTP_SSL)
- if (rc == NGX_AGAIN) {
- c->ssl->handler = ngx_http_upstream_ssl_handshake;
- return;
- }
+static void
+ngx_http_upstream_ssl_init_connection(ngx_http_request_t *r,
+ ngx_http_upstream_t *u, ngx_connection_t *c)
+{
+ ngx_int_t rc;
+ ngx_peer_t *peer;
- ngx_http_upstream_ssl_handshake(c);
+ if (ngx_ssl_create_connection(u->conf->ssl, c,
+ NGX_SSL_BUFFER|NGX_SSL_CLIENT)
+ == NGX_ERROR)
+ {
+ ngx_http_upstream_finalize_request(r, u,
+ NGX_HTTP_INTERNAL_SERVER_ERROR);
+ return;
+ }
+
+ c->sendfile = 0;
+ peer = &u->peer.peers->peer[u->peer.cur_peer];
+
+ if (ngx_ssl_set_session(c, peer->ssl_session) != NGX_OK) {
+ ngx_http_upstream_finalize_request(r, u,
+ NGX_HTTP_INTERNAL_SERVER_ERROR);
return;
}
-#endif
+ rc = ngx_ssl_handshake(c);
- ngx_http_upstream_send_request(r, u);
-}
+ if (rc == NGX_AGAIN) {
+ c->ssl->handler = ngx_http_upstream_ssl_handshake;
+ return;
+ }
+ ngx_http_upstream_ssl_handshake(c);
+}
-#if (NGX_HTTP_SSL)
static void
ngx_http_upstream_ssl_handshake(ngx_connection_t *c)
@@ -671,7 +679,8 @@ ngx_http_upstream_reinit(ngx_http_request_t *r, ngx_http_upstream_t *u)
sizeof(ngx_http_upstream_headers_in_t));
if (ngx_list_init(&r->upstream->headers_in.headers, r->pool, 8,
- sizeof(ngx_table_elt_t)) != NGX_OK)
+ sizeof(ngx_table_elt_t))
+ != NGX_OK)
{
return NGX_ERROR;
}
@@ -851,6 +860,15 @@ ngx_http_upstream_send_request_handler(ngx_event_t *wev)
return;
}
+#if (NGX_HTTP_SSL)
+
+ if (u->conf->ssl && c->ssl == NULL) {
+ ngx_http_upstream_ssl_init_connection(r, u, c);
+ return;
+ }
+
+#endif
+
ngx_http_upstream_send_request(r, u);
}