comparison 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
comparison
equal deleted inserted replaced
7200:cadb43014c7c 7201:641306096f5b
24 static char *ngx_http_v2_merge_srv_conf(ngx_conf_t *cf, void *parent, 24 static char *ngx_http_v2_merge_srv_conf(ngx_conf_t *cf, void *parent,
25 void *child); 25 void *child);
26 static void *ngx_http_v2_create_loc_conf(ngx_conf_t *cf); 26 static void *ngx_http_v2_create_loc_conf(ngx_conf_t *cf);
27 static char *ngx_http_v2_merge_loc_conf(ngx_conf_t *cf, void *parent, 27 static char *ngx_http_v2_merge_loc_conf(ngx_conf_t *cf, void *parent,
28 void *child); 28 void *child);
29
30 static char *ngx_http_v2_push(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
29 31
30 static char *ngx_http_v2_recv_buffer_size(ngx_conf_t *cf, void *post, 32 static char *ngx_http_v2_recv_buffer_size(ngx_conf_t *cf, void *post,
31 void *data); 33 void *data);
32 static char *ngx_http_v2_pool_size(ngx_conf_t *cf, void *post, void *data); 34 static char *ngx_http_v2_pool_size(ngx_conf_t *cf, void *post, void *data);
33 static char *ngx_http_v2_preread_size(ngx_conf_t *cf, void *post, void *data); 35 static char *ngx_http_v2_preread_size(ngx_conf_t *cf, void *post, void *data);
71 ngx_conf_set_num_slot, 73 ngx_conf_set_num_slot,
72 NGX_HTTP_SRV_CONF_OFFSET, 74 NGX_HTTP_SRV_CONF_OFFSET,
73 offsetof(ngx_http_v2_srv_conf_t, concurrent_streams), 75 offsetof(ngx_http_v2_srv_conf_t, concurrent_streams),
74 NULL }, 76 NULL },
75 77
78 { ngx_string("http2_max_concurrent_pushes"),
79 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
80 ngx_conf_set_num_slot,
81 NGX_HTTP_SRV_CONF_OFFSET,
82 offsetof(ngx_http_v2_srv_conf_t, concurrent_pushes),
83 NULL },
84
76 { ngx_string("http2_max_requests"), 85 { ngx_string("http2_max_requests"),
77 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, 86 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
78 ngx_conf_set_num_slot, 87 ngx_conf_set_num_slot,
79 NGX_HTTP_SRV_CONF_OFFSET, 88 NGX_HTTP_SRV_CONF_OFFSET,
80 offsetof(ngx_http_v2_srv_conf_t, max_requests), 89 offsetof(ngx_http_v2_srv_conf_t, max_requests),
126 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, 135 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
127 ngx_conf_set_size_slot, 136 ngx_conf_set_size_slot,
128 NGX_HTTP_LOC_CONF_OFFSET, 137 NGX_HTTP_LOC_CONF_OFFSET,
129 offsetof(ngx_http_v2_loc_conf_t, chunk_size), 138 offsetof(ngx_http_v2_loc_conf_t, chunk_size),
130 &ngx_http_v2_chunk_size_post }, 139 &ngx_http_v2_chunk_size_post },
140
141 { ngx_string("http2_push_preload"),
142 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
143 ngx_conf_set_flag_slot,
144 NGX_HTTP_LOC_CONF_OFFSET,
145 offsetof(ngx_http_v2_loc_conf_t, push_preload),
146 NULL },
147
148 { ngx_string("http2_push"),
149 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
150 ngx_http_v2_push,
151 NGX_HTTP_LOC_CONF_OFFSET,
152 0,
153 NULL },
131 154
132 { ngx_string("spdy_recv_buffer_size"), 155 { ngx_string("spdy_recv_buffer_size"),
133 NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, 156 NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
134 ngx_http_v2_spdy_deprecated, 157 ngx_http_v2_spdy_deprecated,
135 NGX_HTTP_MAIN_CONF_OFFSET, 158 NGX_HTTP_MAIN_CONF_OFFSET,
327 } 350 }
328 351
329 h2scf->pool_size = NGX_CONF_UNSET_SIZE; 352 h2scf->pool_size = NGX_CONF_UNSET_SIZE;
330 353
331 h2scf->concurrent_streams = NGX_CONF_UNSET_UINT; 354 h2scf->concurrent_streams = NGX_CONF_UNSET_UINT;
355 h2scf->concurrent_pushes = NGX_CONF_UNSET_UINT;
332 h2scf->max_requests = NGX_CONF_UNSET_UINT; 356 h2scf->max_requests = NGX_CONF_UNSET_UINT;
333 357
334 h2scf->max_field_size = NGX_CONF_UNSET_SIZE; 358 h2scf->max_field_size = NGX_CONF_UNSET_SIZE;
335 h2scf->max_header_size = NGX_CONF_UNSET_SIZE; 359 h2scf->max_header_size = NGX_CONF_UNSET_SIZE;
336 360
353 377
354 ngx_conf_merge_size_value(conf->pool_size, prev->pool_size, 4096); 378 ngx_conf_merge_size_value(conf->pool_size, prev->pool_size, 4096);
355 379
356 ngx_conf_merge_uint_value(conf->concurrent_streams, 380 ngx_conf_merge_uint_value(conf->concurrent_streams,
357 prev->concurrent_streams, 128); 381 prev->concurrent_streams, 128);
382 ngx_conf_merge_uint_value(conf->concurrent_pushes,
383 prev->concurrent_pushes, 10);
358 ngx_conf_merge_uint_value(conf->max_requests, prev->max_requests, 1000); 384 ngx_conf_merge_uint_value(conf->max_requests, prev->max_requests, 1000);
359 385
360 ngx_conf_merge_size_value(conf->max_field_size, prev->max_field_size, 386 ngx_conf_merge_size_value(conf->max_field_size, prev->max_field_size,
361 4096); 387 4096);
362 ngx_conf_merge_size_value(conf->max_header_size, prev->max_header_size, 388 ngx_conf_merge_size_value(conf->max_header_size, prev->max_header_size,
384 h2lcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_v2_loc_conf_t)); 410 h2lcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_v2_loc_conf_t));
385 if (h2lcf == NULL) { 411 if (h2lcf == NULL) {
386 return NULL; 412 return NULL;
387 } 413 }
388 414
415 /*
416 * set by ngx_pcalloc():
417 *
418 * h2lcf->pushes = NULL;
419 */
420
389 h2lcf->chunk_size = NGX_CONF_UNSET_SIZE; 421 h2lcf->chunk_size = NGX_CONF_UNSET_SIZE;
422
423 h2lcf->push_preload = NGX_CONF_UNSET;
424 h2lcf->push = NGX_CONF_UNSET;
390 425
391 return h2lcf; 426 return h2lcf;
392 } 427 }
393 428
394 429
397 { 432 {
398 ngx_http_v2_loc_conf_t *prev = parent; 433 ngx_http_v2_loc_conf_t *prev = parent;
399 ngx_http_v2_loc_conf_t *conf = child; 434 ngx_http_v2_loc_conf_t *conf = child;
400 435
401 ngx_conf_merge_size_value(conf->chunk_size, prev->chunk_size, 8 * 1024); 436 ngx_conf_merge_size_value(conf->chunk_size, prev->chunk_size, 8 * 1024);
437
438 ngx_conf_merge_value(conf->push, prev->push, 1);
439
440 if (conf->push && conf->pushes == NULL) {
441 conf->pushes = prev->pushes;
442 }
443
444 ngx_conf_merge_value(conf->push_preload, prev->push_preload, 0);
445
446 return NGX_CONF_OK;
447 }
448
449
450 static char *
451 ngx_http_v2_push(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
452 {
453 ngx_http_v2_loc_conf_t *h2lcf = conf;
454
455 ngx_str_t *value;
456 ngx_http_complex_value_t *cv;
457 ngx_http_compile_complex_value_t ccv;
458
459 value = cf->args->elts;
460
461 if (ngx_strcmp(value[1].data, "off") == 0) {
462
463 if (h2lcf->pushes) {
464 return "\"off\" parameter cannot be used with URI";
465 }
466
467 if (h2lcf->push == 0) {
468 return "is duplicate";
469 }
470
471 h2lcf->push = 0;
472 return NGX_CONF_OK;
473 }
474
475 if (h2lcf->push == 0) {
476 return "URI cannot be used with \"off\" parameter";
477 }
478
479 h2lcf->push = 1;
480
481 if (h2lcf->pushes == NULL) {
482 h2lcf->pushes = ngx_array_create(cf->pool, 1,
483 sizeof(ngx_http_complex_value_t));
484 if (h2lcf->pushes == NULL) {
485 return NGX_CONF_ERROR;
486 }
487 }
488
489 cv = ngx_array_push(h2lcf->pushes);
490 if (cv == NULL) {
491 return NGX_CONF_ERROR;
492 }
493
494 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
495
496 ccv.cf = cf;
497 ccv.value = &value[1];
498 ccv.complex_value = cv;
499
500 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
501 return NGX_CONF_ERROR;
502 }
402 503
403 return NGX_CONF_OK; 504 return NGX_CONF_OK;
404 } 505 }
405 506
406 507