summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/xml/nginx/changes.xml26
-rw-r--r--src/core/nginx.h2
-rw-r--r--src/core/ngx_conf_file.h2
-rw-r--r--src/core/ngx_core.h6
-rw-r--r--src/core/ngx_cpuinfo.c12
-rw-r--r--src/core/ngx_inet.c336
-rw-r--r--src/core/ngx_inet.h68
-rw-r--r--src/core/ngx_parse.c8
-rw-r--r--src/event/ngx_event_connect.h35
-rw-r--r--src/http/modules/ngx_http_empty_gif_module.c3
-rw-r--r--src/http/modules/ngx_http_fastcgi_module.c92
-rw-r--r--src/http/modules/ngx_http_proxy_module.c133
-rw-r--r--src/http/modules/ngx_http_ssi_filter_module.c50
-rw-r--r--src/http/modules/perl/ngx_http_perl_module.c18
-rw-r--r--src/http/ngx_http_core_module.c11
-rw-r--r--src/http/ngx_http_request.c2
-rw-r--r--src/http/ngx_http_request.h2
-rw-r--r--src/http/ngx_http_upstream.c308
-rw-r--r--src/http/ngx_http_upstream.h18
19 files changed, 891 insertions, 241 deletions
diff --git a/docs/xml/nginx/changes.xml b/docs/xml/nginx/changes.xml
index 8f77faa20..aa4f14ffe 100644
--- a/docs/xml/nginx/changes.xml
+++ b/docs/xml/nginx/changes.xml
@@ -9,6 +9,30 @@
<title lang="en">nginx changelog</title>
+<changes ver="0.3.47" date="23.05.2006">
+
+<change type="feature">
+<para lang="ru">
+директива upstream.
+</para>
+<para lang="en">
+the "upstream" directive.
+</para>
+</change>
+
+<change type="change">
+<para lang="ru">
+символ "\" в парах "\"" и "\'" в SSI командах теперь всегда убирается.
+</para>
+<para lang="en">
+now the "\" escape symbol in the "\"" and "\'" pairs in the SSI command
+is always removed.
+</para>
+</change>
+
+</changes>
+
+
<changes ver="0.3.46" date="11.05.2006">
<change type="feature">
@@ -24,7 +48,7 @@ and "fastcgi_pass_header" directives.
<change type="change">
<para lang="ru">
-директивы proxy_x_powered_by, fastcgi_x_powered_by и proxy_pass_server
+директивы proxy_pass_x_powered_by, fastcgi_x_powered_by и proxy_pass_server
упразднены.
</para>
<para lang="en">
diff --git a/src/core/nginx.h b/src/core/nginx.h
index ece57f55c..72aaa34bc 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.46"
+#define NGINX_VER "nginx/0.3.47"
#define NGINX_VAR "NGINX"
#define NGX_OLDPID_EXT ".oldbin"
diff --git a/src/core/ngx_conf_file.h b/src/core/ngx_conf_file.h
index 8f84e36a7..17c24c725 100644
--- a/src/core/ngx_conf_file.h
+++ b/src/core/ngx_conf_file.h
@@ -61,7 +61,7 @@
#define NGX_CONF_OK NULL
-#define NGX_CONF_ERROR (char *) -1
+#define NGX_CONF_ERROR (void *) -1
#define NGX_CONF_BLOCK_START 1
#define NGX_CONF_BLOCK_DONE 2
diff --git a/src/core/ngx_core.h b/src/core/ngx_core.h
index 1779513e1..cd066af35 100644
--- a/src/core/ngx_core.h
+++ b/src/core/ngx_core.h
@@ -63,6 +63,9 @@ typedef void (*ngx_connection_handler_pt)(ngx_connection_t *c);
#include <ngx_radix_tree.h>
#include <ngx_times.h>
#include <ngx_shmtx.h>
+#if (NGX_OPENSSL)
+#include <ngx_event_openssl.h>
+#endif
#include <ngx_inet.h>
#if (NGX_HAVE_UNIX_DOMAIN)
#include <ngx_unix_domain.h>
@@ -71,9 +74,6 @@ typedef void (*ngx_connection_handler_pt)(ngx_connection_t *c);
#include <ngx_process_cycle.h>
#include <ngx_conf_file.h>
#include <ngx_os.h>
-#if (NGX_OPENSSL)
-#include <ngx_event_openssl.h>
-#endif
#include <ngx_connection.h>
diff --git a/src/core/ngx_cpuinfo.c b/src/core/ngx_cpuinfo.c
index f905cbc13..2ed26b8d4 100644
--- a/src/core/ngx_cpuinfo.c
+++ b/src/core/ngx_cpuinfo.c
@@ -31,16 +31,14 @@ ngx_cpuid(uint32_t i, uint32_t *buf)
" mov %%ebx, %%esi; "
" cpuid; "
- " mov %%eax, %0; "
- " mov %%ebx, %1; "
- " mov %%edx, %2; "
- " mov %%ecx, %3; "
+ " mov %%eax, (%1); "
+ " mov %%ebx, 4(%1); "
+ " mov %%edx, 8(%1); "
+ " mov %%ecx, 12(%1); "
" mov %%esi, %%ebx; "
- : "=m" (buf[0]), "=m" (buf[1]), "=m" (buf[2]), "=m" (buf[3])
- : "a" (i)
- : "ecx", "edx", "esi" );
+ : : "a" (i), "D" (buf) : "ecx", "edx", "esi", "memory" );
}
diff --git a/src/core/ngx_inet.c b/src/core/ngx_inet.c
index a42df699b..f2b0cf78b 100644
--- a/src/core/ngx_inet.c
+++ b/src/core/ngx_inet.c
@@ -220,6 +220,339 @@ ngx_ptocidr(ngx_str_t *text, void *cidr)
}
+ngx_int_t
+ngx_parse_url(ngx_conf_t *cf, ngx_url_t *u)
+{
+ u_char *p;
+ size_t len;
+ ngx_int_t port;
+ ngx_uint_t i;
+#if (NGX_HAVE_UNIX_DOMAIN)
+ struct sockaddr_un *saun;
+#endif
+
+ len = u->url.len;
+ p = u->url.data;
+
+ if (ngx_strncasecmp(p, "unix:", 5) == 0) {
+
+#if (NGX_HAVE_UNIX_DOMAIN)
+
+ u->type = NGX_PARSE_URL_UNIX;
+
+ p += 5;
+ len -= 5;
+
+ if (u->uri_part) {
+ for (i = 0; i < len; i++) {
+
+ if (p[i] == ':') {
+ len = i;
+
+ u->uri.len -= len + 1;
+ u->uri.data += len + 1;
+
+ break;
+ }
+ }
+ }
+
+ if (len == 0) {
+ u->err = "no path in the unix domain socket";
+ return NGX_ERROR;
+ }
+
+ if (len + 1 > sizeof(saun->sun_path)) {
+ u->err = "too long path in the unix domain socket";
+ return NGX_ERROR;
+ }
+
+ u->peers = ngx_pcalloc(cf->pool, sizeof(ngx_peers_t));
+ if (u->peers == NULL) {
+ return NGX_ERROR;
+ }
+
+ saun = ngx_pcalloc(cf->pool, sizeof(struct sockaddr_un));
+ if (saun == NULL) {
+ return NGX_ERROR;
+ }
+
+ u->peers->number = 1;
+
+ saun->sun_family = AF_UNIX;
+ (void) ngx_cpystrn((u_char *) saun->sun_path, p, len + 1);
+
+ u->peers->peer[0].sockaddr = (struct sockaddr *) saun;
+ u->peers->peer[0].socklen = sizeof(struct sockaddr_un);
+ u->peers->peer[0].name = u->url;
+ u->peers->peer[0].uri_separator = ":";
+
+ u->host_header.len = sizeof("localhost") - 1;
+ u->host_header.data = (u_char *) "localhost";
+
+ return NGX_OK;
+
+#else
+ u->err = "the unix domain sockets are not supported on this platform";
+
+ return NGX_ERROR;
+
+#endif
+ }
+
+ if ((p[0] == ':' || p[0] == '/') && !u->listen) {
+ u->err = "invalid host";
+ return NGX_ERROR;
+ }
+
+ u->type = NGX_PARSE_URL_INET;
+
+ u->host.data = p;
+ u->host_header.len = len;
+ u->host_header.data = p;
+
+ for (i = 0; i < len; i++) {
+
+ if (p[i] == ':') {
+ u->port.data = &p[i + 1];
+ u->host.len = i;
+
+ if (!u->uri_part) {
+ u->port.len = &p[len] - u->port.data;
+ break;
+ }
+ }
+
+ if (p[i] == '/') {
+ u->uri.len = len - i;
+ u->uri.data = &p[i];
+ u->host_header.len = i;
+
+ if (u->host.len == 0) {
+ u->host.len = i;
+ }
+
+ if (u->port.data == NULL) {
+ u->default_port = 1;
+ goto port;
+ }
+
+ u->port.len = &p[i] - u->port.data;
+
+ if (u->port.len == 0) {
+ u->err = "invalid port";
+ return NGX_ERROR;
+ }
+
+ break;
+ }
+ }
+
+ if (u->port.data) {
+
+ if (u->port.len == 0) {
+ u->port.len = &p[i] - u->port.data;
+
+ if (u->port.len == 0) {
+ u->err = "invalid port";
+ return NGX_ERROR;
+ }
+ }
+
+ port = ngx_atoi(u->port.data, u->port.len);
+
+ if (port == NGX_ERROR || port < 1 || port > 65536) {
+ u->err = "invalid port";
+ return NGX_ERROR;
+ }
+
+ } else {
+ port = ngx_atoi(p, len);
+
+ if (port == NGX_ERROR) {
+ u->default_port = 1;
+ u->host.len = len;
+
+ goto port;
+ }
+
+ u->port.len = len;
+ u->port.data = p;
+ u->wildcard = 1;
+ }
+
+ u->portn = (in_port_t) port;
+
+port:
+
+ if (u->listen) {
+ return NGX_OK;
+ }
+
+ if (u->default_port) {
+
+ if (u->upstream) {
+ return NGX_OK;
+ }
+
+ if (u->default_portn == 0) {
+ u->err = "no port";
+ return NGX_ERROR;
+ }
+
+ u->portn = u->default_portn;
+
+ u->port.data = ngx_palloc(cf->pool, sizeof("65536") - 1);
+ if (u->port.data == NULL) {
+ return NGX_ERROR;
+ }
+
+ u->port.len = ngx_sprintf(u->port.data, "%d", u->portn) - u->port.data;
+
+ } else if (u->portn) {
+ if (u->portn == u->default_portn) {
+ u->default_port = 1;
+ }
+
+ } else {
+ u->err = "no port";
+ return NGX_ERROR;
+ }
+
+ if (u->host.len == 0) {
+ u->err = "no host";
+ return NGX_ERROR;
+ }
+
+ u->peers = ngx_inet_resolve_peer(cf, &u->host, u->portn);
+
+ if (u->peers == NULL) {
+ return NGX_ERROR;
+ }
+
+ if (u->peers == NGX_CONF_ERROR) {
+ u->err = "host not found";
+ return NGX_ERROR;
+ }
+
+ return NGX_OK;
+}
+
+
+ngx_peers_t *
+ngx_inet_resolve_peer(ngx_conf_t *cf, ngx_str_t *name, in_port_t port)
+{
+ u_char *host;
+ size_t len;
+ in_addr_t in_addr;
+ ngx_uint_t i;
+ ngx_peers_t *peers;
+ struct hostent *h;
+ struct sockaddr_in *sin;
+
+ host = ngx_palloc(cf->temp_pool, name->len + 1);
+ if (host == NULL) {
+ return NULL;
+ }
+
+ (void) ngx_cpystrn(host, name->data, name->len + 1);
+
+ /* AF_INET only */
+
+ in_addr = inet_addr((char *) host);
+
+ if (in_addr == INADDR_NONE) {
+ h = gethostbyname((char *) host);
+
+ if (h == NULL || h->h_addr_list[0] == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ for (i = 0; h->h_addr_list[i] != NULL; i++) { /* void */ }
+
+ /* MP: ngx_shared_palloc() */
+
+ peers = ngx_pcalloc(cf->pool,
+ sizeof(ngx_peers_t) + sizeof(ngx_peer_t) * (i - 1));
+ if (peers == NULL) {
+ return NULL;
+ }
+
+ peers->number = i;
+ peers->weight = 1;
+
+ for (i = 0; h->h_addr_list[i] != NULL; i++) {
+
+ sin = ngx_pcalloc(cf->pool, sizeof(struct sockaddr_in));
+ if (sin == NULL) {
+ return NULL;
+ }
+
+ sin->sin_family = AF_INET;
+ sin->sin_port = htons(port);
+ sin->sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[i]);
+
+ peers->peer[i].sockaddr = (struct sockaddr *) sin;
+ peers->peer[i].socklen = sizeof(struct sockaddr_in);
+
+ len = INET_ADDRSTRLEN - 1 + 1 + sizeof(":65536") - 1;
+
+ peers->peer[i].name.data = ngx_palloc(cf->pool, len);
+ if (peers->peer[i].name.data == NULL) {
+ return NULL;
+ }
+
+ len = ngx_sock_ntop(AF_INET, (struct sockaddr *) sin,
+ peers->peer[i].name.data, len);
+
+ peers->peer[i].name.len =
+ ngx_sprintf(&peers->peer[i].name.data[len],
+ ":%d", port)
+ - peers->peer[i].name.data;
+
+ peers->peer[i].uri_separator = "";
+ }
+
+ } else {
+
+ /* MP: ngx_shared_palloc() */
+
+ peers = ngx_pcalloc(cf->pool, sizeof(ngx_peers_t));
+ if (peers == NULL) {
+ return NULL;
+ }
+
+ sin = ngx_pcalloc(cf->pool, sizeof(struct sockaddr_in));
+ if (sin == NULL) {
+ return NULL;
+ }
+
+ peers->number = 1;
+
+ sin->sin_family = AF_INET;
+ sin->sin_port = htons(port);
+ sin->sin_addr.s_addr = in_addr;
+
+ peers->peer[0].sockaddr = (struct sockaddr *) sin;
+ peers->peer[0].socklen = sizeof(struct sockaddr_in);
+
+ peers->peer[0].name.data = ngx_palloc(cf->pool,
+ name->len + sizeof(":65536") - 1);
+ if (peers->peer[0].name.data == NULL) {
+ return NULL;
+ }
+
+ peers->peer[0].name.len = ngx_sprintf(peers->peer[0].name.data, "%V:%d",
+ name, port)
+ - peers->peer[0].name.data;
+
+ peers->peer[0].uri_separator = "";
+ }
+
+ return peers;
+}
+
+
ngx_peers_t *
ngx_inet_upstream_parse(ngx_conf_t *cf, ngx_inet_upstream_t *u)
{
@@ -241,6 +574,7 @@ ngx_inet_upstream_parse(ngx_conf_t *cf, ngx_inet_upstream_t *u)
}
if (u->default_port) {
+
if (u->default_port_value == 0) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"no port in upstream \"%V\"", &u->name);
@@ -277,7 +611,7 @@ ngx_inet_upstream_parse(ngx_conf_t *cf, ngx_inet_upstream_t *u)
u->port = htons(u->port);
- host = ngx_palloc(cf->pool, u->host.len + 1);
+ host = ngx_palloc(cf->temp_pool, u->host.len + 1);
if (host == NULL) {
return NULL;
}
diff --git a/src/core/ngx_inet.h b/src/core/ngx_inet.h
index a01fc8a70..25f923230 100644
--- a/src/core/ngx_inet.h
+++ b/src/core/ngx_inet.h
@@ -12,6 +12,10 @@
#include <ngx_core.h>
+#define NGX_PARSE_URL_INET 1
+#define NGX_PARSE_URL_UNIX 2
+
+
typedef struct {
in_addr_t addr;
in_addr_t mask;
@@ -19,6 +23,66 @@ typedef struct {
typedef struct {
+ struct sockaddr *sockaddr;
+ socklen_t socklen;
+
+ ngx_str_t name;
+ char *uri_separator;
+
+ ngx_uint_t weight;
+
+ ngx_uint_t fails;
+ time_t accessed;
+
+ ngx_uint_t max_fails;
+ time_t fail_timeout;
+
+#if (NGX_SSL)
+ ngx_ssl_session_t *ssl_session;
+#endif
+} ngx_peer_t;
+
+
+struct ngx_peers_s {
+ ngx_uint_t current;
+ ngx_uint_t weight;
+
+ ngx_uint_t number;
+ ngx_uint_t last_cached;
+
+ /* ngx_mutex_t *mutex; */
+ ngx_connection_t **cached;
+
+ ngx_peer_t peer[1];
+};
+
+
+typedef struct {
+ ngx_int_t type;
+
+ ngx_peers_t *peers;
+
+ ngx_str_t url;
+ ngx_str_t host;
+ ngx_str_t host_header;
+ ngx_str_t port;
+ ngx_str_t uri;
+
+ in_port_t portn;
+ in_port_t default_portn;
+
+ unsigned listen:1;
+ unsigned uri_part:1;
+ unsigned upstream:1;
+
+ unsigned default_port:1;
+ unsigned wildcard:1;
+
+ char *err;
+} ngx_url_t;
+
+
+typedef struct {
ngx_str_t name; /* "schema:host:port/uri" */
ngx_str_t url; /* "host:port/uri" */
ngx_str_t host;
@@ -35,6 +99,7 @@ typedef struct {
unsigned uri_part:1;
unsigned port_only:1;
+ unsigned virtual:1;
} ngx_inet_upstream_t;
@@ -45,7 +110,10 @@ size_t ngx_inet_ntop(int family, void *addr, u_char *text, size_t len);
ngx_int_t ngx_ptocidr(ngx_str_t *text, void *cidr);
ngx_peers_t *ngx_inet_upstream_parse(ngx_conf_t *cf, ngx_inet_upstream_t *u);
+ngx_peers_t *ngx_inet_resolve_peer(ngx_conf_t *cf, ngx_str_t *name,
+ in_port_t port);
char *ngx_inet_parse_host_port(ngx_inet_upstream_t *u);
+ngx_int_t ngx_parse_url(ngx_conf_t *cf, ngx_url_t *u);
#endif /* _NGX_INET_H_INCLUDED_ */
diff --git a/src/core/ngx_parse.c b/src/core/ngx_parse.c
index f8e5f6c2e..28e5d96c1 100644
--- a/src/core/ngx_parse.c
+++ b/src/core/ngx_parse.c
@@ -50,10 +50,10 @@ ngx_parse_size(ngx_str_t *line)
ngx_int_t
ngx_parse_time(ngx_str_t *line, ngx_int_t sec)
{
- size_t len;
- u_char *start, last;
- ngx_int_t value, total, scale;
- ngx_uint_t max, i;
+ size_t len;
+ u_char *start, last;
+ ngx_int_t value, total, scale;
+ ngx_uint_t max, i;
enum {
st_start = 0,
st_year,
diff --git a/src/event/ngx_event_connect.h b/src/event/ngx_event_connect.h
index f23c02fd2..61c268f37 100644
--- a/src/event/ngx_event_connect.h
+++ b/src/event/ngx_event_connect.h
@@ -14,41 +14,6 @@
typedef struct {
- struct sockaddr *sockaddr;
- socklen_t socklen;
-
- ngx_str_t name;
- char *uri_separator;
-
- ngx_uint_t weight;
-
- ngx_uint_t fails;
- time_t accessed;
-
- ngx_uint_t max_fails;
- time_t fail_timeout;
-
-#if (NGX_SSL)
- ngx_ssl_session_t *ssl_session;
-#endif
-} ngx_peer_t;
-
-
-struct ngx_peers_s {
- ngx_uint_t current;
- ngx_uint_t weight;
-
- ngx_uint_t number;
- ngx_uint_t last_cached;
-
- /* ngx_mutex_t *mutex; */
- ngx_connection_t **cached;
-
- ngx_peer_t peer[1];
-};
-
-
-typedef struct {
ngx_peers_t *peers;
ngx_uint_t cur_peer;
ngx_uint_t tries;
diff --git a/src/http/modules/ngx_http_empty_gif_module.c b/src/http/modules/ngx_http_empty_gif_module.c
index 82bf8c5e2..b97633a58 100644
--- a/src/http/modules/ngx_http_empty_gif_module.c
+++ b/src/http/modules/ngx_http_empty_gif_module.c
@@ -135,7 +135,7 @@ ngx_http_empty_gif_handler(ngx_http_request_t *r)
}
}
- b = ngx_create_temp_buf(r->pool, sizeof(ngx_empty_gif));
+ b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
if (b == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
@@ -145,6 +145,7 @@ ngx_http_empty_gif_handler(ngx_http_request_t *r)
b->pos = ngx_empty_gif;
b->last = ngx_empty_gif + sizeof(ngx_empty_gif);
+ b->memory = 1;
b->last_buf = 1;
r->headers_out.status = NGX_HTTP_OK;
diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c
index 777a7dd8b..82388a6a8 100644
--- a/src/http/modules/ngx_http_fastcgi_module.c
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -11,16 +11,17 @@
typedef struct {
- ngx_http_upstream_conf_t upstream;
+ ngx_http_upstream_conf_t upstream;
- ngx_peers_t *peers;
+ ngx_http_upstream_srv_conf_t *upstream_peers;
+ ngx_peers_t *peers0;
- ngx_str_t index;
+ ngx_str_t index;
- ngx_array_t *flushes;
- ngx_array_t *params_len;
- ngx_array_t *params;
- ngx_array_t *params_source;
+ ngx_array_t *flushes;
+ ngx_array_t *params_len;
+ ngx_array_t *params;
+ ngx_array_t *params_source;
} ngx_http_fastcgi_loc_conf_t;
@@ -39,14 +40,14 @@ typedef enum {
typedef struct {
- ngx_http_fastcgi_state_e state;
- u_char *pos;
- u_char *last;
- ngx_uint_t type;
- size_t length;
- size_t padding;
-
- ngx_uint_t fastcgi_stdout;
+ ngx_http_fastcgi_state_e state;
+ u_char *pos;
+ u_char *last;
+ ngx_uint_t type;
+ size_t length;
+ size_t padding;
+
+ ngx_uint_t fastcgi_stdout;
} ngx_http_fastcgi_ctx_t;
@@ -391,8 +392,8 @@ ngx_http_fastcgi_handler(ngx_http_request_t *r)
u->peer.log = r->connection->log;
u->peer.log_error = NGX_ERROR_ERR;
- u->peer.peers = flcf->peers;
- u->peer.tries = flcf->peers->number;
+ u->peer.peers = flcf->upstream_peers->peers;
+ u->peer.tries = flcf->upstream_peers->peers->number;
#if (NGX_THREADS)
u->peer.lock = &r->connection->lock;
#endif
@@ -1687,11 +1688,13 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_sec_value(conf->upstream.fail_timeout,
prev->upstream.fail_timeout, 10);
- if (conf->peers && conf->peers->number > 1) {
- for (i = 0; i < conf->peers->number; i++) {
- conf->peers->peer[i].weight = 1;
- conf->peers->peer[i].max_fails = conf->upstream.max_fails;
- conf->peers->peer[i].fail_timeout = conf->upstream.fail_timeout;
+ if (conf->upstream_peers && !conf->upstream_peers->balanced) {
+ for (i = 0; i < conf->upstream_peers->peers->number; i++) {
+ conf->upstream_peers->peers->peer[i].weight = 1;
+ conf->upstream_peers->peers->peer[i].max_fails =
+ conf->upstream.max_fails;
+ conf->upstream_peers->peers->peer[i].fail_timeout =
+ conf->upstream.fail_timeout;
}
}
@@ -1813,8 +1816,8 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
peers:
- if (conf->peers == NULL) {
- conf->peers = prev->peers;
+ if (conf->upstream_peers == NULL) {
+ conf->upstream_peers = prev->upstream_peers;
conf->upstream.schema = prev->upstream.schema;
}
@@ -1989,12 +1992,9 @@ ngx_http_fastcgi_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_fastcgi_loc_conf_t *lcf = conf;
+ ngx_url_t u;
ngx_str_t *value;
- ngx_inet_upstream_t inet_upstream;
ngx_http_core_loc_conf_t *clcf;
-#if (NGX_HAVE_UNIX_DOMAIN)
- ngx_unix_domain_upstream_t unix_upstream;
-#endif
if (lcf->upstream.schema.len) {
return "is duplicate";
@@ -2002,40 +2002,14 @@ ngx_http_fastcgi_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
value = cf->args->elts;
- if (ngx_strncasecmp(value[1].data, "unix:", 5) == 0) {
-
-#if (NGX_HAVE_UNIX_DOMAIN)
-
- ngx_memzero(&unix_upstream, sizeof(ngx_unix_domain_upstream_t));
-
- unix_upstream.name = value[1];
- unix_upstream.url = value[1];
-
- lcf->peers = ngx_unix_upstream_parse(cf, &unix_upstream);
- if (lcf->peers == NULL) {
- return NGX_CONF_ERROR;
- }
+ ngx_memzero(&u, sizeof(ngx_url_t));
- lcf->peers->peer[0].uri_separator = "";
+ u.url = value[1];
+ u.upstream = 1;
-#else
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "the unix domain sockets are not supported "
- "on this platform");
+ lcf->upstream_peers = ngx_http_upstream_add(cf, &u);
+ if (lcf->upstream_peers == NULL) {
return NGX_CONF_ERROR;
-
-#endif
-
- } else {
- ngx_memzero(&inet_upstream, sizeof(ngx_inet_upstream_t));
-
- inet_upstream.name = value[1];
- inet_upstream.url = value[1];
-
- lcf->peers = ngx_inet_upstream_parse(cf, &inet_upstream);
- if (lcf->peers == NULL) {
- return NGX_CONF_ERROR;
- }
}
lcf->upstream.schema.len = sizeof("fastcgi://") - 1;
diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c
index dd66bfabc..f5fb9184b 100644
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -16,56 +16,56 @@ typedef ngx_int_t (*ngx_http_proxy_redirect_pt)(ngx_http_request_t *r,
ngx_table_elt_t *h, size_t prefix, ngx_http_proxy_redirect_t *pr);
struct ngx_http_proxy_redirect_s {
- ngx_http_proxy_redirect_pt handler;
- ngx_str_t redirect;
+ ngx_http_proxy_redirect_pt handler;
+ ngx_str_t redirect;
union {
- ngx_str_t text;
+ ngx_str_t text;
struct {
- void *lengths;
- void *values;
+ void *lengths;
+ void *values;
} vars;
- void *regex;
+ void *regex;
} replacement;
};
typedef struct {
- ngx_http_upstream_conf_t upstream;
+ ngx_http_upstream_conf_t upstream;
- ngx_peers_t *peers;
+ ngx_http_upstream_srv_conf_t *upstream_peers;
- ngx_array_t *flushes;
- ngx_array_t *body_set_len;
- ngx_array_t *body_set;
- ngx_array_t *headers_set_len;
- ngx_array_t *headers_set;
- ngx_hash_t headers_set_hash;
+ ngx_array_t *flushes;
+ ngx_array_t *body_set_len;
+ ngx_array_t *body_set;
+ ngx_array_t *headers_set_len;
+ ngx_array_t *headers_set;
+ ngx_hash_t headers_set_hash;
- ngx_array_t *headers_source;
- ngx_array_t *headers_names;
+ ngx_array_t *headers_source;
+ ngx_array_t *headers_names;
- ngx_array_t *redirects;
+ ngx_array_t *redirects;
- ngx_str_t body_source;
+ ngx_str_t body_source;
- ngx_str_t method;
- ngx_str_t host_header;
- ngx_str_t port_text;
+ ngx_str_t method;
+ ngx_str_t host_header;
+ ngx_str_t port_text;
- ngx_flag_t redirect;
+ ngx_flag_t redirect;
} ngx_http_proxy_loc_conf_t;
typedef struct {
- ngx_uint_t status;
- ngx_uint_t status_count;
- u_char *status_start;
- u_char *status_end;
+ ngx_uint_t status;
+ ngx_uint_t status_count;
+ u_char *status_start;
+ u_char *status_end;
- size_t internal_body_length;
+ size_t internal_body_length;
} ngx_http_proxy_ctx_t;
@@ -407,8 +407,8 @@ ngx_http_proxy_handler(ngx_http_request_t *r)
u->peer.log = r->connection->log;
u->peer.log_error = NGX_ERROR_ERR;
- u->peer.peers = plcf->peers;
- u->peer.tries = plcf->peers->number;
+ u->peer.peers = plcf->upstream_peers->peers;
+ u->peer.tries = plcf->upstream_peers->peers->number;
#if (NGX_THREADS)
u->peer.lock = &r->connection->lock;
#endif
@@ -1640,11 +1640,13 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_sec_value(conf->upstream.fail_timeout,
prev->upstream.fail_timeout, 10);
- if (conf->peers && conf->peers->number > 1) {
- for (i = 0; i < conf->peers->number; i++) {
- conf->peers->peer[i].weight = 1;
- conf->peers->peer[i].max_fails = conf->upstream.max_fails;
- conf->peers->peer[i].fail_timeout = conf->upstream.fail_timeout;
+ if (conf->upstream_peers && !conf->upstream_peers->balanced) {
+ for (i = 0; i < conf->upstream_peers->peers->number; i++) {
+ conf->upstream_peers->peers->peer[i].weight = 1;
+ conf->upstream_peers->peers->peer[i].max_fails =
+ conf->upstream.max_fails;
+ conf->upstream_peers->peers->peer[i].fail_timeout =
+ conf->upstream.fail_timeout;
}
}
@@ -1797,8 +1799,8 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
peers:
- if (conf->peers == NULL) {
- conf->peers = prev->peers;
+ if (conf->upstream_peers == NULL) {
+ conf->upstream_peers = prev->upstream_peers;
conf->host_header = prev->host_header;
conf->port_text = prev->port_text;
@@ -2106,14 +2108,11 @@ ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
size_t add;
u_short port;
ngx_str_t *value, *url;
- ngx_inet_upstream_t inet_upstream;
+ ngx_url_t u;
ngx_http_core_loc_conf_t *clcf;
#if (NGX_HTTP_SSL)
ngx_pool_cleanup_t *cln;
#endif
-#if (NGX_HAVE_UNIX_DOMAIN)
- ngx_unix_domain_upstream_t unix_upstream;
-#endif
if (plcf->upstream.schema.len) {
return "is duplicate";
@@ -2167,53 +2166,23 @@ ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_ERROR;
}
- if (ngx_strncasecmp(url->data + add, "unix:", 5) == 0) {
-
-#if (NGX_HAVE_UNIX_DOMAIN)
-
- ngx_memzero(&unix_upstream, sizeof(ngx_unix_domain_upstream_t));
-
- unix_upstream.name = *url;
- unix_upstream.url.len = url->len - add;
- unix_upstream.url.data = url->data + add;
- unix_upstream.uri_part = 1;
-
- plcf->peers = ngx_unix_upstream_parse(cf, &unix_upstream);
- if (plcf->peers == NULL) {
- return NGX_CONF_ERROR;
- }
+ ngx_memzero(&u, sizeof(ngx_url_t));
- plcf->host_header.len = sizeof("localhost") - 1;
- plcf->host_header.data = (u_char *) "localhost";
- plcf->upstream.uri = unix_upstream.uri;
+ u.url.len = url->len - add;
+ u.url.data = url->data + add;
+ u.default_portn = port;
+ u.uri_part = 1;
+ u.upstream = 1;
-#else
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "the unix domain sockets are not supported "
- "on this platform");
+ plcf->upstream_peers = ngx_http_upstream_add(cf, &u);
+ if (plcf->upstream_peers == NULL) {
return NGX_CONF_ERROR;
-
-#endif
-
- } else {
- ngx_memzero(&inet_upstream, sizeof(ngx_inet_upstream_t));
-
- inet_upstream.name = *url;
- inet_upstream.url.len = url->len - add;
- inet_upstream.url.data = url->data + add;
- inet_upstream.default_port_value = port;
- inet_upstream.uri_part = 1;
-
- plcf->peers = ngx_inet_upstream_parse(cf, &inet_upstream);
- if (plcf->peers == NULL) {
- return NGX_CONF_ERROR;
- }
-
- plcf->host_header = inet_upstream.host_header;
- plcf->port_text = inet_upstream.port_text;
- plcf->upstream.uri = inet_upstream.uri;
}
+ plcf->host_header = u.host_header;
+ plcf->port_text = u.port;
+ plcf->upstream.uri = u.uri;
+
plcf->upstream.schema.len = add;
plcf->upstream.schema.data = url->data;
diff --git a/src/http/modules/ngx_http_ssi_filter_module.c b/src/http/modules/ngx_http_ssi_filter_module.c
index 5024d0021..817045e95 100644
--- a/src/http/modules/ngx_http_ssi_filter_module.c
+++ b/src/http/modules/ngx_http_ssi_filter_module.c
@@ -1224,38 +1224,14 @@ ngx_http_ssi_parse(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx)
case ssi_quoted_symbol_state:
state = ctx->saved_state;
- if (ch == '\\') {
- break;
- }
-
- if (ch == '"' && state == ssi_double_quoted_value_state) {
- ctx->param->value.data[ctx->param->value.len - 1] = ch;
- break;
- }
-
- if (ch == '\'' && state == ssi_quoted_value_state) {
- ctx->param->value.data[ctx->param->value.len - 1] = ch;
- break;
- }
-
- if (ctx->param->value.len == ctx->value_len) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "too long \"%V%c...\" value of \"%V\" "
- "parameter in \"%V\" SSI command",
- &ctx->param->value, ch, &ctx->param->key,
- &ctx->command);
- state = ssi_error_state;
- break;
- }
-
ctx->param->value.data[ctx->param->value.len++] = ch;
break;
case ssi_postparam_state:
- if (ctx->param->value.len < ctx->value_len / 2) {
- value = ngx_palloc(r->pool, ctx->param->value.len);
+ if (ctx->param->value.len + 1 < ctx->value_len / 2) {
+ value = ngx_palloc(r->pool, ctx->param->value.len + 1);
if (value == NULL) {
return NGX_ERROR;
}
@@ -1433,7 +1409,7 @@ ngx_http_ssi_evaluate_string(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
size_t *size, len, prefix, part_len;
ngx_str_t var, *val;
ngx_int_t key;
- ngx_uint_t i, j, n, bracket;
+ ngx_uint_t i, j, n, bracket, quoted;
ngx_array_t lengths, values;
ngx_http_variable_value_t *vv;
@@ -1567,18 +1543,28 @@ ngx_http_ssi_evaluate_string(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
} else {
part_data = &text->data[i];
+ quoted = 0;
for (p = part_data; i < text->len; i++) {
ch = text->data[i];
- if (ch == '$') {
- if (text->data[i - 1] != '\\') {
+ if (!quoted) {
+
+ if (ch == '\\') {
+ quoted = 1;
+ continue;
+ }
+
+ if (ch == '$') {
break;
}
- *(p - 1) = ch;
+ } else {
+ quoted = 0;
- continue;
+ if (ch != '\\' && ch != '\'' && ch != '"' && ch != '$') {
+ *p++ = '\\';
+ }
}
*p++ = ch;
@@ -2016,7 +2002,7 @@ ngx_http_ssi_if(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
flags = 0;
if (p < last - 1 && p[0] == '\\' && p[1] == '/') {
- p++;
+ p++;
}
}
diff --git a/src/http/modules/perl/ngx_http_perl_module.c b/src/http/modules/perl/ngx_http_perl_module.c
index 6b7298c63..975c727c8 100644
--- a/src/http/modules/perl/ngx_http_perl_module.c
+++ b/src/http/modules/perl/ngx_http_perl_module.c
@@ -399,6 +399,24 @@ ngx_http_perl_ssi(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ssi_ctx,
dTHXa(ctx->perl);
+#if 0
+
+ /* the code is disabled to force the precompiled perl code using only */
+
+ ngx_http_perl_eval_anon_sub(aTHX_ handler, &sv);
+
+ if (sv == &PL_sv_undef) {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "eval_pv(\"%V\") failed", handler);
+ return NGX_ERROR;
+ }
+
+ if (sv == NULL) {
+ sv = newSVpvn((char *) handler->data, handler->len);
+ }
+
+#endif
+
sv = newSVpvn((char *) handler->data, handler->len);
rc = ngx_http_perl_call_handler(aTHX_ r, sv, &params[NGX_HTTP_PERL_SSI_ARG],
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index 5403fdbda..6cbbf09e7 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -106,7 +106,7 @@ static ngx_command_t ngx_http_core_commands[] = {
NULL },
{ ngx_string("server"),
- NGX_HTTP_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
+ NGX_HTTP_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_MULTI|NGX_CONF_NOARGS,
ngx_http_core_server,
0,
0,
@@ -506,7 +506,6 @@ ngx_http_handler(ngx_http_request_t *r)
r->valid_unparsed_uri = 1;
r->valid_location = 1;
r->uri_changed = 1;
- r->uri_changes = NGX_HTTP_MAX_REWRITE_CYCLES + 1;
r->phase = (r == r->main) ? NGX_HTTP_POST_READ_PHASE:
NGX_HTTP_SERVER_REWRITE_PHASE;
@@ -547,7 +546,7 @@ ngx_http_core_run_phases(ngx_http_request_t *r)
if (r->uri_changes == 0) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "rewrite cycle");
+ "rewrite or internal redirection cycle");
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
return;
}
@@ -1263,6 +1262,8 @@ ngx_http_subrequest(ngx_http_request_t *r,
sr->discard_body = r->discard_body;
sr->main_filter_need_in_memory = r->main_filter_need_in_memory;
+ sr->uri_changes = NGX_HTTP_MAX_URI_CHANGES + 1;
+
ngx_http_handler(sr);
if (!c->destroyed) {
@@ -1331,6 +1332,8 @@ ngx_http_internal_redirect(ngx_http_request_t *r,
r->internal = 1;
r->method = NGX_HTTP_GET;
+ r->uri_changes--;
+
ngx_http_handler(r);
return NGX_DONE;
@@ -1794,7 +1797,7 @@ ngx_http_core_create_main_conf(ngx_conf_t *cf)
if (ngx_array_init(&cmcf->servers, cf->pool, 4,
sizeof(ngx_http_core_srv_conf_t *))
- == NGX_ERROR)
+ != NGX_OK)
{
return NGX_CONF_ERROR;
}
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index d8d8936d0..4f7d24fa5 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -666,6 +666,8 @@ ngx_http_process_request_line(ngx_event_t *rev)
c->write->handler = ngx_http_request_handler;
r->read_event_handler = ngx_http_block_read;
+ r->uri_changes = NGX_HTTP_MAX_URI_CHANGES + 1;
+
ngx_http_handler(r);
return;
diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h
index a8aa98397..a694ee553 100644
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -8,7 +8,7 @@
#define _NGX_HTTP_REQUEST_H_INCLUDED_
-#define NGX_HTTP_MAX_REWRITE_CYCLES 10
+#define NGX_HTTP_MAX_URI_CHANGES 10
/* must be 2^n */
#define NGX_HTTP_LC_HEADER_LEN 32
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index 5eaad79d6..4b914abd8 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -85,8 +85,12 @@ static ngx_int_t ngx_http_upstream_status_variable(ngx_http_request_t *r,
static ngx_int_t ngx_http_upstream_response_time_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
+static char *ngx_http_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy);
+static char *ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd,
+ void *conf);
+
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_upstream_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 *,
@@ -206,12 +210,32 @@ ngx_http_upstream_header_t ngx_http_upstream_headers_in[] = {
};
-ngx_http_module_t ngx_http_upstream_module_ctx = {
+static ngx_command_t ngx_http_upstream_commands[] = {
+
+ { ngx_string("upstream"),
+ NGX_HTTP_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE1,
+ ngx_http_upstream,
+ 0,
+ 0,
+ NULL },
+
+ { ngx_string("server"),
+ NGX_HTTP_UPS_CONF|NGX_CONF_TAKE1,
+ ngx_http_upstream_server,
+ NGX_HTTP_SRV_CONF_OFFSET,
+ 0,
+ NULL },
+
+ ngx_null_command
+};
+
+
+static ngx_http_module_t ngx_http_upstream_module_ctx = {
ngx_http_upstream_add_variables, /* preconfiguration */
NULL, /* postconfiguration */
ngx_http_upstream_create_main_conf, /* create main configuration */
- ngx_http_core_init_main_conf, /* init main configuration */
+ ngx_http_upstream_init_main_conf, /* init main configuration */
NULL, /* create server configuration */
NULL, /* merge server configuration */
@@ -224,7 +248,7 @@ ngx_http_module_t ngx_http_upstream_module_ctx = {
ngx_module_t ngx_http_upstream_module = {
NGX_MODULE_V1,
&ngx_http_upstream_module_ctx, /* module context */
- NULL, /* module directives */
+ ngx_http_upstream_commands, /* module directives */
NGX_HTTP_MODULE, /* module type */
NULL, /* init master */
NULL, /* init module */
@@ -868,6 +892,14 @@ ngx_http_upstream_send_request_handler(ngx_event_t *wev)
#endif
+ if (u->header_sent) {
+ wev->handler = ngx_http_upstream_dummy_handler;
+
+ (void) ngx_handle_write_event(wev, 0);
+
+ return;
+ }
+
ngx_http_upstream_send_request(r, u);
}
@@ -2547,6 +2579,232 @@ ngx_http_upstream_response_time_variable(ngx_http_request_t *r,
}
+static char *
+ngx_http_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
+{
+ char *rv;
+ void *mconf;
+ ngx_str_t *value;
+ ngx_url_t u;
+ ngx_uint_t i, j, m, n;
+ ngx_conf_t pcf;
+ ngx_peers_t **peers;
+ ngx_http_module_t *module;
+ ngx_http_conf_ctx_t *ctx;
+ ngx_http_upstream_srv_conf_t *uscf;
+
+ ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
+ if (ctx == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ ngx_memzero(&u, sizeof(ngx_url_t));
+
+ value = cf->args->elts;
+ u.host = value[1];
+
+ uscf = ngx_http_upstream_add(cf, &u);
+ if (uscf == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ /* the upstream{}'s srv_conf */
+
+ ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
+ if (ctx->srv_conf == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ ctx->srv_conf[ngx_http_upstream_module.ctx_index] = uscf;
+
+
+ /* the upstream{}'s loc_conf */
+
+ ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
+ if (ctx->loc_conf == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ for (m = 0; ngx_modules[m]; m++) {
+ if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
+ continue;
+ }
+
+ module = ngx_modules[m]->ctx;
+
+ if (module->create_loc_conf) {
+ mconf = module->create_loc_conf(cf);
+ if (mconf == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ ctx->loc_conf[ngx_modules[m]->ctx_index] = mconf;
+ }
+ }
+
+
+ /* parse inside upstream{} */
+
+ pcf = *cf;
+ cf->ctx = ctx;
+ cf->cmd_type = NGX_HTTP_UPS_CONF;
+
+ rv = ngx_conf_parse(cf, NULL);
+
+ *cf = pcf;
+
+ if (rv != NGX_CONF_OK) {
+ return rv;
+ }
+
+ if (uscf->servers == NULL) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "no servers are inside upstream");
+ return NGX_CONF_ERROR;
+ }
+
+ peers = uscf->servers->elts;
+
+ if (uscf->servers->nelts == 1) {
+ uscf->peers = peers[0];
+ }
+
+ n = 0;
+
+ for (i = 0; i < uscf->servers->nelts; i++) {
+ n += peers[i]->number;
+ }
+
+ uscf->peers = ngx_pcalloc(cf->pool,
+ sizeof(ngx_peers_t) + sizeof(ngx_peer_t) * (n - 1));
+ if (uscf->peers == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ uscf->peers->number = n;
+ uscf->peers->weight = 1;
+
+ n = 0;
+
+ for (i = 0; i < uscf->servers->nelts; i++) {
+ for (j = 0; j < peers[i]->number; j++) {
+ uscf->peers->peer[n++] = peers[i]->peer[j];
+ }
+ }
+
+ return rv;
+}
+
+
+static char *
+ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+ ngx_http_upstream_srv_conf_t *uscf = conf;
+
+ ngx_str_t *value;
+ ngx_url_t u;
+ ngx_peers_t **peers;
+
+ if (uscf->servers == NULL) {
+ uscf->servers = ngx_array_create(cf->pool, 4, sizeof(ngx_peers_t *));
+ if (uscf->servers == NULL) {
+ return NGX_CONF_ERROR;
+ }
+ }
+
+ peers = ngx_array_push(uscf->servers);
+ if (peers == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ value = cf->args->elts;
+
+ ngx_memzero(&u, sizeof(ngx_url_t));
+
+ u.url = value[1];
+ u.default_portn = 80;
+
+ if (ngx_parse_url(cf, &u) != NGX_OK) {
+ if (u.err) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "%s in upstream \"%V\"", u.err, &u.url);
+ }
+
+ return NGX_CONF_ERROR;
+ }
+
+ *peers = u.peers;
+
+ return NGX_CONF_OK;
+}
+
+
+ngx_http_upstream_srv_conf_t *
+ngx_http_upstream_add(ngx_conf_t *cf, ngx_url_t *u)
+{
+ ngx_uint_t i;
+ ngx_http_upstream_srv_conf_t *uscf, **uscfp;
+ ngx_http_upstream_main_conf_t *umcf;
+
+ if (u->upstream) {
+ if (ngx_parse_url(cf, u) != NGX_OK) {
+ if (u->err) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "%s in upstream \"%V\"", u->err, &u->url);
+ }
+
+ return NULL;
+ }
+
+ if (u->peers) {
+ uscf = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_srv_conf_t));
+ if (uscf == NULL) {
+ return NULL;
+ }
+
+ uscf->peers = u->peers;
+
+ return uscf;
+ }
+ }
+
+ umcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_upstream_module);
+
+ uscfp = umcf->upstreams.elts;
+
+ for (i = 0; i < umcf->upstreams.nelts; i++) {
+ if (uscfp[i]->host.len != u->host.len) {
+ continue;
+ }
+
+ if (ngx_strncasecmp(uscfp[i]->host.data, u->host.data, u->host.len)
+ == 0)
+ {
+ return uscfp[i];
+ }
+ }
+
+ uscf = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_srv_conf_t));
+ if (uscf == NULL) {
+ return NULL;
+ }
+
+ uscf->host = u->host;
+ uscf->file_name = cf->conf_file->file.name;
+ uscf->line = cf->conf_file->line;
+ uscf->port = u->default_portn;
+
+ uscfp = ngx_array_push(&umcf->upstreams);
+ if (uscfp == NULL) {
+ return NULL;
+ }
+
+ *uscfp = uscf;
+
+ return uscf;
+}
+
+
static void *
ngx_http_upstream_create_main_conf(ngx_conf_t *cf)
{
@@ -2557,19 +2815,51 @@ ngx_http_upstream_create_main_conf(ngx_conf_t *cf)
return NULL;
}
+ if (ngx_array_init(&umcf->upstreams, cf->pool, 4,
+ sizeof(ngx_http_upstream_srv_conf_t *))
+ != NGX_OK)
+ {
+ return NGX_CONF_ERROR;
+ }
+
return umcf;
}
static char *
-ngx_http_core_init_main_conf(ngx_conf_t *cf, void *conf)
+ngx_http_upstream_init_main_conf(ngx_conf_t *cf, void *conf)
{
ngx_http_upstream_main_conf_t *umcf = conf;
- ngx_array_t headers_in;
- ngx_hash_key_t *hk;
- ngx_hash_init_t hash;
- ngx_http_upstream_header_t *header;
+ ngx_uint_t i;
+ ngx_array_t headers_in;
+ ngx_hash_key_t *hk;
+ ngx_hash_init_t hash;
+ ngx_http_upstream_header_t *header;
+ ngx_http_upstream_srv_conf_t **uscfp;
+
+ uscfp = umcf->upstreams.elts;
+
+ for (i = 0; i < umcf->upstreams.nelts; i++) {
+ if (uscfp[i]->peers) {
+ continue;
+ }
+
+ uscfp[i]->peers = ngx_inet_resolve_peer(cf, &uscfp[i]->host,
+ uscfp[i]->port);
+
+ if (uscfp[i]->peers == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ if (uscfp[i]->peers == NGX_CONF_ERROR) {
+ ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+ "upstream host \"%V\" is not found in %s:%ui",
+ &uscfp[i]->host, uscfp[i]->file_name.data,
+ uscfp[i]->line);
+ return NGX_CONF_ERROR;
+ }
+ }
if (ngx_array_init(&headers_in, cf->temp_pool, 32, sizeof(ngx_hash_key_t))
!= NGX_OK)
diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h
index e61c0bcc0..f8668307a 100644
--- a/src/http/ngx_http_upstream.h
+++ b/src/http/ngx_http_upstream.h
@@ -42,10 +42,26 @@ typedef struct {
typedef struct {
ngx_hash_t headers_in_hash;
+ ngx_array_t upstreams;
+ /* ngx_http_upstream_srv_conf_t */
} ngx_http_upstream_main_conf_t;
typedef struct {
+ ngx_peers_t *peers;
+
+ ngx_array_t *servers;
+
+ ngx_str_t host;
+ ngx_str_t file_name;
+ ngx_uint_t line;
+ in_port_t port;
+
+ ngx_uint_t balanced; /* unsigned balanced:1; */
+} ngx_http_upstream_srv_conf_t;
+
+
+typedef struct {
ngx_msec_t connect_timeout;
ngx_msec_t send_timeout;
ngx_msec_t read_timeout;
@@ -199,6 +215,8 @@ struct ngx_http_upstream_s {
void ngx_http_upstream_init(ngx_http_request_t *r);
+ngx_http_upstream_srv_conf_t *ngx_http_upstream_add(ngx_conf_t *cf,
+ ngx_url_t *u);
extern ngx_module_t ngx_http_upstream_module;