<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div>Добрый день!</div><div><br></div><div>Я хотел бы попросить уважаемых разработчиков nginx верифицировать работу из моего модуля с переменными. Поскольку nginx изучался  по исходным текстам, я мог опустить какие то существенные моменты и заложить ошибки для дальнейшей нестабильной работы. Если кто-нибудь из экспертов пробежится взглядом по коду (я, естественно, оставил только моменты связанные с переменными), это было бы для меня большой пользой.</div><div><br></div><div>Постановка задачи:</div><div><br></div><div>Конфигурация модуля dobro определяется в секции http и конкретное подклчение происходит в location.</div><div><span class="Apple-style-span" style="line-height: 20px; background-color: rgb(255, 255, 255); "><pre style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; white-space: pre-wrap; "><font class="Apple-style-span" face="'Courier New'"><span class="Apple-style-span" style="font-size: 13px;">http {
    dobro_config {
        dobro_amount 10m;
        dobro_timeout 10h;
    };
    server {
        location / {
            dobro on;
<span class="Apple-tab-span" style="white-space:pre"> </span>    root /;</span></font></pre><pre style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; white-space: pre-wrap; "><font class="Apple-style-span" face="'Courier New'"><span class="Apple-style-span" style="font-size: 13px;">        };
     };
};</span></font></pre></span><div><font class="Apple-style-span" face="'Courier New'" size="4"><br></font></div></div><div>Требовалось иметь возможность отключать работу модуля используя rewrite_module:</div><div><span class="Apple-style-span" style="line-height: 20px; background-color: rgb(255, 255, 255); "><pre style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; white-space: pre-wrap; "><font class="Apple-style-span" face="'Courier New'"><span class="Apple-style-span" style="font-size: 13px;">     location / {
            dobro on;
            if ($request_uri ~ /netdobra) { set $dobro_off "true"; }</span></font></pre><pre style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; white-space: pre-wrap; "><font class="Apple-style-span" face="'Courier New'"><span class="Apple-style-span" style="font-size: 13px;"><span class="Apple-tab-span" style="white-space:pre">        </span>    ...</span></font></pre><pre style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; white-space: pre-wrap; "><font class="Apple-style-span" face="'Courier New'"><span class="Apple-style-span" style="font-size: 13px;">     }</span></font></pre><pre style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; white-space: pre-wrap; "><font class="Apple-style-span" face="'Courier New'"><span class="Apple-style-span" style="font-size: 13px;"><br></span></font></pre></span><span class="Apple-style-span" style="line-height: 20px; background-color: rgb(255, 255, 255); "><pre style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; white-space: pre-wrap; "><font class="Apple-style-span" face="Helvetica">Для упрощения логики считаю, что если переменная dobro_off не определена или пуста, значит работаем как работали.</font></pre></span><span class="Apple-style-span" style="background-color: rgb(255, 255, 255); "><pre style="line-height: 20px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; white-space: pre-wrap; "><font class="Apple-style-span" face="Helvetica"><br></font></pre><pre style="line-height: 20px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; white-space: pre-wrap; "><font class="Apple-style-span" face="Helvetica">Соотвественно код. Постарался максимально сократить и дать необходимые пояснения к функциям в комментариях. Хендлер модуля регистрируется в фазе ACCESS.</font></pre><pre style="line-height: 20px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; white-space: pre-wrap; "><font class="Apple-style-span" face="Courier"><br></font></pre><pre style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "><font class="Apple-style-span" face="Courier"><span class="Apple-style-span" style="line-height: 20px; white-space: pre-wrap;">typedef struct {
    ngx_int_t index;
} ngx_http_dobro_loc_conf_t;</span></font></pre><pre style="line-height: 20px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; white-space: pre-wrap; "><font class="Apple-style-span" face="Courier"><br></font></pre><pre style="line-height: 20px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; white-space: pre-wrap; "><font class="Apple-style-span" face="Courier">#define DOBRO_NO_INDEX -1</font></pre><pre style="line-height: 20px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; white-space: pre-wrap; "><font class="Apple-style-span" face="Courier"><br></font></pre><pre style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "><font class="Apple-style-span" face="Courier"><span class="Apple-style-span" style="line-height: 20px; white-space: pre-wrap; ">/* в секции preconfiguration переменная создается */
static ngx_int_t ngx_http_dobro_add_variables(ngx_conf_t *cf) {
    ngx_http_variable_t  *var;
    var=ngx_http_add_variable(cf, &ngx_http_dobro_ignore, NGX_HTTP_VAR_CHANGEABLE);
    if (var == NULL) {
        return NGX_ERROR;
    }
    var->get_handler = ngx_http_dobro_get_variable;
    return NGX_OK;
}
/* get handler возвращает пустую переменную, модуль работает всегда, только если явно не отключен */
static ngx_int_t ngx_http_dobro_get_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) {
    *v = ngx_http_variable_null_value;
    return NGX_OK;
}

/* функция, которая обрабатывает конфигурационную строку dobro on; */
/* в момент подключения модуля в конфигурационную структуру location заносится индекс переменной, которая гарантированно создана */
static char * ngx_http_dobro_attach_pool(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) {
    ngx_str_t  *value;
    ngx_http_dobro_loc_conf_t *rlcf = conf;
   ...
    rlcf->index = ngx_http_get_variable_index(cf, &ngx_http_dobro_ignore);
    if (rlcf->index == NGX_ERROR) {
        return NGX_CONF_ERROR;
    }
..}

/* при создании конфигурационной структуры index устанавливается в -1 */
static void * ngx_http_dobro_create_loc_conf(ngx_conf_t *cf) {
    ngx_http_dobro_loc_conf_t  *conf;
    ...
    conf->index = DOBRO_NO_INDEX;
..}

/* индекс переменной наследуется при слиянии локейшнов, если еще не был определен */</span></font></pre><pre style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "><font class="Apple-style-span" face="Courier"><span class="Apple-style-span" style="line-height: 20px; white-space: pre-wrap; ">static char * ngx_http_dobro_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) {
    ngx_http_dobro_loc_conf_t  *prev = parent;
    ngx_http_dobro_loc_conf_t  *conf = child;

    if (conf->index == DOBRO_NO_INDEX)
        conf->index = prev->index;
..}

/* в функции-обработчике запроса из конфигурационной структуры берется индекс переменной,
далее проверяется что переменная существует и если ее длина не 0, то сравнивается с "0".
если переменная не равна "0" - не обрабатываем. */
static ngx_int_t ngx_http_dobro_handler(ngx_http_request_t *r) {
    ngx_http_dobro_loc_conf_t * rlcf = ngx_http_get_module_loc_conf(r, ngx_http_dobro_module);</span></font></pre><pre style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "><font class="Apple-style-span" face="Courier"><span class="Apple-style-span" style="line-height: 20px; white-space: pre-wrap; ">    ngx_http_variable_value_t *v;
...
    if (rlcf->index == DOBRO_NO_INDEX) {
        v = NULL;
    } else {
        v = ngx_http_get_indexed_variable(r, rlcf->index);
    }

    if (v != NULL && v->len > 0) {
        if (ngx_strcmp(v->data, "0") != 0) {
            return NGX_DECLINED;
        }
    }
..}</span></font></pre></span></div><div><br><div>
<div>--</div><div>С уважением,</div><div>Александр Жеглов</div><div><br></div><br class="Apple-interchange-newline">
</div>
<br></div></body></html>