--- ngx_http_redis-0.3.7/ngx_http_redis_module.c 2013-11-28 20:41:16.000000000 -0800 +++ ngx_http_redis-0.3.7-patched2/ngx_http_redis_module.c 2015-01-29 12:35:38.610133438 -0800 @@ -18,6 +18,8 @@ typedef struct { ngx_int_t index; ngx_int_t db; ngx_uint_t gzip_flag; + + ngx_http_complex_value_t *complex_target; /* for redis_pass */ } ngx_http_redis_loc_conf_t; @@ -44,6 +46,9 @@ static char *ngx_http_redis_merge_loc_co static char *ngx_http_redis_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +static ngx_http_upstream_srv_conf_t * + ngx_http_redis_upstream_add(ngx_http_request_t *r, ngx_url_t *url); + static ngx_conf_bitmask_t ngx_http_redis_next_upstream_masks[] = { { ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR }, @@ -185,11 +190,43 @@ ngx_http_redis_handler(ngx_http_request_ return NGX_HTTP_INTERNAL_SERVER_ERROR; } + rlcf = ngx_http_get_module_loc_conf(r, ngx_http_redis_module); + if (rlcf->complex_target) { + ngx_str_t target; + ngx_url_t url; + + /* variables used in the redis_pass directive */ + + if (ngx_http_complex_value(r, rlcf->complex_target, &target) + != NGX_OK) + { + return NGX_ERROR; + } + + if (target.len == 0) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "handler: empty \"redis_pass\" target"); + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + url.host = target; + url.port = 0; + url.default_port = 6379; + url.no_resolve = 1; + + rlcf->upstream.upstream = ngx_http_redis_upstream_add(r, &url); + + if (rlcf->upstream.upstream == NULL) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "redis: upstream \"%V\" not found", &target); + + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + } + #if defined nginx_version && nginx_version >= 8011 if (ngx_http_upstream_create(r) != NGX_OK) { #else - rlcf = ngx_http_get_module_loc_conf(r, ngx_http_redis_module); - u = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_t)); if (u == NULL) { #endif @@ -214,9 +251,7 @@ ngx_http_redis_handler(ngx_http_request_ u->peer.log_error = NGX_ERROR_ERR; #endif -#if defined nginx_version && nginx_version >= 8011 - rlcf = ngx_http_get_module_loc_conf(r, ngx_http_redis_module); -#else +#if !defined(nginx_version) || nginx_version < 8011 u->output.tag = (ngx_buf_tag_t) &ngx_http_redis_module; #endif @@ -845,24 +880,15 @@ ngx_http_redis_pass(ngx_conf_t *cf, ngx_ ngx_str_t *value; ngx_url_t u; + ngx_uint_t n; ngx_http_core_loc_conf_t *clcf; + ngx_http_compile_complex_value_t ccv; + if (rlcf->upstream.upstream) { return "is duplicate"; } - value = cf->args->elts; - - ngx_memzero(&u, sizeof(ngx_url_t)); - - u.url = value[1]; - u.no_resolve = 1; - - rlcf->upstream.upstream = ngx_http_upstream_add(cf, &u, 0); - if (rlcf->upstream.upstream == NULL) { - return NGX_CONF_ERROR; - } - clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); clcf->handler = ngx_http_redis_handler; @@ -879,6 +905,41 @@ ngx_http_redis_pass(ngx_conf_t *cf, ngx_ rlcf->db = ngx_http_get_variable_index(cf, &ngx_http_redis_db); + value = cf->args->elts; + + n = ngx_http_script_variables_count(&value[1]); + if (n) { + rlcf->complex_target = ngx_palloc(cf->pool, + sizeof(ngx_http_complex_value_t)); + + if (rlcf->complex_target == NULL) { + return NGX_CONF_ERROR; + } + + ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); + ccv.cf = cf; + ccv.value = &value[1]; + ccv.complex_value = rlcf->complex_target; + + if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } + + return NGX_CONF_OK; + } + + rlcf->complex_target = NULL; + + ngx_memzero(&u, sizeof(ngx_url_t)); + + u.url = value[1]; + u.no_resolve = 1; + + rlcf->upstream.upstream = ngx_http_upstream_add(cf, &u, 0); + if (rlcf->upstream.upstream == NULL) { + return NGX_CONF_ERROR; + } + return NGX_CONF_OK; } @@ -916,3 +977,41 @@ ngx_http_redis_add_variables(ngx_conf_t return NGX_OK; } + + +static ngx_http_upstream_srv_conf_t * +ngx_http_redis_upstream_add(ngx_http_request_t *r, ngx_url_t *url) +{ + ngx_http_upstream_main_conf_t *umcf; + ngx_http_upstream_srv_conf_t **uscfp; + ngx_uint_t i; + + umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module); + + uscfp = umcf->upstreams.elts; + + for (i = 0; i < umcf->upstreams.nelts; i++) { + + if (uscfp[i]->host.len != url->host.len + || ngx_strncasecmp(uscfp[i]->host.data, url->host.data, + url->host.len) != 0) + { + continue; + } + + if (uscfp[i]->port != url->port) { + continue; + } + + if (uscfp[i]->default_port + && url->default_port + && uscfp[i]->default_port != url->default_port) + { + continue; + } + + return uscfp[i]; + } + + return NULL; +}