ngx_http_redis_module (SELECT command)

Sergey A. Osokin osa at MAcomnet.ru
Sat Sep 19 22:07:38 MSD 2009


Патч для поддержки команды SELECT протокола redis.
Патч добавляет конфигурационную переменную $redis_db, указывающую
номер базы данных redis.

Пример конфигурационного файла:

http
{
 ...
        server {
                location / {
                        set $redis_db   "0";
                        set $redis_key  "$uri?$args";
                        redis_pass      127.0.0.1:6379;
                        error_page      404 502 504 = @fallback;
                }

                location @fallback {
                        proxy_pass      backed;
                }
        }
}


diff -ruN ngx_http_redis_module.c.orig ngx_http_redis_module.c
--- ngx_http_redis_module.c.orig	2009-09-14 16:42:56.000000000 +0400
+++ ngx_http_redis_module.c	2009-09-19 17:40:04.000000000 +0400
@@ -15,6 +15,7 @@
 typedef struct {
     ngx_http_upstream_conf_t   upstream;
     ngx_int_t                  index;
+    ngx_int_t                  db;
 } ngx_http_redis_loc_conf_t;
 
 
@@ -131,6 +132,7 @@
 
 
 static ngx_str_t  ngx_http_redis_key = ngx_string("redis_key");
+static ngx_str_t  ngx_http_redis_db  = ngx_string("redis_db");
 
 
 #define NGX_HTTP_REDIS_END   (sizeof(ngx_http_redis_end) - 1)
@@ -234,11 +236,20 @@
     ngx_buf_t                      *b;
     ngx_chain_t                    *cl;
     ngx_http_redis_ctx_t           *ctx;
-    ngx_http_variable_value_t      *vv;
+    ngx_http_variable_value_t      *vv, *vvdb;
     ngx_http_redis_loc_conf_t      *rlcf;
 
     rlcf = ngx_http_get_module_loc_conf(r, ngx_http_redis_module);
 
+    vvdb = ngx_http_get_indexed_variable(r, rlcf->db);
+
+    if (vvdb == NULL || vvdb->not_found || vvdb->len == 0) {
+        len = sizeof("select 0") - 1;
+    } else {
+        len = sizeof("select ") - 1 + vvdb->len;
+    }
+    len += sizeof(CRLF) - 1;
+
     vv = ngx_http_get_indexed_variable(r, rlcf->index);
 
     if (vv == NULL || vv->not_found || vv->len == 0) {
@@ -249,7 +260,7 @@
 
     escape = 2 * ngx_escape_uri(NULL, vv->data, vv->len, NGX_ESCAPE_REDIS);
 
-    len = sizeof("get ") - 1 + vv->len + escape + sizeof(CRLF) - 1;
+    len += sizeof("get ") - 1 + vv->len + escape + sizeof(CRLF) - 1;
 
     b = ngx_create_temp_buf(r->pool, len);
     if (b == NULL) {
@@ -266,6 +277,23 @@
 
     r->upstream->request_bufs = cl;
 
+    *b->last++ = 's'; *b->last++ = 'e'; *b->last++ = 'l'; *b->last++ = 'e';
+    *b->last++ = 'c'; *b->last++ = 't'; *b->last++ = ' ';
+
+    ctx = ngx_http_get_module_ctx(r, ngx_http_redis_module);
+
+    ctx->key.data = b->last;
+
+    if (vvdb == NULL || vvdb->not_found || vvdb->len == 0) {
+        *b->last++ = '0';
+    } else {
+        b->last = ngx_copy(b->last, vvdb->data, vvdb->len);
+        ctx->key.len = b->last - ctx->key.data;
+    }
+
+    *b->last++ = CR; *b->last++ = LF;
+
+
     *b->last++ = 'g'; *b->last++ = 'e'; *b->last++ = 't'; *b->last++ = ' ';
 
     ctx = ngx_http_get_module_ctx(r, ngx_http_redis_module);
@@ -330,6 +358,20 @@
 
     ctx = ngx_http_get_module_ctx(r, ngx_http_redis_module);
 
+    if (ngx_strcmp(p, "-ERR") == 0) {
+        ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
+                      "error was received from redis");
+
+        u->headers_in.status_n = 404;
+        u->state->status = 404;
+
+        return NGX_OK;
+    }
+
+    if (ngx_strcmp(p, "+OK\x0d") == 0) {
+        p += sizeof("+OK") - 1 + sizeof(CRLF) - 1;
+    }
+
     if (ngx_strcmp(p, "$-1\x0d") == 0) {
         ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
                       "key: \"%V\" was not found by redis", &ctx->key);
@@ -526,6 +568,7 @@
     conf->upstream.pass_request_body = 0;
 
     conf->index = NGX_CONF_UNSET;
+    conf->db = NGX_CONF_UNSET;
 
     return conf;
 }
@@ -569,6 +612,10 @@
         conf->index = prev->index;
     }
 
+    if (conf->db == NGX_CONF_UNSET) {
+        conf->db = prev->db;
+    }
+
     return NGX_CONF_OK;
 }
 
@@ -612,6 +659,12 @@
         return NGX_CONF_ERROR;
     }
 
+    rlcf->db = ngx_http_get_variable_index(cf, &ngx_http_redis_db);
+
+    if (rlcf->db == NGX_ERROR) {
+        return NGX_CONF_ERROR;
+    }
+
     return NGX_CONF_OK;
 }
 

-- 
Sergey A. Osokin
osa at FreeBSD.ORG.ru
osa at FreeBSD.ORG
osa at MAcomnet.ru





More information about the nginx-ru mailing list