nginx-0.3.17-RELEASE import

*) 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; the bug had
       appeared in 0.2.4.

    *) Bugfix: in the HTTPS protocol in the "proxy_pass" directive.

    *) Bugfix: when the HTTPS protocol was used in the "proxy_pass"
       directive the port 80 was used by default.
This commit is contained in:
Igor Sysoev 2005-12-18 16:02:44 +00:00
parent d10f2fb86f
commit 43f279dc9c
11 changed files with 472 additions and 250 deletions

View File

@ -38,7 +38,7 @@ fi
ngx_feature="epoll" ngx_feature="epoll"
ngx_feature_name="NGX_HAVE_EPOLL" ngx_feature_name="NGX_HAVE_EPOLL"
ngx_feature_run=no ngx_feature_run=yes
ngx_feature_incs="#include <sys/epoll.h>" ngx_feature_incs="#include <sys/epoll.h>"
ngx_feature_libs= ngx_feature_libs=
ngx_feature_test="int efd = 0, fd = 1, n; ngx_feature_test="int efd = 0, fd = 1, n;
@ -62,12 +62,14 @@ fi
CC_AUX_FLAGS="-D_GNU_SOURCE" CC_AUX_FLAGS="-D_GNU_SOURCE"
ngx_feature="sendfile()" ngx_feature="sendfile()"
ngx_feature_name="NGX_HAVE_SENDFILE" ngx_feature_name="NGX_HAVE_SENDFILE"
ngx_feature_run=no ngx_feature_run=yes
ngx_feature_incs="#include <sys/sendfile.h>" ngx_feature_incs="#include <sys/sendfile.h>
#include <errno.h>"
ngx_feature_libs= ngx_feature_libs=
ngx_feature_test="int s = 0, fd = 1; ngx_feature_test="int s = 0, fd = 1;
ssize_t n; off_t off = 0; 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 . auto/feature
if [ $ngx_found = yes ]; then if [ $ngx_found = yes ]; then
@ -80,12 +82,14 @@ fi
CC_AUX_FLAGS="-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64" CC_AUX_FLAGS="-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64"
ngx_feature="sendfile64()" ngx_feature="sendfile64()"
ngx_feature_name="NGX_HAVE_SENDFILE64" ngx_feature_name="NGX_HAVE_SENDFILE64"
ngx_feature_run=no ngx_feature_run=yes
ngx_feature_incs="#include <sys/sendfile.h>" ngx_feature_incs="#include <sys/sendfile.h>
#include <errno.h>"
ngx_feature_libs= ngx_feature_libs=
ngx_feature_test="int s = 0, fd = 1; ngx_feature_test="int s = 0, fd = 1;
ssize_t n; off_t off = 0; 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 . auto/feature

View File

@ -266,6 +266,7 @@ HTTP_DEPS="src/http/ngx_http.h \
HTTP_SRCS="src/http/ngx_http.c \ HTTP_SRCS="src/http/ngx_http.c \
src/http/ngx_http_core_module.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_special_response.c \
src/http/ngx_http_request.c \ src/http/ngx_http_request.c \
src/http/ngx_http_parse.c \ src/http/ngx_http_parse.c \

View File

