Mercurial > hg > nginx
diff src/http/v2/ngx_http_v2_module.c @ 7201:641306096f5b
HTTP/2: server push.
Resources to be pushed are configured with the "http2_push" directive.
Also, preload links from the Link response headers, as described in
https://www.w3.org/TR/preload/#server-push-http-2, can be pushed, if
enabled with the "http2_push_preload" directive.
Only relative URIs with absolute paths can be pushed.
The number of concurrent pushes is normally limited by a client, but
cannot exceed a hard limit set by the "http2_max_concurrent_pushes"
directive.
author | Ruslan Ermilov <ru@nginx.com> |
---|---|
date | Thu, 08 Feb 2018 09:55:03 +0300 |
parents | 2a288909abc6 |
children | de0b6f1fe4e4 |
line wrap: on
line diff
--- a/src/http/v2/ngx_http_v2_module.c +++ b/src/http/v2/ngx_http_v2_module.c @@ -27,6 +27,8 @@ static void *ngx_http_v2_create_loc_conf static char *ngx_http_v2_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child); +static char *ngx_http_v2_push(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); + static char *ngx_http_v2_recv_buffer_size(ngx_conf_t *cf, void *post, void *data); static char *ngx_http_v2_pool_size(ngx_conf_t *cf, void *post, void *data); @@ -73,6 +75,13 @@ static ngx_command_t ngx_http_v2_comman offsetof(ngx_http_v2_srv_conf_t, concurrent_streams), NULL }, + { ngx_string("http2_max_concurrent_pushes"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_http_v2_srv_conf_t, concurrent_pushes), + NULL }, + { ngx_string("http2_max_requests"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, ngx_conf_set_num_slot, @@ -129,6 +138,20 @@ static ngx_command_t ngx_http_v2_comman offsetof(ngx_http_v2_loc_conf_t, chunk_size), &ngx_http_v2_chunk_size_post }, + { ngx_string("http2_push_preload"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_v2_loc_conf_t, push_preload), + NULL }, + + { ngx_string("http2_push"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_http_v2_push, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + NULL }, + { ngx_string("spdy_recv_buffer_size"), NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, ngx_http_v2_spdy_deprecated, @@ -329,6 +352,7 @@ ngx_http_v2_create_srv_conf(ngx_conf_t * h2scf->pool_size = NGX_CONF_UNSET_SIZE; h2scf->concurrent_streams = NGX_CONF_UNSET_UINT; + h2scf->concurrent_pushes = NGX_CONF_UNSET_UINT; h2scf->max_requests = NGX_CONF_UNSET_UINT; h2scf->max_field_size = NGX_CONF_UNSET_SIZE; @@ -355,6 +379,8 @@ ngx_http_v2_merge_srv_conf(ngx_conf_t *c ngx_conf_merge_uint_value(conf->concurrent_streams, prev->concurrent_streams, 128); + ngx_conf_merge_uint_value(conf->concurrent_pushes, + prev->concurrent_pushes, 10); ngx_conf_merge_uint_value(conf->max_requests, prev->max_requests, 1000); ngx_conf_merge_size_value(conf->max_field_size, prev->max_field_size, @@ -386,8 +412,17 @@ ngx_http_v2_create_loc_conf(ngx_conf_t * return NULL; } + /* + * set by ngx_pcalloc(): + * + * h2lcf->pushes = NULL; + */ + h2lcf->chunk_size = NGX_CONF_UNSET_SIZE; + h2lcf->push_preload = NGX_CONF_UNSET; + h2lcf->push = NGX_CONF_UNSET; + return h2lcf; } @@ -400,6 +435,72 @@ ngx_http_v2_merge_loc_conf(ngx_conf_t *c ngx_conf_merge_size_value(conf->chunk_size, prev->chunk_size, 8 * 1024); + ngx_conf_merge_value(conf->push, prev->push, 1); + + if (conf->push && conf->pushes == NULL) { + conf->pushes = prev->pushes; + } + + ngx_conf_merge_value(conf->push_preload, prev->push_preload, 0); + + return NGX_CONF_OK; +} + + +static char * +ngx_http_v2_push(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_http_v2_loc_conf_t *h2lcf = conf; + + ngx_str_t *value; + ngx_http_complex_value_t *cv; + ngx_http_compile_complex_value_t ccv; + + value = cf->args->elts; + + if (ngx_strcmp(value[1].data, "off") == 0) { + + if (h2lcf->pushes) { + return "\"off\" parameter cannot be used with URI"; + } + + if (h2lcf->push == 0) { + return "is duplicate"; + } + + h2lcf->push = 0; + return NGX_CONF_OK; + } + + if (h2lcf->push == 0) { + return "URI cannot be used with \"off\" parameter"; + } + + h2lcf->push = 1; + + if (h2lcf->pushes == NULL) { + h2lcf->pushes = ngx_array_create(cf->pool, 1, + sizeof(ngx_http_complex_value_t)); + if (h2lcf->pushes == NULL) { + return NGX_CONF_ERROR; + } + } + + cv = ngx_array_push(h2lcf->pushes); + if (cv == NULL) { + return NGX_CONF_ERROR; + } + + ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = &value[1]; + ccv.complex_value = cv; + + if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } + return NGX_CONF_OK; }