<div dir="ltr">Fixed whitespaces.<div>It seems that patch over trunk and over 1.11.10 tag differ only in dates and hashes.</div><div><br></div><div><br></div><div><div># HG changeset patch</div><div># User Evgenii Kliuchnikov <<a href="mailto:eustas.ru@gmail.com">eustas.ru@gmail.com</a>></div><div># Date 1487932524 -3600</div><div># Fri Feb 24 11:35:24 2017 +0100</div><div># Node ID 662115ad250f48cfdd7963de40bfe7c7c8ae8ba3</div><div># Parent 1ad0999a7ded3d4fb01c7acf8ff57c80b643da7e</div><div>Add brotli static serving support (ontoZZ 1.11.10)</div><div><br></div><div>Both .gz and .br static content is served by</div><div>ngx_http_gzip_static_modile, but have separate configuration.</div><div><br></div><div>diff -r 1ad0999a7ded -r 662115ad250f contrib/vim/syntax/nginx.vim</div><div>--- a/contrib/vim/syntax/nginx.vim<span class="gmail-Apple-tab-span" style="white-space:pre"> </span>Tue Feb 14 18:36:04 2017 +0300</div><div>+++ b/contrib/vim/syntax/nginx.vim<span class="gmail-Apple-tab-span" style="white-space:pre"> </span>Fri Feb 24 11:35:24 2017 +0100</div><div>@@ -86,6 +86,7 @@</div><div> syn keyword ngxDirective autoindex</div><div> syn keyword ngxDirective autoindex_exact_size</div><div> syn keyword ngxDirective autoindex_localtime</div><div>+syn keyword ngxDirective brotli_static</div><div> syn keyword ngxDirective charset</div><div> syn keyword ngxDirective charset_types</div><div> syn keyword ngxDirective chunked_transfer_encoding</div><div>diff -r 1ad0999a7ded -r 662115ad250f src/http/modules/ngx_http_gzip_static_module.c</div><div>--- a/src/http/modules/ngx_http_gzip_static_module.c<span class="gmail-Apple-tab-span" style="white-space:pre"> </span>Tue Feb 14 18:36:04 2017 +0300</div><div>+++ b/src/http/modules/ngx_http_gzip_static_module.c<span class="gmail-Apple-tab-span" style="white-space:pre"> </span>Fri Feb 24 11:35:24 2017 +0100</div><div>@@ -16,10 +16,14 @@</div><div> </div><div> </div><div> typedef struct {</div><div>- ngx_uint_t enable;</div><div>+ ngx_uint_t enable_gzip;</div><div>+ ngx_uint_t enable_brotli;</div><div> } ngx_http_gzip_static_conf_t;</div><div> </div><div> </div><div>+static ngx_int_t ngx_http_gzip_static_serve_file(ngx_http_request_t *r,</div><div>+ ngx_uint_t enable, ngx_uint_t ok, ngx_http_core_loc_conf_t *clcf,</div><div>+ ngx_str_t *encoding);</div><div> static ngx_int_t ngx_http_gzip_static_handler(ngx_http_request_t *r);</div><div> static void *ngx_http_gzip_static_create_conf(ngx_conf_t *cf);</div><div> static char *ngx_http_gzip_static_merge_conf(ngx_conf_t *cf, void *parent,</div><div>@@ -41,7 +45,14 @@</div><div> NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,</div><div> ngx_conf_set_enum_slot,</div><div> NGX_HTTP_LOC_CONF_OFFSET,</div><div>- offsetof(ngx_http_gzip_static_conf_t, enable),</div><div>+ offsetof(ngx_http_gzip_static_conf_t, enable_gzip),</div><div>+ &ngx_http_gzip_static },</div><div>+</div><div>+ { ngx_string("brotli_static"),</div><div>+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,</div><div>+ ngx_conf_set_enum_slot,</div><div>+ NGX_HTTP_LOC_CONF_OFFSET,</div><div>+ offsetof(ngx_http_gzip_static_conf_t, enable_brotli),</div><div> &ngx_http_gzip_static },</div><div> </div><div> ngx_null_command</div><div>@@ -79,19 +90,14 @@</div><div> };</div><div> </div><div> </div><div>+static ngx_str_t encoding_gzip = ngx_string("gzip");</div><div>+static ngx_str_t encoding_brotli = ngx_string("br");</div><div>+</div><div>+</div><div> static ngx_int_t</div><div> ngx_http_gzip_static_handler(ngx_http_request_t *r)</div><div> {</div><div>- u_char *p;</div><div>- size_t root;</div><div>- ngx_str_t path;</div><div> ngx_int_t rc;</div><div>- ngx_uint_t level;</div><div>- ngx_log_t *log;</div><div>- ngx_buf_t *b;</div><div>- ngx_chain_t out;</div><div>- ngx_table_elt_t *h;</div><div>- ngx_open_file_info_t of;</div><div> ngx_http_core_loc_conf_t *clcf;</div><div> ngx_http_gzip_static_conf_t *gzcf;</div><div> </div><div>@@ -105,19 +111,56 @@</div><div> </div><div> gzcf = ngx_http_get_module_loc_conf(r, ngx_http_gzip_static_module);</div><div> </div><div>- if (gzcf->enable == NGX_HTTP_GZIP_STATIC_OFF) {</div><div>+ if (gzcf->enable_gzip == NGX_HTTP_GZIP_STATIC_OFF</div><div>+ && gzcf->enable_brotli == NGX_HTTP_GZIP_STATIC_OFF) {</div><div> return NGX_DECLINED;</div><div> }</div><div> </div><div>- if (gzcf->enable == NGX_HTTP_GZIP_STATIC_ON) {</div><div>- rc = ngx_http_gzip_ok(r);</div><div>+ clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);</div><div> </div><div>- } else {</div><div>- /* always */</div><div>- rc = NGX_OK;</div><div>+ rc = NGX_DECLINED;</div><div>+ if (gzcf->enable_gzip != NGX_HTTP_GZIP_STATIC_OFF) {</div><div>+ if (gzcf->enable_gzip == NGX_HTTP_GZIP_STATIC_ON) {</div><div>+ rc = ngx_http_gzip_ok(r);</div><div>+ } else {</div><div>+ /* always */</div><div>+ rc = NGX_OK;</div><div>+ }</div><div>+ rc = ngx_http_gzip_static_serve_file(r, gzcf->enable_gzip, rc, clcf,</div><div>+ &encoding_gzip);</div><div> }</div><div> </div><div>- clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);</div><div>+ if (gzcf->enable_brotli != NGX_HTTP_GZIP_STATIC_OFF && rc == NGX_DECLINED) {</div><div>+ if (gzcf->enable_gzip == NGX_HTTP_GZIP_STATIC_ON) {</div><div>+ rc = ngx_http_gzip_ok(r);</div><div>+ } else {</div><div>+ /* always */</div><div>+ rc = NGX_OK;</div><div>+ }</div><div>+ rc = ngx_http_gzip_static_serve_file(r, gzcf->enable_brotli, rc, clcf,</div><div>+ &encoding_brotli);</div><div>+ }</div><div>+</div><div>+ return rc;</div><div>+}</div><div>+</div><div>+</div><div>+static ngx_int_t</div><div>+ngx_http_gzip_static_serve_file(ngx_http_request_t *r, ngx_uint_t enable,</div><div>+ ngx_uint_t ok, ngx_http_core_loc_conf_t *clcf, ngx_str_t *encoding)</div><div>+{</div><div>+ u_char *p;</div><div>+ size_t root;</div><div>+ ngx_str_t path;</div><div>+ ngx_int_t rc;</div><div>+ ngx_uint_t level;</div><div>+ ngx_log_t *log;</div><div>+ ngx_buf_t *b;</div><div>+ ngx_chain_t out;</div><div>+ ngx_table_elt_t *h;</div><div>+ ngx_open_file_info_t of;</div><div>+</div><div>+ rc = ok;</div><div> </div><div> if (!clcf->gzip_vary && rc != NGX_OK) {</div><div> return NGX_DECLINED;</div><div>@@ -125,14 +168,14 @@</div><div> </div><div> log = r->connection->log;</div><div> </div><div>- p = ngx_http_map_uri_to_path(r, &path, &root, sizeof(".gz") - 1);</div><div>+ p = ngx_http_map_uri_to_path(r, &path, &root, 4 - 1);</div><div> if (p == NULL) {</div><div> return NGX_HTTP_INTERNAL_SERVER_ERROR;</div><div> }</div><div> </div><div> *p++ = '.';</div><div>- *p++ = 'g';</div><div>- *p++ = 'z';</div><div>+ *p++ = encoding->data[0];</div><div>+ *p++ = encoding->data[1];</div><div> *p = '\0';</div><div> </div><div> path.len = p - path.data;</div><div>@@ -188,7 +231,7 @@</div><div> return NGX_DECLINED;</div><div> }</div><div> </div><div>- if (gzcf->enable == NGX_HTTP_GZIP_STATIC_ON) {</div><div>+ if (enable == NGX_HTTP_GZIP_STATIC_ON) {</div><div> r->gzip_vary = 1;</div><div> </div><div> if (rc != NGX_OK) {</div><div>@@ -243,7 +286,7 @@</div><div> </div><div> h->hash = 1;</div><div> ngx_str_set(&h->key, "Content-Encoding");</div><div>- ngx_str_set(&h->value, "gzip");</div><div>+ h->value = *encoding;</div><div> r->headers_out.content_encoding = h;</div><div> </div><div> /* we need to allocate all before the header would be sent */</div><div>@@ -293,7 +336,8 @@</div><div> return NULL;</div><div> }</div><div> </div><div>- conf->enable = NGX_CONF_UNSET_UINT;</div><div>+ conf->enable_gzip = NGX_CONF_UNSET_UINT;</div><div>+ conf->enable_brotli = NGX_CONF_UNSET_UINT;</div><div> </div><div> return conf;</div><div> }</div><div>@@ -305,7 +349,9 @@</div><div> ngx_http_gzip_static_conf_t *prev = parent;</div><div> ngx_http_gzip_static_conf_t *conf = child;</div><div> </div><div>- ngx_conf_merge_uint_value(conf->enable, prev->enable,</div><div>+ ngx_conf_merge_uint_value(conf->enable_gzip, prev->enable_gzip,</div><div>+ NGX_HTTP_GZIP_STATIC_OFF);</div><div>+ ngx_conf_merge_uint_value(conf->enable_brotli, prev->enable_brotli,</div><div> NGX_HTTP_GZIP_STATIC_OFF);</div><div> </div><div> return NGX_CONF_OK;</div><div>diff -r 1ad0999a7ded -r 662115ad250f src/http/ngx_http_core_module.c</div><div>--- a/src/http/ngx_http_core_module.c<span class="gmail-Apple-tab-span" style="white-space:pre"> </span>Tue Feb 14 18:36:04 2017 +0300</div><div>+++ b/src/http/ngx_http_core_module.c<span class="gmail-Apple-tab-span" style="white-space:pre"> </span>Fri Feb 24 11:35:24 2017 +0100</div><div>@@ -74,8 +74,8 @@</div><div> static char *ngx_http_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd,</div><div> void *conf);</div><div> #if (NGX_HTTP_GZIP)</div><div>-static ngx_int_t ngx_http_gzip_accept_encoding(ngx_str_t *ae);</div><div>-static ngx_uint_t ngx_http_gzip_quantity(u_char *p, u_char *last);</div><div>+static ngx_int_t ngx_http_accept_encoding(ngx_str_t *ae, char *e, size_t n);</div><div>+static ngx_uint_t ngx_http_encoding_quantity(u_char *p, u_char *last);</div><div> static char *ngx_http_gzip_disable(ngx_conf_t *cf, ngx_command_t *cmd,</div><div> void *conf);</div><div> #endif</div><div>@@ -2170,7 +2170,7 @@</div><div> */</div><div> </div><div> if (ngx_memcmp(ae->value.data, "gzip,", 5) != 0</div><div>- && ngx_http_gzip_accept_encoding(&ae->value) != NGX_OK)</div><div>+ && ngx_http_accept_encoding(&ae->value, "gzip", 4) != NGX_OK)</div><div> {</div><div> return NGX_DECLINED;</div><div> }</div><div>@@ -2297,15 +2297,42 @@</div><div> }</div><div> </div><div> </div><div>+ngx_int_t</div><div>+ngx_http_brotli_ok(ngx_http_request_t *r)</div><div>+{</div><div>+ ngx_table_elt_t *ae;</div><div>+</div><div>+ if (r != r->main) {</div><div>+ return NGX_DECLINED;</div><div>+ }</div><div>+</div><div>+ ae = r->headers_in.accept_encoding;</div><div>+ if (ae == NULL) {</div><div>+ return NGX_DECLINED;</div><div>+ }</div><div>+</div><div>+ if (ae->value.len < sizeof("br") - 1) {</div><div>+ return NGX_DECLINED;</div><div>+ }</div><div>+</div><div>+ if (ngx_http_accept_encoding(&ae->value, "br", 2) != NGX_OK)</div><div>+ {</div><div>+ return NGX_DECLINED;</div><div>+ }</div><div>+</div><div>+ return NGX_OK;</div><div>+}</div><div>+</div><div>+</div><div> /*</div><div>- * gzip is enabled for the following quantities:</div><div>+ * encoding is enabled for the following quantities:</div><div> * "gzip; q=0.001" ... "gzip; q=1.000"</div><div>- * gzip is disabled for the following quantities:</div><div>- * "gzip; q=0" ... "gzip; q=0.000", and for any invalid cases</div><div>+ * encoding is disabled for the following quantities:</div><div>+ * "br; q=0" ... "br; q=0.000", and for any invalid cases</div><div> */</div><div> </div><div> static ngx_int_t</div><div>-ngx_http_gzip_accept_encoding(ngx_str_t *ae)</div><div>+ngx_http_accept_encoding(ngx_str_t *ae, char *e, size_t n)</div><div> {</div><div> u_char *p, *start, *last;</div><div> </div><div>@@ -2313,7 +2340,7 @@</div><div> last = start + ae->len;</div><div> </div><div> for ( ;; ) {</div><div>- p = ngx_strcasestrn(start, "gzip", 4 - 1);</div><div>+ p = ngx_strcasestrn(start, e, n - 1);</div><div> if (p == NULL) {</div><div> return NGX_DECLINED;</div><div> }</div><div>@@ -2322,10 +2349,10 @@</div><div> break;</div><div> }</div><div> </div><div>- start = p + 4;</div><div>- }</div><div>-</div><div>- p += 4;</div><div>+ start = p + n;</div><div>+ }</div><div>+</div><div>+ p += n;</div><div> </div><div> while (p < last) {</div><div> switch (*p++) {</div><div>@@ -2364,7 +2391,7 @@</div><div> return NGX_DECLINED;</div><div> }</div><div> </div><div>- if (ngx_http_gzip_quantity(p, last) == 0) {</div><div>+ if (ngx_http_encoding_quantity(p, last) == 0) {</div><div> return NGX_DECLINED;</div><div> }</div><div> </div><div>@@ -2373,7 +2400,7 @@</div><div> </div><div> </div><div> static ngx_uint_t</div><div>-ngx_http_gzip_quantity(u_char *p, u_char *last)</div><div>+ngx_http_encoding_quantity(u_char *p, u_char *last)</div><div> {</div><div> u_char c;</div><div> ngx_uint_t n, q;</div><div>diff -r 1ad0999a7ded -r 662115ad250f src/http/ngx_http_core_module.h</div><div>--- a/src/http/ngx_http_core_module.h<span class="gmail-Apple-tab-span" style="white-space:pre"> </span>Tue Feb 14 18:36:04 2017 +0300</div><div>+++ b/src/http/ngx_http_core_module.h<span class="gmail-Apple-tab-span" style="white-space:pre"> </span>Fri Feb 24 11:35:24 2017 +0100</div><div>@@ -504,6 +504,7 @@</div><div> ngx_int_t ngx_http_auth_basic_user(ngx_http_request_t *r);</div><div> #if (NGX_HTTP_GZIP)</div><div> ngx_int_t ngx_http_gzip_ok(ngx_http_request_t *r);</div><div>+ngx_int_t ngx_http_brotli_ok(ngx_http_request_t *r);</div><div> #endif</div><div> </div><div> </div></div><div><br></div><div><br></div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On 24 February 2017 at 12:01, Eugene Kluchnikov <span dir="ltr"><<a href="mailto:eustas.ru@gmail.com" target="_blank">eustas.ru@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Easily =)<div><br></div><div><br></div><div><span class=""><div># HG changeset patch</div><div># User Evgenii Kliuchnikov <<a href="mailto:eustas.ru@gmail.com" target="_blank">eustas.ru@gmail.com</a>></div></span><div># Date 1487932524 -3600</div><div># Fri Feb 24 11:35:24 2017 +0100</div><div># Node ID e1f5e06ade015f9855a6f683817cde<wbr>7bb0f243a3</div><div># Parent <wbr>1ad0999a7ded3d4fb01c7acf8ff57c<wbr>80b643da7e</div><div>Add brotli static (over nginx-1.11.10)</div><div><br></div><div>diff -r 1ad0999a7ded -r e1f5e06ade01 contrib/vim/syntax/nginx.vim</div><div>--- a/contrib/vim/syntax/nginx.vim<span class="m_6833097349097297554gmail-Apple-tab-span" style="white-space:pre-wrap"> </span>Tue Feb 14 18:36:04 2017 +0300</div><div>+++ b/contrib/vim/syntax/nginx.vim<span class="m_6833097349097297554gmail-Apple-tab-span" style="white-space:pre-wrap"> </span>Fri Feb 24 11:35:24 2017 +0100</div><span class=""><div>@@ -86,6 +86,7 @@</div><div> syn keyword ngxDirective autoindex</div><div> syn keyword ngxDirective autoindex_exact_size</div><div> syn keyword ngxDirective autoindex_localtime</div><div>+syn keyword ngxDirective brotli_static</div><div> syn keyword ngxDirective charset</div><div> syn keyword ngxDirective charset_types</div><div> syn keyword ngxDirective chunked_transfer_encoding</div></span><div>diff -r 1ad0999a7ded -r e1f5e06ade01 src/http/modules/ngx_http_<wbr>gzip_static_module.c</div><div>--- a/src/http/modules/ngx_http_<wbr>gzip_static_module.c<span class="m_6833097349097297554gmail-Apple-tab-span" style="white-space:pre-wrap"> </span>Tue Feb 14 18:36:04 2017 +0300</div><div>+++ b/src/http/modules/ngx_http_<wbr>gzip_static_module.c<span class="m_6833097349097297554gmail-Apple-tab-span" style="white-space:pre-wrap"> </span>Fri Feb 24 11:35:24 2017 +0100</div><div>@@ -16,10 +16,13 @@</div><span class=""><div> </div><div> </div><div> typedef struct {</div><div>- ngx_uint_t enable;</div><div>+ ngx_uint_t enable_gzip;</div><div>+ ngx_uint_t enable_brotli;</div><div> } ngx_http_gzip_static_conf_t;</div><div> </div></span><div>-</div><span class=""><div>+static ngx_int_t ngx_http_gzip_static_serve_<wbr>file(ngx_http_request_t *r,</div><div>+ ngx_uint_t enable, ngx_uint_t ok, ngx_http_core_loc_conf_t *clcf,</div><div>+ ngx_str_t *encoding);</div><div> static ngx_int_t ngx_http_gzip_static_handler(<wbr>ngx_http_request_t *r);</div><div> static void *ngx_http_gzip_static_create_<wbr>conf(ngx_conf_t *cf);</div><div> static char *ngx_http_gzip_static_merge_<wbr>conf(ngx_conf_t *cf, void *parent,</div></span><div>@@ -41,7 +44,14 @@</div><span class=""><div> NGX_HTTP_MAIN_CONF|NGX_HTTP_<wbr>SRV_CONF|NGX_HTTP_LOC_CONF|<wbr>NGX_CONF_TAKE1,</div><div> ngx_conf_set_enum_slot,</div><div> NGX_HTTP_LOC_CONF_OFFSET,</div><div>- offsetof(ngx_http_gzip_<wbr>static_conf_t, enable),</div><div>+ offsetof(ngx_http_gzip_<wbr>static_conf_t, enable_gzip),</div><div>+ &ngx_http_gzip_static },</div><div>+</div><div>+ { ngx_string("brotli_static"),</div><div>+ NGX_HTTP_MAIN_CONF|NGX_HTTP_<wbr>SRV_CONF|NGX_HTTP_LOC_CONF|<wbr>NGX_CONF_TAKE1,</div><div>+ ngx_conf_set_enum_slot,</div><div>+ NGX_HTTP_LOC_CONF_OFFSET,</div><div>+ offsetof(ngx_http_gzip_<wbr>static_conf_t, enable_brotli),</div><div> &ngx_http_gzip_static },</div><div> </div><div> ngx_null_command</div></span><div>@@ -79,19 +89,14 @@</div><span class=""><div> };</div><div> </div><div> </div><div>+static ngx_str_t encoding_gzip = ngx_string("gzip");</div><div>+static ngx_str_t encoding_brotli = ngx_string("br");</div><div>+</div><div>+</div><div> static ngx_int_t</div><div> ngx_http_gzip_static_handler(<wbr>ngx_http_request_t *r)</div><div> {</div><div>- u_char *p;</div><div>- size_t root;</div><div>- ngx_str_t path;</div><div> ngx_int_t rc;</div><div>- ngx_uint_t level;</div><div>- ngx_log_t *log;</div><div>- ngx_buf_t *b;</div><div>- ngx_chain_t out;</div><div>- ngx_table_elt_t *h;</div><div>- ngx_open_file_info_t of;</div><div> ngx_http_core_loc_conf_t *clcf;</div><div> ngx_http_gzip_static_conf_t *gzcf;</div><div> </div></span><span class=""><div>@@ -105,19 +110,56 @@</div><div> </div><div> gzcf = ngx_http_get_module_loc_conf(<wbr>r, ngx_http_gzip_static_module);</div><div> </div><div>- if (gzcf->enable == NGX_HTTP_GZIP_STATIC_OFF) {</div><div>+ if (gzcf->enable_gzip == NGX_HTTP_GZIP_STATIC_OFF</div></span><div>+ && gzcf->enable_brotli == NGX_HTTP_GZIP_STATIC_OFF) {</div><div><div class="h5"><div> return NGX_DECLINED;</div><div> }</div><div> </div><div>- if (gzcf->enable == NGX_HTTP_GZIP_STATIC_ON) {</div><div>- rc = ngx_http_gzip_ok(r);</div><div>+ clcf = ngx_http_get_module_loc_conf(<wbr>r, ngx_http_core_module);</div><div> </div><div>- } else {</div><div>- /* always */</div><div>- rc = NGX_OK;</div><div>+ rc = NGX_DECLINED;</div><div>+ if (gzcf->enable_gzip != NGX_HTTP_GZIP_STATIC_OFF) {</div><div>+ if (gzcf->enable_gzip == NGX_HTTP_GZIP_STATIC_ON) {</div><div>+ rc = ngx_http_gzip_ok(r);</div><div>+ } else {</div><div>+ /* always */</div><div>+ rc = NGX_OK;</div><div>+ }</div><div>+ rc = ngx_http_gzip_static_serve_<wbr>file(r, gzcf->enable_gzip, rc, clcf,</div><div>+ &encoding_gzip);</div><div> }</div><div> </div><div>- clcf = ngx_http_get_module_loc_conf(<wbr>r, ngx_http_core_module);</div><div>+ if (gzcf->enable_brotli != NGX_HTTP_GZIP_STATIC_OFF && rc == NGX_DECLINED) {</div><div>+ if (gzcf->enable_gzip == NGX_HTTP_GZIP_STATIC_ON) {</div><div>+ rc = ngx_http_gzip_ok(r);</div><div>+ } else {</div><div>+ /* always */</div><div>+ rc = NGX_OK;</div><div>+ }</div><div>+ rc = ngx_http_gzip_static_serve_<wbr>file(r, gzcf->enable_brotli, rc, clcf,</div><div>+ &encoding_brotli);</div><div>+ }</div><div>+</div><div>+ return rc;</div><div>+}</div><div>+</div><div>+</div><div>+static ngx_int_t</div><div>+ngx_http_gzip_static_serve_<wbr>file(ngx_http_request_t *r, ngx_uint_t enable,</div><div>+ ngx_uint_t ok, ngx_http_core_loc_conf_t *clcf, ngx_str_t *encoding)</div><div>+{</div><div>+ u_char *p;</div><div>+ size_t root;</div><div>+ ngx_str_t path;</div><div>+ ngx_int_t rc;</div><div>+ ngx_uint_t level;</div><div>+ ngx_log_t *log;</div><div>+ ngx_buf_t *b;</div><div>+ ngx_chain_t out;</div><div>+ ngx_table_elt_t *h;</div><div>+ ngx_open_file_info_t of;</div><div>+</div><div>+ rc = ok;</div><div> </div><div> if (!clcf->gzip_vary && rc != NGX_OK) {</div><div> return NGX_DECLINED;</div><div>@@ -125,14 +167,14 @@</div><div> </div><div> log = r->connection->log;</div><div> </div><div>- p = ngx_http_map_uri_to_path(r, &path, &root, sizeof(".gz") - 1);</div><div>+ p = ngx_http_map_uri_to_path(r, &path, &root, 4 - 1);</div><div> if (p == NULL) {</div><div> return NGX_HTTP_INTERNAL_SERVER_<wbr>ERROR;</div><div> }</div><div> </div><div> *p++ = '.';</div><div>- *p++ = 'g';</div><div>- *p++ = 'z';</div><div>+ *p++ = encoding->data[0];</div><div>+ *p++ = encoding->data[1];</div><div> *p = '\0';</div><div> </div><div> path.len = p - path.data;</div><div>@@ -188,7 +230,7 @@</div><div> return NGX_DECLINED;</div><div> }</div><div> </div><div>- if (gzcf->enable == NGX_HTTP_GZIP_STATIC_ON) {</div><div>+ if (enable == NGX_HTTP_GZIP_STATIC_ON) {</div><div> r->gzip_vary = 1;</div><div> </div><div> if (rc != NGX_OK) {</div><div>@@ -243,7 +285,7 @@</div><div> </div><div> h->hash = 1;</div><div> ngx_str_set(&h->key, "Content-Encoding");</div><div>- ngx_str_set(&h->value, "gzip");</div><div>+ h->value = *encoding;</div><div> r->headers_out.content_<wbr>encoding = h;</div><div> </div><div> /* we need to allocate all before the header would be sent */</div><div>@@ -293,7 +335,8 @@</div><div> return NULL;</div><div> }</div><div> </div><div>- conf->enable = NGX_CONF_UNSET_UINT;</div><div>+ conf->enable_gzip = NGX_CONF_UNSET_UINT;</div><div>+ conf->enable_brotli = NGX_CONF_UNSET_UINT;</div><div> </div><div> return conf;</div><div> }</div><div>@@ -305,7 +348,9 @@</div><div> ngx_http_gzip_static_conf_t *prev = parent;</div><div> ngx_http_gzip_static_conf_t *conf = child;</div><div> </div><div>- ngx_conf_merge_uint_value(<wbr>conf->enable, prev->enable,</div><div>+ ngx_conf_merge_uint_value(<wbr>conf->enable_gzip, prev->enable_gzip,</div><div>+ NGX_HTTP_GZIP_STATIC_OFF);</div><div>+ ngx_conf_merge_uint_value(<wbr>conf->enable_brotli, prev->enable_brotli,</div><div> NGX_HTTP_GZIP_STATIC_OFF);</div><div> </div><div> return NGX_CONF_OK;</div></div></div><div>diff -r 1ad0999a7ded -r e1f5e06ade01 src/http/ngx_http_core_module.<wbr>c</div><div>--- a/src/http/ngx_http_core_<wbr>module.c<span class="m_6833097349097297554gmail-Apple-tab-span" style="white-space:pre-wrap"> </span>Tue Feb 14 18:36:04 2017 +0300</div><div>+++ b/src/http/ngx_http_core_<wbr>module.c<span class="m_6833097349097297554gmail-Apple-tab-span" style="white-space:pre-wrap"> </span>Fri Feb 24 11:35:24 2017 +0100</div><div><div class="h5"><div>@@ -74,8 +74,8 @@</div><div> static char *ngx_http_core_resolver(ngx_<wbr>conf_t *cf, ngx_command_t *cmd,</div><div> void *conf);</div><div> #if (NGX_HTTP_GZIP)</div><div>-static ngx_int_t ngx_http_gzip_accept_encoding(<wbr>ngx_str_t *ae);</div><div>-static ngx_uint_t ngx_http_gzip_quantity(u_char *p, u_char *last);</div><div>+static ngx_int_t ngx_http_accept_encoding(ngx_<wbr>str_t *ae, char *e, size_t n);</div><div>+static ngx_uint_t ngx_http_encoding_quantity(u_<wbr>char *p, u_char *last);</div><div> static char *ngx_http_gzip_disable(ngx_<wbr>conf_t *cf, ngx_command_t *cmd,</div><div> void *conf);</div><div> #endif</div><div>@@ -2170,7 +2170,7 @@</div><div> */</div><div> </div><div> if (ngx_memcmp(ae->value.data, "gzip,", 5) != 0</div><div>- && ngx_http_gzip_accept_encoding(<wbr>&ae->value) != NGX_OK)</div><div>+ && ngx_http_accept_encoding(&ae-><wbr>value, "gzip", 4) != NGX_OK)</div><div> {</div><div> return NGX_DECLINED;</div><div> }</div><div>@@ -2297,15 +2297,42 @@</div><div> }</div><div> </div><div> </div><div>+ngx_int_t</div><div>+ngx_http_brotli_ok(ngx_http_<wbr>request_t *r)</div><div>+{</div><div>+ ngx_table_elt_t *ae;</div><div>+</div><div>+ if (r != r->main) {</div><div>+ return NGX_DECLINED;</div><div>+ }</div><div>+</div><div>+ ae = r->headers_in.accept_encoding;</div><div>+ if (ae == NULL) {</div><div>+ return NGX_DECLINED;</div><div>+ }</div><div>+</div><div>+ if (ae->value.len < sizeof("br") - 1) {</div><div>+ return NGX_DECLINED;</div><div>+ }</div><div>+</div><div>+ if (ngx_http_accept_encoding(&ae-<wbr>>value, "br", 2) != NGX_OK)</div><div>+ {</div><div>+ return NGX_DECLINED;</div><div>+ }</div><div>+</div><div>+ return NGX_OK;</div><div>+}</div><div>+</div><div>+</div><div> /*</div><div>- * gzip is enabled for the following quantities:</div></div></div><div>- * "gzip; q=0.001" ... "gzip; q=1.000"</div><span class=""><div>- * gzip is disabled for the following quantities:</div><div>- * "gzip; q=0" ... "gzip; q=0.000", and for any invalid cases</div></span><div>+ * encoding is enabled for the following quantities:</div><div>+ * "gzip; q=0.001" ... "gzip; q=1.000"</div><div><div class="h5"><div>+ * encoding is disabled for the following quantities:</div><div>+ * "br; q=0" ... "br; q=0.000", and for any invalid cases</div><div> */</div><div> </div><div> static ngx_int_t</div><div>-ngx_http_gzip_accept_<wbr>encoding(ngx_str_t *ae)</div><div>+ngx_http_accept_encoding(ngx_<wbr>str_t *ae, char *e, size_t n)</div><div> {</div><div> u_char *p, *start, *last;</div><div> </div><div>@@ -2313,7 +2340,7 @@</div><div> last = start + ae->len;</div><div> </div><div> for ( ;; ) {</div><div>- p = ngx_strcasestrn(start, "gzip", 4 - 1);</div><div>+ p = ngx_strcasestrn(start, e, n - 1);</div><div> if (p == NULL) {</div><div> return NGX_DECLINED;</div><div> }</div><div>@@ -2322,10 +2349,10 @@</div><div> break;</div><div> }</div><div> </div><div>- start = p + 4;</div><div>- }</div><div>-</div><div>- p += 4;</div><div>+ start = p + n;</div><div>+ }</div><div>+</div><div>+ p += n;</div><div> </div><div> while (p < last) {</div><div> switch (*p++) {</div><div>@@ -2364,7 +2391,7 @@</div><div> return NGX_DECLINED;</div><div> }</div><div> </div><div>- if (ngx_http_gzip_quantity(p, last) == 0) {</div><div>+ if (ngx_http_encoding_quantity(p, last) == 0) {</div><div> return NGX_DECLINED;</div><div> }</div><div> </div><div>@@ -2373,7 +2400,7 @@</div><div> </div><div> </div><div> static ngx_uint_t</div><div>-ngx_http_gzip_quantity(u_char *p, u_char *last)</div><div>+ngx_http_encoding_quantity(u_<wbr>char *p, u_char *last)</div><div> {</div><div> u_char c;</div><div> ngx_uint_t n, q;</div></div></div><div>diff -r 1ad0999a7ded -r e1f5e06ade01 src/http/ngx_http_core_module.<wbr>h</div><div>--- a/src/http/ngx_http_core_<wbr>module.h<span class="m_6833097349097297554gmail-Apple-tab-span" style="white-space:pre-wrap"> </span>Tue Feb 14 18:36:04 2017 +0300</div><div>+++ b/src/http/ngx_http_core_<wbr>module.h<span class="m_6833097349097297554gmail-Apple-tab-span" style="white-space:pre-wrap"> </span>Fri Feb 24 11:35:24 2017 +0100</div><span class=""><div>@@ -504,6 +504,7 @@</div><div> ngx_int_t ngx_http_auth_basic_user(ngx_<wbr>http_request_t *r);</div><div> #if (NGX_HTTP_GZIP)</div><div> ngx_int_t ngx_http_gzip_ok(ngx_http_<wbr>request_t *r);</div><div>+ngx_int_t ngx_http_brotli_ok(ngx_http_<wbr>request_t *r);</div><div> #endif</div><div> </div><div> </div></span></div><div><br></div><div><br></div><div><br></div></div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><div class="gmail_quote">On 24 February 2017 at 09:05, Ryan <span dir="ltr"><<a href="mailto:mp3geek@gmail.com" target="_blank">mp3geek@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Do you have a brotli patch that applies cleanly with nginx-1.11.10. I'm getting many patch fails.<br></div><div class="gmail_extra"><br><div class="gmail_quote"><div><div class="m_6833097349097297554h5">On Fri, Feb 24, 2017 at 8:03 AM, Eugene Kluchnikov <span dir="ltr"><<a href="mailto:eustas.ru@gmail.com" target="_blank">eustas.ru@gmail.com</a>></span> wrote:<br></div></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div class="m_6833097349097297554h5"><div dir="ltr"><span><div># HG changeset patch</div><div># User Evgenii Kliuchnikov <<a href="mailto:eustas.ru@gmail.com" target="_blank">eustas.ru@gmail.com</a>></div><div># Date 1487764873 -3600</div><div># Wed Feb 22 13:01:13 2017 +0100</div></span><div># Node ID c230f3874e060ccb14d7560233f2c7<wbr>0a910640a1</div><span><div># Parent 87cf6ddb41c216876d13cffa5e637<wbr>a61b159362c</div><div>Add brotli static serving support.</div><div><br></div><div>Both .gz and .br static content is served by</div><div>ngx_http_gzip_static_modile, but have separate configuration.</div><div><br></div></span><div>diff -r 87cf6ddb41c2 -r c230f3874e06 contrib/vim/syntax/nginx.vim</div><span><div>--- a/contrib/vim/syntax/nginx.vim<span class="m_6833097349097297554m_7257113163132077855m_6178666162894360792gmail-Apple-tab-span" style="white-space:pre-wrap"> </span>Fri Feb 17 17:01:27 2017 +0300</div><div>+++ b/contrib/vim/syntax/nginx.vim<span class="m_6833097349097297554m_7257113163132077855m_6178666162894360792gmail-Apple-tab-span" style="white-space:pre-wrap"> </span>Wed Feb 22 13:01:13 2017 +0100</div><div>@@ -86,6 +86,7 @@</div><div> syn keyword ngxDirective autoindex</div><div> syn keyword ngxDirective autoindex_exact_size</div><div> syn keyword ngxDirective autoindex_localtime</div><div>+syn keyword ngxDirective brotli_static</div><div> syn keyword ngxDirective charset</div><div> syn keyword ngxDirective charset_types</div><div> syn keyword ngxDirective chunked_transfer_encoding</div></span><div>diff -r 87cf6ddb41c2 -r c230f3874e06 src/http/modules/ngx_http_gzip<wbr>_static_module.c</div><div><div class="m_6833097349097297554m_7257113163132077855h5"><div>--- a/src/http/modules/ngx_http_gz<wbr>ip_static_module.c<span class="m_6833097349097297554m_7257113163132077855m_6178666162894360792gmail-Apple-tab-span" style="white-space:pre-wrap"> </span>Fri Feb 17 17:01:27 2017 +0300</div><div>+++ b/src/http/modules/ngx_http_gz<wbr>ip_static_module.c<span class="m_6833097349097297554m_7257113163132077855m_6178666162894360792gmail-Apple-tab-span" style="white-space:pre-wrap"> </span>Wed Feb 22 13:01:13 2017 +0100</div><div>@@ -16,10 +16,14 @@</div><div> </div><div> </div><div> typedef struct {</div><div>- ngx_uint_t enable;</div><div>+ ngx_uint_t enable_gzip;</div><div>+ ngx_uint_t enable_brotli;</div><div> } ngx_http_gzip_static_conf_t;</div><div> </div><div> </div><div>+static ngx_int_t ngx_http_gzip_static_serve_fil<wbr>e(ngx_http_request_t *r,</div><div>+ ngx_uint_t enable, ngx_uint_t ok, ngx_http_core_loc_conf_t *clcf,</div><div>+ ngx_str_t *encoding);</div><div> static ngx_int_t ngx_http_gzip_static_handler(n<wbr>gx_http_request_t *r);</div><div> static void *ngx_http_gzip_static_create_c<wbr>onf(ngx_conf_t *cf);</div><div> static char *ngx_http_gzip_static_merge_co<wbr>nf(ngx_conf_t *cf, void *parent,</div><div>@@ -41,7 +45,14 @@</div><div> NGX_HTTP_MAIN_CONF|NGX_HTTP_S<wbr>RV_CONF|NGX_HTTP_LOC_CONF|NGX_<wbr>CONF_TAKE1,</div><div> ngx_conf_set_enum_slot,</div><div> NGX_HTTP_LOC_CONF_OFFSET,</div><div>- offsetof(ngx_http_gzip_static<wbr>_conf_t, enable),</div><div>+ offsetof(ngx_http_gzip_static<wbr>_conf_t, enable_gzip),</div><div>+ &ngx_http_gzip_static },</div><div>+</div><div>+ { ngx_string("brotli_static"),</div><div>+ NGX_HTTP_MAIN_CONF|NGX_HTTP_S<wbr>RV_CONF|NGX_HTTP_LOC_CONF|NGX_<wbr>CONF_TAKE1,</div><div>+ ngx_conf_set_enum_slot,</div><div>+ NGX_HTTP_LOC_CONF_OFFSET,</div><div>+ offsetof(ngx_http_gzip_static<wbr>_conf_t, enable_brotli),</div><div> &ngx_http_gzip_static },</div><div> </div><div> ngx_null_command</div></div></div><div>@@ -79,19 +90,14 @@</div><span><div> };</div><div> </div><div> </div><div>+static ngx_str_t encoding_gzip = ngx_string("gzip");</div></span><div>+static ngx_str_t encoding_brotli = ngx_string("br");</div><div>+</div><span><div>+</div><div> static ngx_int_t</div><div> ngx_http_gzip_static_handler(<wbr>ngx_http_request_t *r)</div><div> {</div><div>- u_char *p;</div><div>- size_t root;</div><div>- ngx_str_t path;</div><div> ngx_int_t rc;</div><div>- ngx_uint_t level;</div><div>- ngx_log_t *log;</div><div>- ngx_buf_t *b;</div><div>- ngx_chain_t out;</div><div>- ngx_table_elt_t *h;</div><div>- ngx_open_file_info_t of;</div><div> ngx_http_core_loc_conf_t *clcf;</div><div> ngx_http_gzip_static_conf_t *gzcf;</div><div> </div></span><div>@@ -105,19 +111,56 @@</div><div><div class="m_6833097349097297554m_7257113163132077855h5"><div> </div><div> gzcf = ngx_http_get_module_loc_conf(r<wbr>, ngx_http_gzip_static_module);</div><div> </div><div>- if (gzcf->enable == NGX_HTTP_GZIP_STATIC_OFF) {</div><div>+ if (gzcf->enable_gzip == NGX_HTTP_GZIP_STATIC_OFF &&</div><div>+ gzcf->enable_brotli == NGX_HTTP_GZIP_STATIC_OFF) {</div><div> return NGX_DECLINED;</div><div> }</div><div> </div><div>- if (gzcf->enable == NGX_HTTP_GZIP_STATIC_ON) {</div><div>- rc = ngx_http_gzip_ok(r);</div><div>+ clcf = ngx_http_get_module_loc_conf(r<wbr>, ngx_http_core_module);</div><div> </div><div>- } else {</div><div>- /* always */</div><div>- rc = NGX_OK;</div><div>+ rc = NGX_DECLINED;</div><div>+ if (gzcf->enable_gzip != NGX_HTTP_GZIP_STATIC_OFF) {</div><div>+ if (gzcf->enable_gzip == NGX_HTTP_GZIP_STATIC_ON) {</div><div>+ rc = ngx_http_gzip_ok(r);</div><div>+ } else {</div><div>+ /* always */</div><div>+ rc = NGX_OK;</div><div>+ }</div><div>+ rc = ngx_http_gzip_static_serve_fil<wbr>e(r, gzcf->enable_gzip, rc, clcf,</div><div>+ &encoding_gzip);</div><div> }</div><div> </div><div>- clcf = ngx_http_get_module_loc_conf(r<wbr>, ngx_http_core_module);</div><div>+ if (gzcf->enable_brotli != NGX_HTTP_GZIP_STATIC_OFF && rc == NGX_DECLINED) {</div><div>+ if (gzcf->enable_gzip == NGX_HTTP_GZIP_STATIC_ON) {</div><div>+ rc = ngx_http_gzip_ok(r);</div><div>+ } else {</div><div>+ /* always */</div><div>+ rc = NGX_OK;</div><div>+ }</div><div>+ rc = ngx_http_gzip_static_serve_fil<wbr>e(r, gzcf->enable_brotli, rc, clcf,</div><div>+ &encoding_brotli);</div><div>+ }</div><div>+</div><div>+ return rc;</div><div>+}</div><div>+</div><div>+</div><div>+static ngx_int_t</div><div>+ngx_http_gzip_static_serve_fi<wbr>le(ngx_http_request_t *r, ngx_uint_t enable,</div><div>+ ngx_uint_t ok, ngx_http_core_loc_conf_t *clcf, ngx_str_t *encoding)</div><div>+{</div><div>+ u_char *p;</div><div>+ size_t root;</div><div>+ ngx_str_t path;</div><div>+ ngx_int_t rc;</div><div>+ ngx_uint_t level;</div><div>+ ngx_log_t *log;</div><div>+ ngx_buf_t *b;</div><div>+ ngx_chain_t out;</div><div>+ ngx_table_elt_t *h;</div><div>+ ngx_open_file_info_t of;</div><div>+</div><div>+ rc = ok;</div><div> </div><div> if (!clcf->gzip_vary && rc != NGX_OK) {</div><div> return NGX_DECLINED;</div></div></div><div>@@ -125,14 +168,14 @@</div><span><div> </div><div> log = r->connection->log;</div><div> </div><div>- p = ngx_http_map_uri_to_path(r, &path, &root, sizeof(".gz") - 1);</div><div>+ p = ngx_http_map_uri_to_path(r, &path, &root, 4 - 1);</div><div> if (p == NULL) {</div><div> return NGX_HTTP_INTERNAL_SERVER_ERROR<wbr>;</div><div> }</div><div> </div><div> *p++ = '.';</div><div>- *p++ = 'g';</div><div>- *p++ = 'z';</div><div>+ *p++ = encoding->data[0];</div><div>+ *p++ = encoding->data[1];</div><div> *p = '\0';</div><div> </div><div> path.len = p - path.data;</div></span><div>@@ -188,7 +231,7 @@</div><span><div> return NGX_DECLINED;</div><div> }</div><div> </div><div>- if (gzcf->enable == NGX_HTTP_GZIP_STATIC_ON) {</div><div>+ if (enable == NGX_HTTP_GZIP_STATIC_ON) {</div><div> r->gzip_vary = 1;</div><div> </div><div> if (rc != NGX_OK) {</div></span><div>@@ -243,7 +286,7 @@</div><span><div> </div><div> h->hash = 1;</div><div> ngx_str_set(&h->key, "Content-Encoding");</div><div>- ngx_str_set(&h->value, "gzip");</div><div>+ h->value = *encoding;</div><div> r->headers_out.content_encodi<wbr>ng = h;</div><div> </div><div> /* we need to allocate all before the header would be sent */</div></span><div>@@ -293,7 +336,8 @@</div><span><div> return NULL;</div><div> }</div><div> </div><div>- conf->enable = NGX_CONF_UNSET_UINT;</div><div>+ conf->enable_gzip = NGX_CONF_UNSET_UINT;</div><div>+ conf->enable_brotli = NGX_CONF_UNSET_UINT;</div><div> </div><div> return conf;</div><div> }</div></span><div>@@ -305,7 +349,9 @@</div><span><div> ngx_http_gzip_static_conf_t *prev = parent;</div><div> ngx_http_gzip_static_conf_t *conf = child;</div><div> </div><div>- ngx_conf_merge_uint_value(con<wbr>f->enable, prev->enable,</div><div>+ ngx_conf_merge_uint_value(con<wbr>f->enable_gzip, prev->enable_gzip,</div><div>+ NGX_HTTP_GZIP_STATIC_OFF);</div><div>+ ngx_conf_merge_uint_value(con<wbr>f->enable_brotli, prev->enable_brotli,</div><div> NGX_HTTP_GZIP_STATIC_OFF);</div><div> </div><div> return NGX_CONF_OK;</div></span><div>diff -r 87cf6ddb41c2 -r c230f3874e06 src/http/ngx_http_core_module.<wbr>c</div><div><div class="m_6833097349097297554m_7257113163132077855h5"><div>--- a/src/http/ngx_http_core_modul<wbr>e.c<span class="m_6833097349097297554m_7257113163132077855m_6178666162894360792gmail-Apple-tab-span" style="white-space:pre-wrap"> </span>Fri Feb 17 17:01:27 2017 +0300</div><div>+++ b/src/http/ngx_http_core_modul<wbr>e.c<span class="m_6833097349097297554m_7257113163132077855m_6178666162894360792gmail-Apple-tab-span" style="white-space:pre-wrap"> </span>Wed Feb 22 13:01:13 2017 +0100</div><div>@@ -74,8 +74,8 @@</div><div> static char *ngx_http_core_resolver(ngx_co<wbr>nf_t *cf, ngx_command_t *cmd,</div><div> void *conf);</div><div> #if (NGX_HTTP_GZIP)</div><div>-static ngx_int_t ngx_http_gzip_accept_encoding(<wbr>ngx_str_t *ae);</div><div>-static ngx_uint_t ngx_http_gzip_quantity(u_char *p, u_char *last);</div><div>+static ngx_int_t ngx_http_accept_encoding(ngx_s<wbr>tr_t *ae, char *e, size_t n);</div><div>+static ngx_uint_t ngx_http_encoding_quantity(u_c<wbr>har *p, u_char *last);</div><div> static char *ngx_http_gzip_disable(ngx_con<wbr>f_t *cf, ngx_command_t *cmd,</div><div> void *conf);</div><div> #endif</div><div>@@ -2170,7 +2170,7 @@</div><div> */</div><div> </div><div> if (ngx_memcmp(ae->value.data, "gzip,", 5) != 0</div><div>- && ngx_http_gzip_accept_encoding(<wbr>&ae->value) != NGX_OK)</div><div>+ && ngx_http_accept_encoding(&ae-><wbr>value, "gzip", 4) != NGX_OK)</div><div> {</div><div> return NGX_DECLINED;</div><div> }</div><div>@@ -2297,15 +2297,42 @@</div><div> }</div><div> </div><div> </div><div>+ngx_int_t</div><div>+ngx_http_brotli_ok(ngx_http_r<wbr>equest_t *r)</div><div>+{</div><div>+ ngx_table_elt_t *ae;</div><div>+</div><div>+ if (r != r->main) {</div><div>+ return NGX_DECLINED;</div><div>+ }</div><div>+</div><div>+ ae = r->headers_in.accept_encoding;</div><div>+ if (ae == NULL) {</div><div>+ return NGX_DECLINED;</div><div>+ }</div><div>+</div><div>+ if (ae->value.len < sizeof("br") - 1) {</div><div>+ return NGX_DECLINED;</div><div>+ }</div><div>+</div><div>+ if (ngx_http_accept_encoding(&ae-<wbr>>value, "br", 2) != NGX_OK)</div><div>+ {</div><div>+ return NGX_DECLINED;</div><div>+ }</div><div>+</div><div>+ return NGX_OK;</div><div>+}</div><div>+</div><div>+</div><div> /*</div><div>- * gzip is enabled for the following quantities:</div><div>+ * encoding is enabled for the following quantities:</div><div> * "gzip; q=0.001" ... "gzip; q=1.000"</div><div>- * gzip is disabled for the following quantities:</div><div>- * "gzip; q=0" ... "gzip; q=0.000", and for any invalid cases</div><div>+ * encoding is disabled for the following quantities:</div><div>+ * "br; q=0" ... "br; q=0.000", and for any invalid cases</div><div> */</div><div> </div><div> static ngx_int_t</div><div>-ngx_http_gzip_accept_encoding<wbr>(ngx_str_t *ae)</div><div>+ngx_http_accept_encoding(ngx_<wbr>str_t *ae, char *e, size_t n)</div><div> {</div><div> u_char *p, *start, *last;</div><div> </div><div>@@ -2313,7 +2340,7 @@</div><div> last = start + ae->len;</div><div> </div><div> for ( ;; ) {</div><div>- p = ngx_strcasestrn(start, "gzip", 4 - 1);</div><div>+ p = ngx_strcasestrn(start, e, n - 1);</div><div> if (p == NULL) {</div><div> return NGX_DECLINED;</div><div> }</div><div>@@ -2322,10 +2349,10 @@</div><div> break;</div><div> }</div><div> </div><div>- start = p + 4;</div><div>- }</div><div>-</div><div>- p += 4;</div><div>+ start = p + n;</div><div>+ }</div><div>+</div><div>+ p += n;</div><div> </div><div> while (p < last) {</div><div> switch (*p++) {</div><div>@@ -2364,7 +2391,7 @@</div><div> return NGX_DECLINED;</div><div> }</div><div> </div><div>- if (ngx_http_gzip_quantity(p, last) == 0) {</div><div>+ if (ngx_http_encoding_quantity(p, last) == 0) {</div><div> return NGX_DECLINED;</div><div> }</div><div> </div><div>@@ -2373,7 +2400,7 @@</div><div> </div><div> </div><div> static ngx_uint_t</div><div>-ngx_http_gzip_quantity(u_char *p, u_char *last)</div><div>+ngx_http_encoding_quantity(u_<wbr>char *p, u_char *last)</div><div> {</div><div> u_char c;</div><div> ngx_uint_t n, q;</div></div></div><div>diff -r 87cf6ddb41c2 -r c230f3874e06 src/http/ngx_http_core_module.<wbr>h</div><span><div>--- a/src/http/ngx_http_core_modul<wbr>e.h<span class="m_6833097349097297554m_7257113163132077855m_6178666162894360792gmail-Apple-tab-span" style="white-space:pre-wrap"> </span>Fri Feb 17 17:01:27 2017 +0300</div><div>+++ b/src/http/ngx_http_core_modul<wbr>e.h<span class="m_6833097349097297554m_7257113163132077855m_6178666162894360792gmail-Apple-tab-span" style="white-space:pre-wrap"> </span>Wed Feb 22 13:01:13 2017 +0100</div><div>@@ -504,6 +504,7 @@</div><div> ngx_int_t ngx_http_auth_basic_user(ngx_h<wbr>ttp_request_t *r);</div><div> #if (NGX_HTTP_GZIP)</div><div> ngx_int_t ngx_http_gzip_ok(ngx_http_requ<wbr>est_t *r);</div><div>+ngx_int_t ngx_http_brotli_ok(ngx_http_re<wbr>quest_t *r);</div><div> #endif</div><div> </div><div> </div><div><br></div><div><br></div><div><br></div></span><div>Fixed "Content-Encoding" value.</div></div><div class="gmail_extra"><div><div class="m_6833097349097297554m_7257113163132077855h5"><br><div class="gmail_quote">On 23 February 2017 at 13:11, Eugene Kluchnikov <span dir="ltr"><<a href="mailto:eustas.ru@gmail.com" target="_blank">eustas.ru@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><span><div># HG changeset patch</div><div># User Evgenii Kliuchnikov <<a href="mailto:eustas.ru@gmail.com" target="_blank">eustas.ru@gmail.com</a>></div><div># Date 1487764873 -3600</div><div># Wed Feb 22 13:01:13 2017 +0100</div></span><div># Node ID 96939e63f30579f2f32e843d217bd4<wbr>6fa6086bb4</div><div># Parent 87cf6ddb41c216876d13cffa5e637<wbr>a61b159362c</div><div>Add brotli static serving support.</div><div><br></div><div>Both .gz and .br static content is served by</div><div>ngx_http_gzip_static_modile, but have separate configuration.</div><div><br></div><div>diff -r 87cf6ddb41c2 -r 96939e63f305 contrib/vim/syntax/nginx.vim</div><span><div>--- a/contrib/vim/syntax/nginx.vim<span class="m_6833097349097297554m_7257113163132077855m_6178666162894360792m_8332095074251656233gmail-Apple-tab-span" style="white-space:pre-wrap"> </span>Fri Feb 17 17:01:27 2017 +0300</div><div>+++ b/contrib/vim/syntax/nginx.vim<span class="m_6833097349097297554m_7257113163132077855m_6178666162894360792m_8332095074251656233gmail-Apple-tab-span" style="white-space:pre-wrap"> </span>Wed Feb 22 13:01:13 2017 +0100</div><div>@@ -86,6 +86,7 @@</div><div> syn keyword ngxDirective autoindex</div><div> syn keyword ngxDirective autoindex_exact_size</div><div> syn keyword ngxDirective autoindex_localtime</div><div>+syn keyword ngxDirective brotli_static</div><div> syn keyword ngxDirective charset</div><div> syn keyword ngxDirective charset_types</div><div> syn keyword ngxDirective chunked_transfer_encoding</div></span><div>diff -r 87cf6ddb41c2 -r 96939e63f305 src/http/modules/ngx_http_gzip<wbr>_static_module.c</div><div>--- a/src/http/modules/ngx_http_gz<wbr>ip_static_module.c<span class="m_6833097349097297554m_7257113163132077855m_6178666162894360792m_8332095074251656233gmail-Apple-tab-span" style="white-space:pre-wrap"> </span>Fri Feb 17 17:01:27 2017 +0300</div><div>+++ b/src/http/modules/ngx_http_gz<wbr>ip_static_module.c<span class="m_6833097349097297554m_7257113163132077855m_6178666162894360792m_8332095074251656233gmail-Apple-tab-span" style="white-space:pre-wrap"> </span>Wed Feb 22 13:01:13 2017 +0100</div><div>@@ -16,10 +16,14 @@</div><div> </div><div> </div><div> typedef struct {</div><div>- ngx_uint_t enable;</div><div>+ ngx_uint_t enable_gzip;</div><div>+ ngx_uint_t enable_brotli;</div><div> } ngx_http_gzip_static_conf_t;</div><div> </div><div> </div><div>+static ngx_int_t ngx_http_gzip_static_serve_fil<wbr>e(ngx_http_request_t *r,</div><div>+ ngx_uint_t enable, ngx_uint_t ok, ngx_http_core_loc_conf_t *clcf,</div><div>+ ngx_str_t *encoding);</div><div> static ngx_int_t ngx_http_gzip_static_handler(n<wbr>gx_http_request_t *r);</div><div> static void *ngx_http_gzip_static_create_c<wbr>onf(ngx_conf_t *cf);</div><div> static char *ngx_http_gzip_static_merge_co<wbr>nf(ngx_conf_t *cf, void *parent,</div><div>@@ -41,7 +45,14 @@</div><div> NGX_HTTP_MAIN_CONF|NGX_HTTP_S<wbr>RV_CONF|NGX_HTTP_LOC_CONF|NGX_<wbr>CONF_TAKE1,</div><div> ngx_conf_set_enum_slot,</div><div> NGX_HTTP_LOC_CONF_OFFSET,</div><div>- offsetof(ngx_http_gzip_static<wbr>_conf_t, enable),</div><div>+ offsetof(ngx_http_gzip_static<wbr>_conf_t, enable_gzip),</div><div>+ &ngx_http_gzip_static },</div><span><div>+</div><div>+ { ngx_string("brotli_static"),</div><div>+ NGX_HTTP_MAIN_CONF|NGX_HTTP_S<wbr>RV_CONF|NGX_HTTP_LOC_CONF|NGX_<wbr>CONF_TAKE1,</div><div>+ ngx_conf_set_enum_slot,</div><div>+ NGX_HTTP_LOC_CONF_OFFSET,</div></span><div>+ offsetof(ngx_http_gzip_static<wbr>_conf_t, enable_brotli),</div><div> &ngx_http_gzip_static },</div><div> </div><div> ngx_null_command</div><div>@@ -79,19 +90,13 @@</div><div> };</div><div> </div><div> </div><div>+static ngx_str_t encoding_gzip = ngx_string("gzip");</div><div>+static ngx_str_t encoding_brotli = ngx_string("brotli");</div><div>+</div><div> static ngx_int_t</div><div> ngx_http_gzip_static_handler(<wbr>ngx_http_request_t *r)</div><div> {</div><div>- u_char *p;</div><div>- size_t root;</div><div>- ngx_str_t path;</div><div> ngx_int_t rc;</div><div>- ngx_uint_t level;</div><div>- ngx_log_t *log;</div><div>- ngx_buf_t *b;</div><div>- ngx_chain_t out;</div><div>- ngx_table_elt_t *h;</div><div>- ngx_open_file_info_t of;</div><div> ngx_http_core_loc_conf_t *clcf;</div><div> ngx_http_gzip_static_conf_t *gzcf;</div><div> </div><div>@@ -105,19 +110,56 @@</div><div> </div><div> gzcf = ngx_http_get_module_loc_conf(r<wbr>, ngx_http_gzip_static_module);</div><div> </div><div>- if (gzcf->enable == NGX_HTTP_GZIP_STATIC_OFF) {</div><div>+ if (gzcf->enable_gzip == NGX_HTTP_GZIP_STATIC_OFF &&</div><div>+ gzcf->enable_brotli == NGX_HTTP_GZIP_STATIC_OFF) {</div><div> return NGX_DECLINED;</div><div> }</div><div> </div><div>- if (gzcf->enable == NGX_HTTP_GZIP_STATIC_ON) {</div><div>- rc = ngx_http_gzip_ok(r);</div><span><div>+ clcf = ngx_http_get_module_loc_conf(r<wbr>, ngx_http_core_module);</div><div> </div></span><div>- } else {</div><div>- /* always */</div><div>- rc = NGX_OK;</div><div>+ rc = NGX_DECLINED;</div><div>+ if (gzcf->enable_gzip != NGX_HTTP_GZIP_STATIC_OFF) {</div><div>+ if (gzcf->enable_gzip == NGX_HTTP_GZIP_STATIC_ON) {</div><div>+ rc = ngx_http_gzip_ok(r);</div><span><div>+ } else {</div><div>+ /* always */</div><div>+ rc = NGX_OK;</div><div>+ }</div></span><div>+ rc = ngx_http_gzip_static_serve_fil<wbr>e(r, gzcf->enable_gzip, rc, clcf,</div><div>+ &encoding_gzip);</div><div> }</div><div> </div><div>- clcf = ngx_http_get_module_loc_conf(r<wbr>, ngx_http_core_module);</div><div>+ if (gzcf->enable_brotli != NGX_HTTP_GZIP_STATIC_OFF && rc == NGX_DECLINED) {</div><div>+ if (gzcf->enable_gzip == NGX_HTTP_GZIP_STATIC_ON) {</div><div>+ rc = ngx_http_gzip_ok(r);</div><span><div>+ } else {</div><div>+ /* always */</div><div>+ rc = NGX_OK;</div><div>+ }</div></span><div>+ rc = ngx_http_gzip_static_serve_fil<wbr>e(r, gzcf->enable_brotli, rc, clcf,</div><div>+ &encoding_brotli);</div><div>+ }</div><div>+</div><span><div>+ return rc;</div><div>+}</div><div>+</div><div>+</div></span><div>+static ngx_int_t</div><div>+ngx_http_gzip_static_serve_fi<wbr>le(ngx_http_request_t *r, ngx_uint_t enable,</div><div>+ ngx_uint_t ok, ngx_http_core_loc_conf_t *clcf, ngx_str_t *encoding)</div><span><div>+{</div><div>+ u_char *p;</div><div>+ size_t root;</div><div>+ ngx_str_t path;</div><div>+ ngx_int_t rc;</div><div>+ ngx_uint_t level;</div><div>+ ngx_log_t *log;</div><div>+ ngx_buf_t *b;</div><div>+ ngx_chain_t out;</div><div>+ ngx_table_elt_t *h;</div><div>+ ngx_open_file_info_t of;</div><div>+</div></span><div>+ rc = ok;</div><span><div> </div><div> if (!clcf->gzip_vary && rc != NGX_OK) {</div></span><div> return NGX_DECLINED;</div><div>@@ -125,14 +167,14 @@</div><span><div> </div><div> log = r->connection->log;</div><div> </div></span><div>- p = ngx_http_map_uri_to_path(r, &path, &root, sizeof(".gz") - 1);</div><div>+ p = ngx_http_map_uri_to_path(r, &path, &root, 4 - 1);</div><div> if (p == NULL) {</div><div> return NGX_HTTP_INTERNAL_SERVER_ERROR<wbr>;</div><div> }</div><div> </div><div> *p++ = '.';</div><div>- *p++ = 'g';</div><div>- *p++ = 'z';</div><div>+ *p++ = encoding->data[0];</div><div>+ *p++ = encoding->data[1];</div><div> *p = '\0';</div><span><div> </div><div> path.len = p - path.data;</div></span><div>@@ -188,7 +230,7 @@</div><div> return NGX_DECLINED;</div><div> }</div><div> </div><div>- if (gzcf->enable == NGX_HTTP_GZIP_STATIC_ON) {</div><div>+ if (enable == NGX_HTTP_GZIP_STATIC_ON) {</div><div> r->gzip_vary = 1;</div><div> </div><div> if (rc != NGX_OK) {</div><div>@@ -243,7 +285,7 @@</div><div> </div><div> h->hash = 1;</div><div> ngx_str_set(&h->key, "Content-Encoding");</div><div>- ngx_str_set(&h->value, "gzip");</div><div>+ h->value = *encoding;</div><div> r->headers_out.content_encodi<wbr>ng = h;</div><span><div> </div><div> /* we need to allocate all before the header would be sent */</div></span><div>@@ -293,7 +335,8 @@</div><div> return NULL;</div><div> }</div><div> </div><div>- conf->enable = NGX_CONF_UNSET_UINT;</div><div>+ conf->enable_gzip = NGX_CONF_UNSET_UINT;</div><div>+ conf->enable_brotli = NGX_CONF_UNSET_UINT;</div><div> </div><div> return conf;</div><div> }</div><div>@@ -305,7 +348,9 @@</div><div> ngx_http_gzip_static_conf_t *prev = parent;</div><div> ngx_http_gzip_static_conf_t *conf = child;</div><div> </div><div>- ngx_conf_merge_uint_value(con<wbr>f->enable, prev->enable,</div><div>+ ngx_conf_merge_uint_value(con<wbr>f->enable_gzip, prev->enable_gzip,</div><div>+ NGX_HTTP_GZIP_STATIC_OFF);</div><div>+ ngx_conf_merge_uint_value(con<wbr>f->enable_brotli, prev->enable_brotli,</div><div> NGX_HTTP_GZIP_STATIC_OFF);</div><div> </div><div> return NGX_CONF_OK;</div><div>diff -r 87cf6ddb41c2 -r 96939e63f305 src/http/ngx_http_core_module.<wbr>c</div><span><div>--- a/src/http/ngx_http_core_modul<wbr>e.c<span class="m_6833097349097297554m_7257113163132077855m_6178666162894360792m_8332095074251656233gmail-Apple-tab-span" style="white-space:pre-wrap"> </span>Fri Feb 17 17:01:27 2017 +0300</div></span><div>+++ b/src/http/ngx_http_core_modul<wbr>e.c<span class="m_6833097349097297554m_7257113163132077855m_6178666162894360792m_8332095074251656233gmail-Apple-tab-span" style="white-space:pre-wrap"> </span>Wed Feb 22 13:01:13 2017 +0100</div><div>@@ -74,8 +74,8 @@</div><span><div> static char *ngx_http_core_resolver(ngx_co<wbr>nf_t *cf, ngx_command_t *cmd,</div><div> void *conf);</div></span><span><div> #if (NGX_HTTP_GZIP)</div><div>-static ngx_int_t ngx_http_gzip_accept_encoding(<wbr>ngx_str_t *ae);</div><div>-static ngx_uint_t ngx_http_gzip_quantity(u_char *p, u_char *last);</div></span><span><div>+static ngx_int_t ngx_http_accept_encoding(ngx_s<wbr>tr_t *ae, char *e, size_t n);</div><div>+static ngx_uint_t ngx_http_encoding_quantity(u_c<wbr>har *p, u_char *last);</div></span><span><div> static char *ngx_http_gzip_disable(ngx_con<wbr>f_t *cf, ngx_command_t *cmd,</div><div> void *conf);</div><div> #endif</div></span><div>@@ -2170,7 +2170,7 @@</div><span><div> */</div><div> </div><div> if (ngx_memcmp(ae->value.data, "gzip,", 5) != 0</div><div>- && ngx_http_gzip_accept_encoding(<wbr>&ae->value) != NGX_OK)</div><div>+ && ngx_http_accept_encoding(&ae-><wbr>value, "gzip", 4) != NGX_OK)</div><div> {</div><div> return NGX_DECLINED;</div><div> }</div></span><div>@@ -2297,15 +2297,42 @@</div><div><div class="m_6833097349097297554m_7257113163132077855m_6178666162894360792h5"><div> }</div><div> </div><div> </div><div>+ngx_int_t</div><div>+ngx_http_brotli_ok(ngx_http_r<wbr>equest_t *r)</div><div>+{</div><div>+ ngx_table_elt_t *ae;</div><div>+</div><div>+ if (r != r->main) {</div><div>+ return NGX_DECLINED;</div><div>+ }</div><div>+</div><div>+ ae = r->headers_in.accept_encoding;</div><div>+ if (ae == NULL) {</div><div>+ return NGX_DECLINED;</div><div>+ }</div><div>+</div><div>+ if (ae->value.len < sizeof("br") - 1) {</div><div>+ return NGX_DECLINED;</div><div>+ }</div><div>+</div><div>+ if (ngx_http_accept_encoding(&ae-<wbr>>value, "br", 2) != NGX_OK)</div><div>+ {</div><div>+ return NGX_DECLINED;</div><div>+ }</div><div>+</div><div>+ return NGX_OK;</div><div>+}</div><div>+</div><div>+</div></div></div><span><div> /*</div><div>- * gzip is enabled for the following quantities:</div><div>+ * encoding is enabled for the following quantities:</div><div> * "gzip; q=0.001" ... "gzip; q=1.000"</div><div>- * gzip is disabled for the following quantities:</div><div>- * "gzip; q=0" ... "gzip; q=0.000", and for any invalid cases</div><div>+ * encoding is disabled for the following quantities:</div><div>+ * "br; q=0" ... "br; q=0.000", and for any invalid cases</div><div> */</div><div> </div><div> static ngx_int_t</div><div>-ngx_http_gzip_accept_encoding<wbr>(ngx_str_t *ae)</div><div>+ngx_http_accept_encoding(ngx_<wbr>str_t *ae, char *e, size_t n)</div><div> {</div><div> u_char *p, *start, *last;</div><div> </div></span><div>@@ -2313,7 +2340,7 @@</div><span><div> last = start + ae->len;</div><div> </div><div> for ( ;; ) {</div><div>- p = ngx_strcasestrn(start, "gzip", 4 - 1);</div><div>+ p = ngx_strcasestrn(start, e, n - 1);</div><div> if (p == NULL) {</div><div> return NGX_DECLINED;</div><div> }</div></span><div>@@ -2322,10 +2349,10 @@</div><span><div> break;</div><div> }</div><div> </div><div>- start = p + 4;</div><div>- }</div><div>-</div><div>- p += 4;</div><div>+ start = p + n;</div><div>+ }</div><div>+</div><div>+ p += n;</div><div> </div><div> while (p < last) {</div><div> switch (*p++) {</div></span><div>@@ -2364,7 +2391,7 @@</div><span><div> return NGX_DECLINED;</div><div> }</div><div> </div><div>- if (ngx_http_gzip_quantity(p, last) == 0) {</div><div>+ if (ngx_http_encoding_quantity(p, last) == 0) {</div><div> return NGX_DECLINED;</div><div> }</div><div> </div></span><div>@@ -2373,7 +2400,7 @@</div><span><div> </div><div> </div><div> static ngx_uint_t</div><div>-ngx_http_gzip_quantity(u_char *p, u_char *last)</div><div>+ngx_http_encoding_quantity(u_<wbr>char *p, u_char *last)</div><div> {</div><div> u_char c;</div><div> ngx_uint_t n, q;</div></span><div>diff -r 87cf6ddb41c2 -r 96939e63f305 src/http/ngx_http_core_module.<wbr>h</div><span><div>--- a/src/http/ngx_http_core_modul<wbr>e.h<span class="m_6833097349097297554m_7257113163132077855m_6178666162894360792m_8332095074251656233gmail-Apple-tab-span" style="white-space:pre-wrap"> </span>Fri Feb 17 17:01:27 2017 +0300</div></span><div>+++ b/src/http/ngx_http_core_modul<wbr>e.h<span class="m_6833097349097297554m_7257113163132077855m_6178666162894360792m_8332095074251656233gmail-Apple-tab-span" style="white-space:pre-wrap"> </span>Wed Feb 22 13:01:13 2017 +0100</div><div>@@ -504,6 +504,7 @@</div><div> ngx_int_t ngx_http_auth_basic_user(ngx_h<wbr>ttp_request_t *r);</div><div> #if (NGX_HTTP_GZIP)</div><div> ngx_int_t ngx_http_gzip_ok(ngx_http_requ<wbr>est_t *r);</div><div>+ngx_int_t ngx_http_brotli_ok(ngx_http_re<wbr>quest_t *r);</div><div> #endif</div><div> </div><div> </div><div><br></div><div><br></div><div><br></div><div><br></div><div>Take 2 - modify ngx_http_gzip_static_modile to serve both .gz and .br.</div><div class="gmail_extra"><br></div><div class="gmail_extra"><br><div class="gmail_quote"><span>On 22 February 2017 at 16:10, Eugene Kluchnikov <span dir="ltr"><<a href="mailto:eustas.ru@gmail.com" target="_blank">eustas.ru@gmail.com</a>></span> wrote:<br></span><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span><div dir="ltr">Yup. Going to try to create a "combined" module soon =)</div></span><div class="gmail_extra"><div><div class="m_6833097349097297554m_7257113163132077855m_6178666162894360792m_8332095074251656233gmail-h5"><br><div class="gmail_quote"><span>On 22 February 2017 at 15:40, Valentin V. Bartenev <span dir="ltr"><<a href="mailto:vbart@nginx.com" target="_blank">vbart@nginx.com</a>></span> wrote:</span><span><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
At the first glance, the differences are really small and<br>
such functionality can be combined in one module.<br></blockquote></span></div></div></div></div></blockquote></div>
</div></div>
</blockquote></div><br><br clear="all"><div><br></div></div></div><span>-- <br><div class="m_6833097349097297554m_7257113163132077855m_6178666162894360792gmail_signature" data-smartmail="gmail_signature">С наилучшими пожеланиями, Евгений Ключников<br>WBR, Eugene Kluchnikov<br></div>
</span></div>
<br></div></div><span>______________________________<wbr>_________________<br>
nginx-devel mailing list<br>
<a href="mailto:nginx-devel@nginx.org" target="_blank">nginx-devel@nginx.org</a><br>
<a href="http://mailman.nginx.org/mailman/listinfo/nginx-devel" rel="noreferrer" target="_blank">http://mailman.nginx.org/mailm<wbr>an/listinfo/nginx-devel</a><br></span></blockquote></div><br></div>
</blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="m_6833097349097297554gmail_signature" data-smartmail="gmail_signature">С наилучшими пожеланиями, Евгений Ключников<br>WBR, Eugene Kluchnikov<br></div>
</div>
</div></div></blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature" data-smartmail="gmail_signature">С наилучшими пожеланиями, Евгений Ключников<br>WBR, Eugene Kluchnikov<br></div>
</div>