@ -9,6 +9,58 @@
<title lang="en">nginx changelog</title> <title lang="en">nginx changelog</title>
<changes ver="0.3.17" date="18.12.2005">
<change type="change">
<para lang="ru">
ÎÁ Linux configure ÔÅÐÅÒØ ÐÒÏ×ÅÒÑÅÔ ÎÁÌÉÞÉÅ epoll É sendfile64() × ÑÄÒÅ.
</para>
<para lang="en">
now on Linux configure checks the presence of epoll and sendfile64() in kernel.
</para>
</change>
<change type="feature">
<para lang="ru">
ÄÉÒÅËÔÉ×Á map ÐÏÄÄÅÒÖÉ×ÁÅÔ ÄÏÍÅÎÎÙÅ ÉÍÅÎÁ × ÆÏÒÍÁÔÅ ".domain.tld".
</para>
<para lang="en">
the "map" directive supports domain names in the ".domain.tld" form.
</para>
</change>
<change type="bugfix">
<para lang="ru">
×Ï ×ÒÅÍÑ SSL handshake ÎÅ ÉcÐÏÌØÚÏ×ÁÌÉÓØ ÔÁÊÍÁÕÔÙ.
</para>
<para lang="en">
the timeouts were not used in SSL handshake.
</para>
</change>
<change type="bugfix">
<para lang="ru">
× ÉÓÐÏÌØÚÏ×ÁÎÉÉ ÐÒÏÔÏËÏÌÁ HTTPS × ÄÉÒÅËÔÉ×Å proxy_pass.
</para>
<para lang="en">
in the HTTP protocol in the "proxy_pass" directive.
</para>
</change>
<change type="bugfix">
<para lang="ru">
ÐÒÉ ÉÓÐÏÌØÚÏ×ÁÎÉÉ ÐÒÏÔÏËÏÌÁ HTTPS × ÄÉÒÅËÔÉ×Å proxy_pass ÐÏ ÕÍÏÌÞÁÎÉÀ
ÉÓÐÏÌØÚÏ×ÁÌÓÑ ÐÏÒÔ 80.
</para>
<para lang="en">
when the HTTP protocol was used in the "proxy_pass" directive the port 80
was used by default.
</para>
</change>
</changes>
<changes ver="0.3.16" date="16.12.2005"> <changes ver="0.3.16" date="16.12.2005">
<change type="feature"> <change type="feature">
@ -383,7 +435,7 @@ the "if" directive supports the "=" and "!=" operations.
ÄÉÒÅËÔÉ×Á proxy_pass ÐÏÄÄÅÒÖÉ×ÁÅÔ ÐÒÏÔÏËÏÌ HTTPS. ÄÉÒÅËÔÉ×Á proxy_pass ÐÏÄÄÅÒÖÉ×ÁÅÔ ÐÒÏÔÏËÏÌ HTTPS.
</para> </para>
<para lang="en"> <para lang="en">
the "proxy_set_body" directive supports the HTTPS protocol. the "proxy_pass" directive supports the HTTPS protocol.
</para> </para>
</change> </change>

View File

@ -8,7 +8,7 @@
#define _NGINX_H_INCLUDED_ #define _NGINX_H_INCLUDED_
#define NGINX_VER "nginx/0.3.16" #define NGINX_VER "nginx/0.3.17"
#define NGINX_VAR "NGINX" #define NGINX_VAR "NGINX"
#define NGX_OLDPID_EXT ".oldbin" #define NGX_OLDPID_EXT ".oldbin"

View File

@ -76,10 +76,6 @@ ngx_hash_find_wildcard(ngx_hash_wildcard_t *hwc, u_char *name, size_t len)
n--; n--;
} }
if (n == 0) {
return NULL;
}
key = 0; key = 0;
for (i = n; i < len; i++) { 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); value = ngx_hash_find(&hwc->hash, key, &name[n], len - n);
if (value) { 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) { 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); 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) ngx_uint_t nelts)
{ {
size_t len; size_t len;
ngx_uint_t i, n; ngx_uint_t i, n, dot;
ngx_array_t curr_names, next_names; ngx_array_t curr_names, next_names;
ngx_hash_key_t *name, *next_name; ngx_hash_key_t *name, *next_name;
ngx_hash_init_t h; 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); "wc0: \"%V\"", &names[n].key);
#endif #endif
dot = 0;
for (len = 0; len < names[n].key.len; len++) { for (len = 0; len < names[n].key.len; len++) {
if (names[n].key.data[len] == '.') { if (names[n].key.data[len] == '.') {
len++; dot = 1;
break; break;
} }
} }
@ -371,7 +389,7 @@ ngx_hash_wildcard_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names,
return NGX_ERROR; return NGX_ERROR;
} }
name->key.len = len - 1; name->key.len = len;
name->key.data = names[n].key.data; name->key.data = names[n].key.data;
name->key_hash = hinit->key(name->key.data, name->key.len); name->key_hash = hinit->key(name->key.data, name->key.len);
name->value = names[n].value; 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); "wc1: \"%V\"", &name->key);
#endif #endif
if (dot) {
len++;
}
next_names.nelts = 0; next_names.nelts = 0;
if (names[n].key.len != len) { 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 #if 0
ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0, ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0,
"wc2: \"%V\"", &next_name->key); "wc3: \"%V\"", &next_name->key);
#endif #endif
} }
@ -442,7 +464,7 @@ ngx_hash_wildcard_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names,
#endif #endif
} }
name->value = (void *) ((uintptr_t) wdc | 1); name->value = (void *) ((uintptr_t) wdc | (dot ? 1 : 3));
} }
} }

