Mercurial > hg > nginx-vendor-1-0
diff src/http/ngx_http_upstream.c @ 200:d2ae1c9f1fd3 NGINX_0_3_47
nginx 0.3.47
*) Feature: the "upstream" directive.
*) Change: now the "\" escape symbol in the "\"" and "\'" pairs in the
SSI command is always removed.
author | Igor Sysoev <http://sysoev.ru> |
---|---|
date | Tue, 23 May 2006 00:00:00 +0400 |
parents | e6da4931e0e0 |
children | ca5f86d94316 |
line wrap: on
line diff
--- 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_statu 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_ups }; -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_mod 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(n #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 } +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_c 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)