<div dir="ltr"><div># HG changeset patch</div><div># User Evgenii Kliuchnikov <<a href="mailto:eustas.ru@gmail.com">eustas.ru@gmail.com</a>></div><div># Date 1487764873 -3600</div><div># Wed Feb 22 13:01:13 2017 +0100</div><div># Node ID 81eacab152efa88d1296cc04dfd110a168a6b1fb</div><div># Parent 87cf6ddb41c216876d13cffa5e637a61b159362c</div><div>Add brotli static serving module</div><div><br></div><div>Brotli static serving module is a copy of gzip static serving module</div><div>with "gzip" and derivatives replaced with "brotli" and derivatives.</div><div><br></div><div>This module does not add any dependencies.</div><div>It allows serving offline-compressed content when browser specifies</div><div>that "br" content encoding is supported.</div><div><br></div><div>For lower binary overhead ngx_http_gzip_accept_encoding and</div><div>ngx_http_gzip_quantity were refactored and to be used both by gzip</div><div>and brotli modules.</div><div><br></div><div>diff -r 87cf6ddb41c2 -r 81eacab152ef auto/modules</div><div>--- a/auto/modules<span class="gmail-Apple-tab-span" style="white-space:pre"> </span>Fri Feb 17 17:01:27 2017 +0300</div><div>+++ b/auto/modules<span class="gmail-Apple-tab-span" style="white-space:pre"> </span>Wed Feb 22 13:01:13 2017 +0100</div><div>@@ -124,6 +124,7 @@</div><div> </div><div> # the module order is important</div><div> # ngx_http_static_module</div><div>+# ngx_http_brotli_static_module</div><div> # ngx_http_gzip_static_module</div><div> # ngx_http_dav_module</div><div> # ngx_http_autoindex_module</div><div>@@ -160,6 +161,7 @@</div><div> HTTP_FILTER_MODULES=</div><div> </div><div> ngx_module_order="ngx_http_static_module \</div><div>+ ngx_http_brotli_static_module \</div><div> ngx_http_gzip_static_module \</div><div> ngx_http_dav_module \</div><div> ngx_http_autoindex_module \</div><div>@@ -451,6 +453,19 @@</div><div> . auto/module</div><div> fi</div><div> </div><div>+if [ $HTTP_BROTLI_STATIC = YES ]; then</div><div>+ have=NGX_HTTP_BROTLI . auto/have</div><div>+</div><div>+ ngx_module_name=ngx_http_brotli_static_module</div><div>+ ngx_module_incs=</div><div>+ ngx_module_deps=</div><div>+ ngx_module_srcs=src/http/modules/ngx_http_brotli_static_module.c</div><div>+ ngx_module_libs=</div><div>+ ngx_module_link=$HTTP_BROTLI_STATIC</div><div>+</div><div>+ . auto/module</div><div>+fi</div><div>+</div><div> if [ $HTTP_GZIP_STATIC = YES ]; then</div><div> have=NGX_HTTP_GZIP . auto/have</div><div> </div><div>diff -r 87cf6ddb41c2 -r 81eacab152ef auto/options</div><div>--- a/auto/options<span class="gmail-Apple-tab-span" style="white-space:pre"> </span>Fri Feb 17 17:01:27 2017 +0300</div><div>+++ b/auto/options<span class="gmail-Apple-tab-span" style="white-space:pre"> </span>Wed Feb 22 13:01:13 2017 +0100</div><div>@@ -96,6 +96,7 @@</div><div> HTTP_FLV=NO</div><div> HTTP_MP4=NO</div><div> HTTP_GUNZIP=NO</div><div>+HTTP_BROTLI_STATIC=NO</div><div> HTTP_GZIP_STATIC=NO</div><div> HTTP_UPSTREAM_HASH=YES</div><div> HTTP_UPSTREAM_IP_HASH=YES</div><div>@@ -236,6 +237,7 @@</div><div> --with-http_flv_module) HTTP_FLV=YES ;;</div><div> --with-http_mp4_module) HTTP_MP4=YES ;;</div><div> --with-http_gunzip_module) HTTP_GUNZIP=YES ;;</div><div>+ --with-http_brotli_static_module) HTTP_BROTLI_STATIC=YES ;;</div><div> --with-http_gzip_static_module) HTTP_GZIP_STATIC=YES ;;</div><div> --with-http_auth_request_module) HTTP_AUTH_REQUEST=YES ;;</div><div> --with-http_random_index_module) HTTP_RANDOM_INDEX=YES ;;</div><div>@@ -444,6 +446,7 @@</div><div> --with-http_flv_module enable ngx_http_flv_module</div><div> --with-http_mp4_module enable ngx_http_mp4_module</div><div> --with-http_gunzip_module enable ngx_http_gunzip_module</div><div>+ --with-http_brotli_static_module enable ngx_http_brotli_static_module</div><div> --with-http_gzip_static_module enable ngx_http_gzip_static_module</div><div> --with-http_auth_request_module enable ngx_http_auth_request_module</div><div> --with-http_random_index_module enable ngx_http_random_index_module</div><div>diff -r 87cf6ddb41c2 -r 81eacab152ef contrib/vim/syntax/nginx.vim</div><div>--- a/contrib/vim/syntax/nginx.vim<span class="gmail-Apple-tab-span" style="white-space:pre"> </span>Fri Feb 17 17:01:27 2017 +0300</div><div>+++ b/contrib/vim/syntax/nginx.vim<span class="gmail-Apple-tab-span" style="white-space:pre"> </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><div>diff -r 87cf6ddb41c2 -r 81eacab152ef misc/GNUmakefile</div><div>--- a/misc/GNUmakefile<span class="gmail-Apple-tab-span" style="white-space:pre"> </span>Fri Feb 17 17:01:27 2017 +0300</div><div>+++ b/misc/GNUmakefile<span class="gmail-Apple-tab-span" style="white-space:pre"> </span>Wed Feb 22 13:01:13 2017 +0100</div><div>@@ -74,6 +74,7 @@</div><div> <span class="gmail-Apple-tab-span" style="white-space:pre"> </span>--with-http_flv_module<span class="gmail-Apple-tab-span" style="white-space:pre"> </span>\</div><div> <span class="gmail-Apple-tab-span" style="white-space:pre"> </span>--with-http_mp4_module<span class="gmail-Apple-tab-span" style="white-space:pre"> </span>\</div><div> <span class="gmail-Apple-tab-span" style="white-space:pre"> </span>--with-http_gunzip_module<span class="gmail-Apple-tab-span" style="white-space:pre"> </span>\</div><div>+<span class="gmail-Apple-tab-span" style="white-space:pre"> </span>--with-http_brotli_static_module<span class="gmail-Apple-tab-span" style="white-space:pre"> </span>\</div><div> <span class="gmail-Apple-tab-span" style="white-space:pre"> </span>--with-http_gzip_static_module<span class="gmail-Apple-tab-span" style="white-space:pre"> </span>\</div><div> <span class="gmail-Apple-tab-span" style="white-space:pre"> </span>--with-http_auth_request_module<span class="gmail-Apple-tab-span" style="white-space:pre"> </span>\</div><div> <span class="gmail-Apple-tab-span" style="white-space:pre"> </span>--with-http_random_index_module<span class="gmail-Apple-tab-span" style="white-space:pre"> </span>\</div><div>diff -r 87cf6ddb41c2 -r 81eacab152ef src/http/modules/ngx_http_brotli_static_module.c</div><div>--- /dev/null<span class="gmail-Apple-tab-span" style="white-space:pre"> </span>Thu Jan 01 00:00:00 1970 +0000</div><div>+++ b/src/http/modules/ngx_http_brotli_static_module.c<span class="gmail-Apple-tab-span" style="white-space:pre"> </span>Wed Feb 22 13:01:13 2017 +0100</div><div>@@ -0,0 +1,331 @@</div><div>+</div><div>+/*</div><div>+ * Copyright (C) Igor Sysoev</div><div>+ * Copyright (C) Nginx, Inc.</div><div>+ */</div><div>+</div><div>+</div><div>+#include <ngx_config.h></div><div>+#include <ngx_core.h></div><div>+#include <ngx_http.h></div><div>+</div><div>+</div><div>+#define NGX_HTTP_BROTLI_STATIC_OFF 0</div><div>+#define NGX_HTTP_BROTLI_STATIC_ON 1</div><div>+#define NGX_HTTP_BROTLI_STATIC_ALWAYS 2</div><div>+</div><div>+</div><div>+typedef struct {</div><div>+ ngx_uint_t enable;</div><div>+} ngx_http_brotli_static_conf_t;</div><div>+</div><div>+</div><div>+static ngx_int_t ngx_http_brotli_static_handler(ngx_http_request_t *r);</div><div>+static void *ngx_http_brotli_static_create_conf(ngx_conf_t *cf);</div><div>+static char *ngx_http_brotli_static_merge_conf(ngx_conf_t *cf, void *parent,</div><div>+ void *child);</div><div>+static ngx_int_t ngx_http_brotli_static_init(ngx_conf_t *cf);</div><div>+</div><div>+</div><div>+static ngx_conf_enum_t ngx_http_brotli_static[] = {</div><div>+ { ngx_string("off"), NGX_HTTP_BROTLI_STATIC_OFF },</div><div>+ { ngx_string("on"), NGX_HTTP_BROTLI_STATIC_ON },</div><div>+ { ngx_string("always"), NGX_HTTP_BROTLI_STATIC_ALWAYS },</div><div>+ { ngx_null_string, 0 }</div><div>+};</div><div>+</div><div>+</div><div>+static ngx_command_t ngx_http_brotli_static_commands[] = {</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_brotli_static_conf_t, enable),</div><div>+ &ngx_http_brotli_static },</div><div>+</div><div>+ ngx_null_command</div><div>+};</div><div>+</div><div>+</div><div>+ngx_http_module_t ngx_http_brotli_static_module_ctx = {</div><div>+ NULL, /* preconfiguration */</div><div>+ ngx_http_brotli_static_init, /* postconfiguration */</div><div>+</div><div>+ NULL, /* create main configuration */</div><div>+ NULL, /* init main configuration */</div><div>+</div><div>+ NULL, /* create server configuration */</div><div>+ NULL, /* merge server configuration */</div><div>+</div><div>+ ngx_http_brotli_static_create_conf, /* create location configuration */</div><div>+ ngx_http_brotli_static_merge_conf /* merge location configuration */</div><div>+};</div><div>+</div><div>+</div><div>+ngx_module_t ngx_http_brotli_static_module = {</div><div>+ NGX_MODULE_V1,</div><div>+ &ngx_http_brotli_static_module_ctx, /* module context */</div><div>+ ngx_http_brotli_static_commands, /* module directives */</div><div>+ NGX_HTTP_MODULE, /* module type */</div><div>+ NULL, /* init master */</div><div>+ NULL, /* init module */</div><div>+ NULL, /* init process */</div><div>+ NULL, /* init thread */</div><div>+ NULL, /* exit thread */</div><div>+ NULL, /* exit process */</div><div>+ NULL, /* exit master */</div><div>+ NGX_MODULE_V1_PADDING</div><div>+};</div><div>+</div><div>+</div><div>+static ngx_int_t</div><div>+ngx_http_brotli_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_brotli_static_conf_t *bscf;</div><div>+</div><div>+ if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) {</div><div>+ return NGX_DECLINED;</div><div>+ }</div><div>+</div><div>+ if (r->uri.data[r->uri.len - 1] == '/') {</div><div>+ return NGX_DECLINED;</div><div>+ }</div><div>+</div><div>+ bscf = ngx_http_get_module_loc_conf(r, ngx_http_brotli_static_module);</div><div>+</div><div>+ if (bscf->enable == NGX_HTTP_BROTLI_STATIC_OFF) {</div><div>+ return NGX_DECLINED;</div><div>+ }</div><div>+</div><div>+ if (bscf->enable == NGX_HTTP_BROTLI_STATIC_ON) {</div><div>+ rc = ngx_http_brotli_ok(r);</div><div>+</div><div>+ } else {</div><div>+ /* always */</div><div>+ rc = NGX_OK;</div><div>+ }</div><div>+</div><div>+ clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);</div><div>+</div><div>+ if (!clcf->gzip_vary && rc != NGX_OK) {</div><div>+ return NGX_DECLINED;</div><div>+ }</div><div>+</div><div>+ log = r->connection->log;</div><div>+</div><div>+ p = ngx_http_map_uri_to_path(r, &path, &root, sizeof(".br") - 1);</div><div>+ if (p == NULL) {</div><div>+ return NGX_HTTP_INTERNAL_SERVER_ERROR;</div><div>+ }</div><div>+</div><div>+ *p++ = '.';</div><div>+ *p++ = 'b';</div><div>+ *p++ = 'r';</div><div>+ *p = '\0';</div><div>+</div><div>+ path.len = p - path.data;</div><div>+</div><div>+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,</div><div>+ "http filename: \"%s\"", path.data);</div><div>+</div><div>+ ngx_memzero(&of, sizeof(ngx_open_file_info_t));</div><div>+</div><div>+ of.read_ahead = clcf->read_ahead;</div><div>+ of.directio = clcf->directio;</div><div>+ of.valid = clcf->open_file_cache_valid;</div><div>+ of.min_uses = clcf->open_file_cache_min_uses;</div><div>+ of.errors = clcf->open_file_cache_errors;</div><div>+ of.events = clcf->open_file_cache_events;</div><div>+</div><div>+ if (ngx_http_set_disable_symlinks(r, clcf, &path, &of) != NGX_OK) {</div><div>+ return NGX_HTTP_INTERNAL_SERVER_ERROR;</div><div>+ }</div><div>+</div><div>+ if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)</div><div>+ != NGX_OK)</div><div>+ {</div><div>+ switch (of.err) {</div><div>+</div><div>+ case 0:</div><div>+ return NGX_HTTP_INTERNAL_SERVER_ERROR;</div><div>+</div><div>+ case NGX_ENOENT:</div><div>+ case NGX_ENOTDIR:</div><div>+ case NGX_ENAMETOOLONG:</div><div>+</div><div>+ return NGX_DECLINED;</div><div>+</div><div>+ case NGX_EACCES:</div><div>+#if (NGX_HAVE_OPENAT)</div><div>+ case NGX_EMLINK:</div><div>+ case NGX_ELOOP:</div><div>+#endif</div><div>+</div><div>+ level = NGX_LOG_ERR;</div><div>+ break;</div><div>+</div><div>+ default:</div><div>+</div><div>+ level = NGX_LOG_CRIT;</div><div>+ break;</div><div>+ }</div><div>+</div><div>+ ngx_log_error(level, log, of.err,</div><div>+ "%s \"%s\" failed", of.failed, path.data);</div><div>+</div><div>+ return NGX_DECLINED;</div><div>+ }</div><div>+</div><div>+ if (bscf->enable == NGX_HTTP_BROTLI_STATIC_ON) {</div><div>+ r->gzip_vary = 1;</div><div>+</div><div>+ if (rc != NGX_OK) {</div><div>+ return NGX_DECLINED;</div><div>+ }</div><div>+ }</div><div>+</div><div>+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http static fd: %d", of.fd);</div><div>+</div><div>+ if (of.is_dir) {</div><div>+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "http dir");</div><div>+ return NGX_DECLINED;</div><div>+ }</div><div>+</div><div>+#if !(NGX_WIN32) /* the not regular files are probably Unix specific */</div><div>+</div><div>+ if (!of.is_file) {</div><div>+ ngx_log_error(NGX_LOG_CRIT, log, 0,</div><div>+ "\"%s\" is not a regular file", path.data);</div><div>+</div><div>+ return NGX_HTTP_NOT_FOUND;</div><div>+ }</div><div>+</div><div>+#endif</div><div>+</div><div>+ r->root_tested = !r->error_page;</div><div>+</div><div>+ rc = ngx_http_discard_request_body(r);</div><div>+</div><div>+ if (rc != NGX_OK) {</div><div>+ return rc;</div><div>+ }</div><div>+</div><div>+ log->action = "sending response to client";</div><div>+</div><div>+ r->headers_out.status = NGX_HTTP_OK;</div><div>+ r->headers_out.content_length_n = of.size;</div><div>+ r->headers_out.last_modified_time = of.mtime;</div><div>+</div><div>+ if (ngx_http_set_etag(r) != NGX_OK) {</div><div>+ return NGX_HTTP_INTERNAL_SERVER_ERROR;</div><div>+ }</div><div>+</div><div>+ if (ngx_http_set_content_type(r) != NGX_OK) {</div><div>+ return NGX_HTTP_INTERNAL_SERVER_ERROR;</div><div>+ }</div><div>+</div><div>+ h = ngx_list_push(&r->headers_out.headers);</div><div>+ if (h == NULL) {</div><div>+ return NGX_ERROR;</div><div>+ }</div><div>+</div><div>+ h->hash = 1;</div><div>+ ngx_str_set(&h->key, "Content-Encoding");</div><div>+ ngx_str_set(&h->value, "br");</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>+</div><div>+ b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));</div><div>+ if (b == NULL) {</div><div>+ return NGX_HTTP_INTERNAL_SERVER_ERROR;</div><div>+ }</div><div>+</div><div>+ b->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t));</div><div>+ if (b->file == NULL) {</div><div>+ return NGX_HTTP_INTERNAL_SERVER_ERROR;</div><div>+ }</div><div>+</div><div>+ rc = ngx_http_send_header(r);</div><div>+</div><div>+ if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {</div><div>+ return rc;</div><div>+ }</div><div>+</div><div>+ b->file_pos = 0;</div><div>+ b->file_last = of.size;</div><div>+</div><div>+ b->in_file = b->file_last ? 1 : 0;</div><div>+ b->last_buf = (r == r->main) ? 1 : 0;</div><div>+ b->last_in_chain = 1;</div><div>+</div><div>+ b->file->fd = of.fd;</div><div>+ b->file->name = path;</div><div>+ b->file->log = log;</div><div>+ b->file->directio = of.is_directio;</div><div>+</div><div>+ out.buf = b;</div><div>+ out.next = NULL;</div><div>+</div><div>+ return ngx_http_output_filter(r, &out);</div><div>+}</div><div>+</div><div>+</div><div>+static void *</div><div>+ngx_http_brotli_static_create_conf(ngx_conf_t *cf)</div><div>+{</div><div>+ ngx_http_brotli_static_conf_t *conf;</div><div>+</div><div>+ conf = ngx_palloc(cf->pool, sizeof(ngx_http_brotli_static_conf_t));</div><div>+ if (conf == NULL) {</div><div>+ return NULL;</div><div>+ }</div><div>+</div><div>+ conf->enable = NGX_CONF_UNSET_UINT;</div><div>+</div><div>+ return conf;</div><div>+}</div><div>+</div><div>+</div><div>+static char *</div><div>+ngx_http_brotli_static_merge_conf(ngx_conf_t *cf, void *parent, void *child)</div><div>+{</div><div>+ ngx_http_brotli_static_conf_t *prev = parent;</div><div>+ ngx_http_brotli_static_conf_t *conf = child;</div><div>+</div><div>+ ngx_conf_merge_uint_value(conf->enable, prev->enable,</div><div>+ NGX_HTTP_BROTLI_STATIC_OFF);</div><div>+</div><div>+ return NGX_CONF_OK;</div><div>+}</div><div>+</div><div>+</div><div>+static ngx_int_t</div><div>+ngx_http_brotli_static_init(ngx_conf_t *cf)</div><div>+{</div><div>+ ngx_http_handler_pt *h;</div><div>+ ngx_http_core_main_conf_t *cmcf;</div><div>+</div><div>+ cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);</div><div>+</div><div>+ h = ngx_array_push(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers);</div><div>+ if (h == NULL) {</div><div>+ return NGX_ERROR;</div><div>+ }</div><div>+</div><div>+ *h = ngx_http_brotli_static_handler;</div><div>+</div><div>+ return NGX_OK;</div><div>+}</div><div>diff -r 87cf6ddb41c2 -r 81eacab152ef 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>Fri Feb 17 17:01:27 2017 +0300</div><div>+++ b/src/http/ngx_http_core_module.c<span class="gmail-Apple-tab-span" style="white-space:pre"> </span>Wed Feb 22 13:01:13 2017 +0100</div><div>@@ -73,9 +73,11 @@</div><div> void *conf);</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_BROTLI || NGX_HTTP_GZIP)</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>+#endif</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 char *ngx_http_gzip_disable(ngx_conf_t *cf, ngx_command_t *cmd,</div><div> void *conf);</div><div> #endif</div><div>@@ -2170,7 +2172,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>@@ -2296,16 +2298,20 @@</div><div> return NGX_OK;</div><div> }</div><div> </div><div>+#endif</div><div>+</div><div>+</div><div>+#if (NGX_HTTP_BROTLI || NGX_HTTP_GZIP)</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 +2319,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 +2328,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 +2370,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 +2379,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>@@ -2428,6 +2434,37 @@</div><div> #endif</div><div> </div><div> </div><div>+#if (NGX_HTTP_BROTLI)</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>+#endif</div><div>+</div><div>+</div><div> ngx_int_t</div><div> ngx_http_subrequest(ngx_http_request_t *r,</div><div> ngx_str_t *uri, ngx_str_t *args, ngx_http_request_t **psr,</div><div>diff -r 87cf6ddb41c2 -r 81eacab152ef 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>Fri Feb 17 17:01:27 2017 +0300</div><div>+++ b/src/http/ngx_http_core_module.h<span class="gmail-Apple-tab-span" style="white-space:pre"> </span>Wed Feb 22 13:01:13 2017 +0100</div><div>@@ -506,6 +506,9 @@</div><div> ngx_int_t ngx_http_gzip_ok(ngx_http_request_t *r);</div><div> #endif</div><div> </div><div>+#if (NGX_HTTP_BROTLI)</div><div>+ngx_int_t ngx_http_brotli_ok(ngx_http_request_t *r);</div><div>+#endif</div><div> </div><div> ngx_int_t ngx_http_subrequest(ngx_http_request_t *r,</div><div> ngx_str_t *uri, ngx_str_t *args, ngx_http_request_t **sr,</div><div><br></div><div><br></div>-- <br><div class="gmail_signature">С наилучшими пожеланиями, Евгений Ключников<br>WBR, Eugene Kluchnikov<br></div>
</div>