View File

@ -334,6 +334,7 @@ ngx_ssl_handshake(ngx_connection_t *c)
if (sslerr == SSL_ERROR_WANT_READ) { if (sslerr == SSL_ERROR_WANT_READ) {
c->read->ready = 0; c->read->ready = 0;
c->read->handler = ngx_ssl_handshake_handler; c->read->handler = ngx_ssl_handshake_handler;
c->write->handler = ngx_ssl_handshake_handler;
if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) { if (ngx_handle_read_event(c->read, 0) == NGX_ERROR) {
return NGX_ERROR; return NGX_ERROR;
@ -344,6 +345,7 @@ ngx_ssl_handshake(ngx_connection_t *c)
if (sslerr == SSL_ERROR_WANT_WRITE) { if (sslerr == SSL_ERROR_WANT_WRITE) {
c->write->ready = 0; c->write->ready = 0;
c->read->handler = ngx_ssl_handshake_handler;
c->write->handler = ngx_ssl_handshake_handler; c->write->handler = ngx_ssl_handshake_handler;
if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) { 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_wait_shutdown = 1;
c->ssl->no_send_shutdown = 1; c->ssl->no_send_shutdown = 1;
c->read->eof = 1;
if (sslerr == SSL_ERROR_ZERO_RETURN || ERR_peek_error() == 0) { if (sslerr == SSL_ERROR_ZERO_RETURN || ERR_peek_error() == 0) {
ngx_log_error(NGX_LOG_INFO, c->log, err, ngx_log_error(NGX_LOG_INFO, c->log, err,
@ -365,6 +368,8 @@ ngx_ssl_handshake(ngx_connection_t *c)
return NGX_ERROR; return NGX_ERROR;
} }
c->read->error = 1;
ngx_ssl_connection_error(c, sslerr, err, "SSL_do_handshake() failed"); ngx_ssl_connection_error(c, sslerr, err, "SSL_do_handshake() failed");
return NGX_ERROR; 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, ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
"SSL handshake handler: %d", ev->write); "SSL handshake handler: %d", ev->write);
if (ev->timedout) {
c->ssl->handler(c);
return;
}
if (ngx_ssl_handshake(c) == NGX_AGAIN) { if (ngx_ssl_handshake(c) == NGX_AGAIN) {
return; return;
} }
@ -548,6 +558,7 @@ ngx_ssl_handle_recv(ngx_connection_t *c, int n)
return NGX_DONE; return NGX_DONE;
} }
c->read->error = 1;
ngx_ssl_connection_error(c, sslerr, err, "SSL_read() failed"); ngx_ssl_connection_error(c, sslerr, err, "SSL_read() failed");
return NGX_ERROR; 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_wait_shutdown = 1;
c->ssl->no_send_shutdown = 1; c->ssl->no_send_shutdown = 1;
c->write->error = 1;
ngx_ssl_connection_error(c, sslerr, err, "SSL_write() failed"); ngx_ssl_connection_error(c, sslerr, err, "SSL_write() failed");
@ -795,6 +807,7 @@ ngx_int_t
ngx_ssl_shutdown(ngx_connection_t *c) ngx_ssl_shutdown(ngx_connection_t *c)
{ {
int n, sslerr, mode; int n, sslerr, mode;
ngx_err_t err;
ngx_uint_t again; ngx_uint_t again;
if (c->timedout) { if (c->timedout) {
@ -866,7 +879,9 @@ ngx_ssl_shutdown(ngx_connection_t *c)
return NGX_AGAIN; 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); SSL_free(c->ssl->connection);
c->ssl = NULL; c->ssl = NULL;

View File

@ -9,8 +9,6 @@
#include <ngx_http.h> #include <ngx_http.h>
#define NGX_HTTP_MAP_HASH 10007
typedef struct { typedef struct {
ngx_uint_t hash_max_size; ngx_uint_t hash_max_size;
ngx_uint_t hash_bucket_size; ngx_uint_t hash_bucket_size;
@ -18,13 +16,7 @@ typedef struct {
typedef struct { typedef struct {
ngx_pool_t *pool; ngx_http_hash_conf_t hash;
ngx_array_t keys;
ngx_array_t *keys_hash;
ngx_array_t dns_wildcards;
ngx_array_t *dns_hash;
ngx_array_t *values_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; 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_OK)
{ {
ngx_destroy_pool(pool); ngx_destroy_pool(pool);
return NGX_CONF_ERROR; 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_OK)
{ {
ngx_destroy_pool(pool); ngx_destroy_pool(pool);
return NGX_CONF_ERROR; return NGX_CONF_ERROR;
} }
ctx.keys_hash = ngx_pcalloc(pool, sizeof(ngx_array_t) * NGX_HTTP_MAP_HASH); ctx.hash.keys_hash = ngx_pcalloc(pool,
if (ctx.keys_hash == NULL) { sizeof(ngx_array_t) * NGX_HTTP_CONFIG_HASH);
if (ctx.hash.keys_hash == NULL) {
ngx_destroy_pool(pool); ngx_destroy_pool(pool);
return NGX_CONF_ERROR; return NGX_CONF_ERROR;
} }
ctx.dns_hash = ngx_pcalloc(pool, sizeof(ngx_array_t) * NGX_HTTP_MAP_HASH); ctx.hash.dns_hash = ngx_pcalloc(pool,
if (ctx.dns_hash == NULL) { sizeof(ngx_array_t) * NGX_HTTP_CONFIG_HASH);
if (ctx.hash.dns_hash == NULL) {
ngx_destroy_pool(pool); ngx_destroy_pool(pool);
return NGX_CONF_ERROR; return NGX_CONF_ERROR;
} }
ctx.values_hash = ngx_pcalloc(pool, 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) { if (ctx.values_hash == NULL) {
ngx_destroy_pool(pool); ngx_destroy_pool(pool);
return NGX_CONF_ERROR; return NGX_CONF_ERROR;
} }
ctx.pool = cf->pool; ctx.hash.pool = cf->pool;
ctx.hash.temp_pool = pool;
ctx.default_value = NULL; ctx.default_value = NULL;
ctx.hostnames = 0; 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.name = "map_hash";
hash.pool = cf->pool; hash.pool = cf->pool;
if (ctx.keys.nelts) { if (ctx.hash.keys.nelts) {
hash.hash = &map->hash; hash.hash = &map->hash;
hash.temp_pool = NULL; 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; 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: map->default_value = ctx.default_value ? ctx.default_value:
&ngx_http_variable_null_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); sizeof(ngx_hash_key_t), ngx_http_map_cmp_dns_wildcards);
hash.hash = NULL; hash.hash = NULL;
hash.temp_pool = pool; hash.temp_pool = pool;
if (ngx_hash_wildcard_init(&hash, ctx.dns_wildcards.elts, if (ngx_hash_wildcard_init(&hash, ctx.hash.dns_wildcards.elts,
ctx.dns_wildcards.nelts) ctx.hash.dns_wildcards.nelts)
!= NGX_OK) != NGX_OK)
{ {
return NGX_CONF_ERROR; return NGX_CONF_ERROR;
@ -363,13 +362,12 @@ ngx_http_map_cmp_dns_wildcards(const void *one, const void *two)
static char * static char *
ngx_http_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) ngx_http_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
{ {
size_t len; u_char ch;
ngx_str_t *value, file, *name; ngx_int_t rc;
ngx_uint_t i, n, key; ngx_str_t *value, file;
ngx_hash_key_t *m; ngx_uint_t i, key, flags;
ngx_http_map_conf_ctx_t *ctx; ngx_http_map_conf_ctx_t *ctx;
ngx_http_variable_value_t *var, *old, **vp; ngx_http_variable_value_t *var, **vp;
u_char buf[2048];
ctx = cf->ctx; 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_hash(key, value[1].data[i]);
} }
key %= NGX_HTTP_MAP_HASH; key %= NGX_HTTP_CONFIG_HASH;
vp = ctx->values_hash[key].elts; 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) { if (var == NULL) {
return NGX_CONF_ERROR; return NGX_CONF_ERROR;
} }
var->len = value[1].len; 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) { if (var->data == NULL) {
return NGX_CONF_ERROR; return NGX_CONF_ERROR;
} }
@ -459,179 +457,54 @@ ngx_http_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
found: found:
if (value[0].data[0] != '*' || ctx->hostnames == 0) { ch = value[0].data[0];
if (ngx_strcmp(value[0].data, "default") != 0) { if ((ch != '*' && ch != '.') || ctx->hostnames == 0) {
if (value[0].len && value[0].data[0] == '!') { if (ngx_strcmp(value[0].data, "default") == 0) {
if (ctx->default_value) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"duplicate default map parameter");
return NGX_CONF_ERROR;
}
ctx->default_value = var;
return NGX_CONF_OK;
}
if (value[0].len && ch == '!') {
value[0].len--; value[0].len--;
value[0].data++; value[0].data++;
} }
key = 0; flags = 0;
for (i = 0; i < value[0].len; i++) { } else {
value[0].data[i] = ngx_tolower(value[0].data[i]);
key = ngx_hash(key, value[0].data[i]);
}
key %= NGX_HTTP_MAP_HASH; if ((ch == '*' && (value[0].len < 3 || value[0].data[1] != '.'))
|| (ch == '.' && value[0].len < 2))
name = ctx->keys_hash[key].elts;
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;
}
ctx->default_value = var;
}
} else {
if (value[0].len < 3 || value[0].data[1] != '.') {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"invalid DNS wildcard \"%V\"", &value[0]); "invalid DNS wildcard \"%V\"", &value[0]);
return NGX_CONF_ERROR; return NGX_CONF_ERROR;
} }
key = 0; flags = NGX_HTTP_WILDCARD_HASH;
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; rc = ngx_http_config_add_hash(&ctx->hash, &value[0], var, flags);
/* 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++;
}
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;
}
}
name = ngx_array_push(&ctx->dns_hash[key]);
if (name == NULL) {
return NGX_CONF_ERROR;
}
*name = value[0];
ngx_memcpy(value[0].data, buf, value[0].len);
value[0].len--;
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;
}
if (rc == NGX_OK) {
return NGX_CONF_OK; return NGX_CONF_OK;
}
duplicate: if (rc == NGX_BUSY) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"conflicting parameter \"%V\"", &value[0]);
}
ngx_conf_log_error(NGX_LOG_WARN, cf, 0, return NGX_CONF_ERROR;
"duplicate parameter \"%V\", value: \"%V\", "
"old value: \"%V\"",
&value[0], var, old);
return NGX_CONF_OK;
} }

View File

@ -1926,6 +1926,7 @@ ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
size_t add; size_t add;
ngx_str_t *value, *url; ngx_str_t *value, *url;
ngx_uint_t port;
ngx_inet_upstream_t inet_upstream; ngx_inet_upstream_t inet_upstream;
ngx_http_core_loc_conf_t *clcf; ngx_http_core_loc_conf_t *clcf;
#if (NGX_HTTP_SSL) #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) { if (ngx_strncasecmp(url->data, "http://", 7) == 0) {
add = 7; add = 7;
port = 80;
} else if (ngx_strncasecmp(url->data, "https://", 8) == 0) { } else if (ngx_strncasecmp(url->data, "https://", 8) == 0) {
#if (NGX_HTTP_SSL) #if (NGX_HTTP_SSL)
add = 8; add = 8;
port = 443;
plcf->upstream.ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t)); plcf->upstream.ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t));
if (plcf->upstream.ssl == NULL) { 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.name = *url;
inet_upstream.url.len = url->len - add; inet_upstream.url.len = url->len - add;
inet_upstream.url.data = url->data + 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; inet_upstream.uri_part = 1;
plcf->peers = ngx_inet_upstream_parse(cf, &inet_upstream); 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.uri = inet_upstream.uri;
} }
plcf->upstream.schema.len = sizeof("http://") - 1; plcf->upstream.schema.len = add;
plcf->upstream.schema.data = (u_char *) "http://"; plcf->upstream.schema.data = url->data;
clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);

214
src/http/ngx_http_config.c Normal file
View File

@ -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;
}

View File

@ -72,5 +72,25 @@ typedef struct {
cycle->conf_ctx[ngx_http_module.index])->main_conf[module.ctx_index] 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_ */ #endif /* _NGX_HTTP_CONFIG_H_INCLUDED_ */

View File

@ -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); static char *ngx_http_core_init_main_conf(ngx_conf_t *cf, void *conf);
#if (NGX_HTTP_SSL) #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_handshake(ngx_connection_t *c);
static void ngx_http_upstream_ssl_shutdown(ngx_connection_t *c, static void ngx_http_upstream_ssl_shutdown(ngx_connection_t *c,
ngx_peer_t *peer); ngx_peer_t *peer);
@ -499,7 +501,6 @@ static void
ngx_http_upstream_connect(ngx_http_request_t *r, ngx_http_upstream_t *u) ngx_http_upstream_connect(ngx_http_request_t *r, ngx_http_upstream_t *u)
{ {
ngx_int_t rc; ngx_int_t rc;
ngx_peer_t *peer;
ngx_connection_t *c; ngx_connection_t *c;
r->connection->log->action = "connecting to upstream"; 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; return;
} }
peer = &u->peer.peers->peer[u->peer.cur_peer]; u->state->peer = &u->peer.peers->peer[u->peer.cur_peer].name;
u->state->peer = &peer->name;
if (rc == NGX_BUSY) { if (rc == NGX_BUSY) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "no live upstreams"); 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 = u->peer.connection;
c->data = r; c->data = r;
c->write->handler = ngx_http_upstream_send_request_handler; c->write->handler = ngx_http_upstream_send_request_handler;
c->read->handler = ngx_http_upstream_process_header; c->read->handler = ngx_http_upstream_process_header;
@ -587,12 +588,27 @@ ngx_http_upstream_connect(ngx_http_request_t *r, ngx_http_upstream_t *u)
return; return;
} }
/* rc == NGX_OK */ #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);
}
#if (NGX_HTTP_SSL) #if (NGX_HTTP_SSL)
if (u->conf->ssl) { static void
if (c->ssl == NULL) { 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;
if (ngx_ssl_create_connection(u->conf->ssl, c, if (ngx_ssl_create_connection(u->conf->ssl, c,
NGX_SSL_BUFFER|NGX_SSL_CLIENT) NGX_SSL_BUFFER|NGX_SSL_CLIENT)
@ -604,7 +620,8 @@ ngx_http_upstream_connect(ngx_http_request_t *r, ngx_http_upstream_t *u)
} }
c->sendfile = 0; c->sendfile = 0;
}
peer = &u->peer.peers->peer[u->peer.cur_peer];
if (ngx_ssl_set_session(c, peer->ssl_session) != NGX_OK) { if (ngx_ssl_set_session(c, peer->ssl_session) != NGX_OK) {
ngx_http_upstream_finalize_request(r, u, ngx_http_upstream_finalize_request(r, u,
@ -620,18 +637,9 @@ ngx_http_upstream_connect(ngx_http_request_t *r, ngx_http_upstream_t *u)
} }
ngx_http_upstream_ssl_handshake(c); ngx_http_upstream_ssl_handshake(c);
return;
}
#endif
ngx_http_upstream_send_request(r, u);
} }
#if (NGX_HTTP_SSL)
static void static void
ngx_http_upstream_ssl_handshake(ngx_connection_t *c) 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)); sizeof(ngx_http_upstream_headers_in_t));
if (ngx_list_init(&r->upstream->headers_in.headers, r->pool, 8, 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; return NGX_ERROR;
} }
@ -851,6 +860,15 @@ ngx_http_upstream_send_request_handler(ngx_event_t *wev)
return; 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); ngx_http_upstream_send_request(r, u);
} }