nginxtra 1.0.15.0 → 1.2.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (147) hide show
  1. data/VERSION +1 -1
  2. data/bin/nginxtra +1 -1
  3. data/lib/nginxtra/action.rb +10 -0
  4. data/lib/nginxtra/actions/compile.rb +16 -2
  5. data/lib/nginxtra/actions/start.rb +18 -2
  6. data/lib/nginxtra/actions/status.rb +1 -10
  7. data/lib/nginxtra/actions/stop.rb +18 -0
  8. data/lib/nginxtra/cli.rb +12 -3
  9. data/lib/nginxtra/config.rb +10 -0
  10. data/src/nginx/CHANGES +311 -90
  11. data/src/nginx/CHANGES.ru +315 -88
  12. data/src/nginx/auto/lib/pcre/conf +22 -5
  13. data/src/nginx/auto/lib/pcre/make +1 -1
  14. data/src/nginx/auto/modules +14 -3
  15. data/src/nginx/auto/options +17 -3
  16. data/src/nginx/auto/os/freebsd +8 -0
  17. data/src/nginx/auto/os/linux +5 -4
  18. data/src/nginx/auto/os/solaris +2 -1
  19. data/src/nginx/auto/sources +10 -2
  20. data/src/nginx/auto/summary +2 -0
  21. data/src/nginx/auto/types/sizeof +2 -1
  22. data/src/nginx/auto/types/typedef +1 -1
  23. data/src/nginx/auto/types/uintptr_t +7 -4
  24. data/src/nginx/auto/unix +82 -21
  25. data/src/nginx/conf/fastcgi.conf +1 -0
  26. data/src/nginx/conf/fastcgi_params +1 -0
  27. data/src/nginx/conf/scgi_params +1 -0
  28. data/src/nginx/conf/uwsgi_params +1 -0
  29. data/src/nginx/man/nginx.8 +49 -49
  30. data/src/nginx/src/core/nginx.c +10 -12
  31. data/src/nginx/src/core/nginx.h +2 -2
  32. data/src/nginx/src/core/ngx_buf.c +9 -7
  33. data/src/nginx/src/core/ngx_buf.h +2 -2
  34. data/src/nginx/src/core/ngx_conf_file.c +4 -11
  35. data/src/nginx/src/core/ngx_conf_file.h +1 -1
  36. data/src/nginx/src/core/ngx_connection.c +52 -1
  37. data/src/nginx/src/core/ngx_connection.h +6 -0
  38. data/src/nginx/src/core/ngx_core.h +5 -0
  39. data/src/nginx/src/core/ngx_cycle.c +1 -1
  40. data/src/nginx/src/core/ngx_cycle.h +2 -2
  41. data/src/nginx/src/core/ngx_file.c +1 -1
  42. data/src/nginx/src/core/ngx_inet.c +11 -8
  43. data/src/nginx/src/core/ngx_murmurhash.h +1 -1
  44. data/src/nginx/src/core/ngx_open_file_cache.c +343 -38
  45. data/src/nginx/src/core/ngx_open_file_cache.h +10 -0
  46. data/src/nginx/src/core/ngx_output_chain.c +2 -1
  47. data/src/nginx/src/core/ngx_parse.h +0 -3
  48. data/src/nginx/src/core/ngx_rbtree.c +1 -2
  49. data/src/nginx/src/core/ngx_regex.c +263 -5
  50. data/src/nginx/src/core/ngx_regex.h +6 -2
  51. data/src/nginx/src/core/ngx_resolver.c +88 -21
  52. data/src/nginx/src/core/ngx_resolver.h +7 -8
  53. data/src/nginx/src/core/ngx_shmtx.c +69 -44
  54. data/src/nginx/src/core/ngx_shmtx.h +12 -1
  55. data/src/nginx/src/core/ngx_slab.c +3 -3
  56. data/src/nginx/src/core/ngx_slab.h +1 -1
  57. data/src/nginx/src/core/ngx_string.c +19 -16
  58. data/src/nginx/src/core/ngx_times.c +2 -2
  59. data/src/nginx/src/event/modules/ngx_epoll_module.c +2 -2
  60. data/src/nginx/src/event/modules/ngx_eventport_module.c +1 -1
  61. data/src/nginx/src/event/modules/ngx_kqueue_module.c +1 -1
  62. data/src/nginx/src/event/ngx_event.c +25 -17
  63. data/src/nginx/src/event/ngx_event_openssl.c +3 -1
  64. data/src/nginx/src/event/ngx_event_pipe.c +108 -85
  65. data/src/nginx/src/event/ngx_event_pipe.h +1 -2
  66. data/src/nginx/src/event/ngx_event_timer.c +2 -3
  67. data/src/nginx/src/http/modules/ngx_http_access_module.c +9 -4
  68. data/src/nginx/src/http/modules/ngx_http_browser_module.c +5 -3
  69. data/src/nginx/src/http/modules/ngx_http_chunked_filter_module.c +1 -1
  70. data/src/nginx/src/http/modules/ngx_http_degradation_module.c +1 -1
  71. data/src/nginx/src/http/modules/ngx_http_fastcgi_module.c +144 -22
  72. data/src/nginx/src/http/modules/ngx_http_flv_module.c +8 -0
  73. data/src/nginx/src/http/modules/ngx_http_geo_module.c +3 -3
  74. data/src/nginx/src/http/modules/ngx_http_gzip_filter_module.c +20 -6
  75. data/src/nginx/src/http/modules/ngx_http_gzip_static_module.c +8 -0
  76. data/src/nginx/src/http/modules/ngx_http_headers_filter_module.c +23 -27
  77. data/src/nginx/src/http/modules/ngx_http_image_filter_module.c +1 -3
  78. data/src/nginx/src/http/modules/ngx_http_index_module.c +24 -0
  79. data/src/nginx/src/http/modules/ngx_http_limit_conn_module.c +747 -0
  80. data/src/nginx/src/http/modules/ngx_http_limit_req_module.c +289 -133
  81. data/src/nginx/src/http/modules/ngx_http_log_module.c +34 -6
  82. data/src/nginx/src/http/modules/ngx_http_memcached_module.c +19 -3
  83. data/src/nginx/src/http/modules/ngx_http_mp4_module.c +8 -0
  84. data/src/nginx/src/http/modules/ngx_http_proxy_module.c +1446 -239
  85. data/src/nginx/src/http/modules/ngx_http_realip_module.c +4 -10
  86. data/src/nginx/src/http/modules/ngx_http_scgi_module.c +90 -21
  87. data/src/nginx/src/http/modules/ngx_http_split_clients_module.c +8 -11
  88. data/src/nginx/src/http/modules/ngx_http_ssi_filter_module.c +16 -6
  89. data/src/nginx/src/http/modules/ngx_http_static_module.c +8 -0
  90. data/src/nginx/src/http/modules/ngx_http_upstream_ip_hash_module.c +2 -2
  91. data/src/nginx/src/http/modules/ngx_http_upstream_keepalive_module.c +570 -0
  92. data/src/nginx/src/http/modules/ngx_http_userid_filter_module.c +1 -5
  93. data/src/nginx/src/http/modules/ngx_http_uwsgi_module.c +77 -26
  94. data/src/nginx/src/http/modules/ngx_http_xslt_filter_module.c +171 -37
  95. data/src/nginx/src/http/modules/perl/nginx.pm +2 -1
  96. data/src/nginx/src/http/modules/perl/nginx.xs +4 -0
  97. data/src/nginx/src/http/ngx_http.c +8 -1
  98. data/src/nginx/src/http/ngx_http.h +1 -0
  99. data/src/nginx/src/http/ngx_http_busy_lock.c +2 -2
  100. data/src/nginx/src/http/ngx_http_cache.h +12 -1
  101. data/src/nginx/src/http/ngx_http_copy_filter_module.c +4 -3
  102. data/src/nginx/src/http/ngx_http_core_module.c +303 -37
  103. data/src/nginx/src/http/ngx_http_core_module.h +15 -0
  104. data/src/nginx/src/http/ngx_http_file_cache.c +226 -52
  105. data/src/nginx/src/http/ngx_http_parse.c +69 -3
  106. data/src/nginx/src/http/ngx_http_postpone_filter_module.c +4 -4
  107. data/src/nginx/src/http/ngx_http_request.c +61 -27
  108. data/src/nginx/src/http/ngx_http_request.h +3 -3
  109. data/src/nginx/src/http/ngx_http_request_body.c +1 -1
  110. data/src/nginx/src/http/ngx_http_script.c +6 -0
  111. data/src/nginx/src/http/ngx_http_upstream.c +200 -47
  112. data/src/nginx/src/http/ngx_http_upstream.h +20 -1
  113. data/src/nginx/src/http/ngx_http_upstream_round_robin.c +22 -6
  114. data/src/nginx/src/http/ngx_http_upstream_round_robin.h +1 -0
  115. data/src/nginx/src/http/ngx_http_variables.c +123 -4
  116. data/src/nginx/src/mail/ngx_mail.c +13 -0
  117. data/src/nginx/src/mail/ngx_mail.h +12 -0
  118. data/src/nginx/src/mail/ngx_mail_core_module.c +100 -15
  119. data/src/nginx/src/os/unix/ngx_daemon.c +2 -1
  120. data/src/nginx/src/os/unix/ngx_darwin.h +3 -0
  121. data/src/nginx/src/os/unix/ngx_darwin_config.h +1 -0
  122. data/src/nginx/src/os/unix/ngx_darwin_init.c +30 -0
  123. data/src/nginx/src/os/unix/ngx_darwin_sendfile_chain.c +11 -5
  124. data/src/nginx/src/os/unix/ngx_errno.h +5 -0
  125. data/src/nginx/src/os/unix/ngx_files.h +50 -1
  126. data/src/nginx/src/os/unix/ngx_freebsd.h +2 -1
  127. data/src/nginx/src/os/unix/ngx_freebsd_config.h +2 -0
  128. data/src/nginx/src/os/unix/ngx_freebsd_init.c +4 -3
  129. data/src/nginx/src/os/unix/ngx_freebsd_rfork_thread.c +2 -2
  130. data/src/nginx/src/os/unix/ngx_freebsd_sendfile_chain.c +12 -6
  131. data/src/nginx/src/os/unix/ngx_gcc_atomic_sparc64.h +1 -1
  132. data/src/nginx/src/os/unix/ngx_linux_config.h +1 -0
  133. data/src/nginx/src/os/unix/ngx_linux_sendfile_chain.c +6 -4
  134. data/src/nginx/src/os/unix/ngx_os.h +0 -1
  135. data/src/nginx/src/os/unix/ngx_posix_config.h +3 -0
  136. data/src/nginx/src/os/unix/ngx_process.c +50 -11
  137. data/src/nginx/src/os/unix/ngx_process.h +1 -0
  138. data/src/nginx/src/os/unix/ngx_process_cycle.c +6 -15
  139. data/src/nginx/src/os/unix/ngx_readv_chain.c +8 -0
  140. data/src/nginx/src/os/unix/ngx_setaffinity.c +69 -0
  141. data/src/nginx/src/os/unix/ngx_setaffinity.h +23 -0
  142. data/src/nginx/src/os/unix/ngx_setproctitle.c +1 -1
  143. data/src/nginx/src/os/unix/ngx_solaris_config.h +2 -0
  144. data/src/nginx/src/os/unix/ngx_solaris_sendfilev_chain.c +11 -3
  145. data/src/nginx/src/os/unix/ngx_writev_chain.c +7 -3
  146. metadata +7 -4
  147. data/src/nginx/src/http/modules/ngx_http_limit_zone_module.c +0 -553
@@ -80,6 +80,8 @@ static ssize_t ngx_http_log_script_write(ngx_http_request_t *r,
80
80
 
81
81
  static u_char *ngx_http_log_connection(ngx_http_request_t *r, u_char *buf,
82
82
  ngx_http_log_op_t *op);
83
+ static u_char *ngx_http_log_connection_requests(ngx_http_request_t *r,
84
+ u_char *buf, ngx_http_log_op_t *op);
83
85
  static u_char *ngx_http_log_pipe(ngx_http_request_t *r, u_char *buf,
84
86
  ngx_http_log_op_t *op);
85
87
  static u_char *ngx_http_log_time(ngx_http_request_t *r, u_char *buf,
@@ -193,6 +195,8 @@ static ngx_str_t ngx_http_combined_fmt =
193
195
 
194
196
  static ngx_http_log_var_t ngx_http_log_vars[] = {
195
197
  { ngx_string("connection"), NGX_ATOMIC_T_LEN, ngx_http_log_connection },
198
+ { ngx_string("connection_requests"), NGX_INT_T_LEN,
199
+ ngx_http_log_connection_requests },
196
200
  { ngx_string("pipe"), 1, ngx_http_log_pipe },
197
201
  { ngx_string("time_local"), sizeof("28/Sep/1970:12:00:00 +0600") - 1,
198
202
  ngx_http_log_time },
@@ -373,6 +377,8 @@ ngx_http_log_script_write(ngx_http_request_t *r, ngx_http_log_script_t *script,
373
377
  ngx_http_log_loc_conf_t *llcf;
374
378
  ngx_http_core_loc_conf_t *clcf;
375
379
 
380
+ clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
381
+
376
382
  if (!r->root_tested) {
377
383
 
378
384
  /* test root directory existence */
@@ -384,8 +390,6 @@ ngx_http_log_script_write(ngx_http_request_t *r, ngx_http_log_script_t *script,
384
390
 
385
391
  path.data[root] = '\0';
386
392
 
387
- clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
388
-
389
393
  ngx_memzero(&of, sizeof(ngx_open_file_info_t));
390
394
 
391
395
  of.valid = clcf->open_file_cache_valid;
@@ -395,6 +399,11 @@ ngx_http_log_script_write(ngx_http_request_t *r, ngx_http_log_script_t *script,
395
399
  of.errors = clcf->open_file_cache_errors;
396
400
  of.events = clcf->open_file_cache_events;
397
401
 
402
+ if (ngx_http_set_disable_symlinks(r, clcf, &path, &of) != NGX_OK) {
403
+ /* simulate successful logging */
404
+ return len;
405
+ }
406
+
398
407
  if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
399
408
  != NGX_OK)
400
409
  {
@@ -442,6 +451,11 @@ ngx_http_log_script_write(ngx_http_request_t *r, ngx_http_log_script_t *script,
442
451
  of.min_uses = llcf->open_file_cache_min_uses;
443
452
  of.directio = NGX_OPEN_FILE_DIRECTIO_OFF;
444
453
 
454
+ if (ngx_http_set_disable_symlinks(r, clcf, &log, &of) != NGX_OK) {
455
+ /* simulate successful logging */
456
+ return len;
457
+ }
458
+
445
459
  if (ngx_open_cached_file(llcf->open_file_cache, &log, &of, r->pool)
446
460
  != NGX_OK)
447
461
  {
@@ -491,7 +505,15 @@ static u_char *
491
505
  ngx_http_log_connection(ngx_http_request_t *r, u_char *buf,
492
506
  ngx_http_log_op_t *op)
493
507
  {
494
- return ngx_sprintf(buf, "%ui", r->connection->number);
508
+ return ngx_sprintf(buf, "%uA", r->connection->number);
509
+ }
510
+
511
+
512
+ static u_char *
513
+ ngx_http_log_connection_requests(ngx_http_request_t *r, u_char *buf,
514
+ ngx_http_log_op_t *op)
515
+ {
516
+ return ngx_sprintf(buf, "%ui", r->connection->requests);
495
517
  }
496
518
 
497
519
 
@@ -972,7 +994,7 @@ buffer:
972
994
 
973
995
  if (buf == NGX_ERROR) {
974
996
  ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
975
- "invalid parameter \"%V\"", &value[3]);
997
+ "invalid buffer value \"%V\"", &name);
976
998
  return NGX_CONF_ERROR;
977
999
  }
978
1000
 
@@ -1005,6 +1027,12 @@ ngx_http_log_set_format(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1005
1027
  ngx_uint_t i;
1006
1028
  ngx_http_log_fmt_t *fmt;
1007
1029
 
1030
+ if (cf->cmd_type != NGX_HTTP_MAIN_CONF) {
1031
+ ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1032
+ "the \"log_format\" directive may be used "
1033
+ "only on \"http\" level");
1034
+ }
1035
+
1008
1036
  value = cf->args->elts;
1009
1037
 
1010
1038
  fmt = lmcf->formats.elts;
@@ -1243,7 +1271,7 @@ ngx_http_log_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1243
1271
  s.data = value[i].data + 9;
1244
1272
 
1245
1273
  inactive = ngx_parse_time(&s, 1);
1246
- if (inactive < 0) {
1274
+ if (inactive == (time_t) NGX_ERROR) {
1247
1275
  goto failed;
1248
1276
  }
1249
1277
 
@@ -1266,7 +1294,7 @@ ngx_http_log_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1266
1294
  s.data = value[i].data + 6;
1267
1295
 
1268
1296
  valid = ngx_parse_time(&s, 1);
1269
- if (valid < 0) {
1297
+ if (valid == (time_t) NGX_ERROR) {
1270
1298
  goto failed;
1271
1299
  }
1272
1300
 
@@ -345,8 +345,8 @@ found:
345
345
 
346
346
  while (*p && *p++ != CR) { /* void */ }
347
347
 
348
- r->headers_out.content_length_n = ngx_atoof(len, p - len - 1);
349
- if (r->headers_out.content_length_n == -1) {
348
+ u->headers_in.content_length_n = ngx_atoof(len, p - len - 1);
349
+ if (u->headers_in.content_length_n == -1) {
350
350
  ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
351
351
  "memcached sent invalid length in response \"%V\" "
352
352
  "for key \"%V\"",
@@ -367,6 +367,7 @@ found:
367
367
 
368
368
  u->headers_in.status_n = 404;
369
369
  u->state->status = 404;
370
+ u->keepalive = 1;
370
371
 
371
372
  return NGX_OK;
372
373
  }
@@ -408,7 +409,7 @@ ngx_http_memcached_filter(void *data, ssize_t bytes)
408
409
  u = ctx->request->upstream;
409
410
  b = &u->buffer;
410
411
 
411
- if (u->length == ctx->rest) {
412
+ if (u->length == (ssize_t) ctx->rest) {
412
413
 
413
414
  if (ngx_strncmp(b->last,
414
415
  ngx_http_memcached_end + NGX_HTTP_MEMCACHED_END - ctx->rest,
@@ -427,6 +428,10 @@ ngx_http_memcached_filter(void *data, ssize_t bytes)
427
428
  u->length -= bytes;
428
429
  ctx->rest -= bytes;
429
430
 
431
+ if (u->length == 0) {
432
+ u->keepalive = 1;
433
+ }
434
+
430
435
  return NGX_OK;
431
436
  }
432
437
 
@@ -464,6 +469,13 @@ ngx_http_memcached_filter(void *data, ssize_t bytes)
464
469
  if (ngx_strncmp(last, ngx_http_memcached_end, b->last - last) != 0) {
465
470
  ngx_log_error(NGX_LOG_ERR, ctx->request->connection->log, 0,
466
471
  "memcached sent invalid trailer");
472
+
473
+ b->last = last;
474
+ cl->buf->last = last;
475
+ u->length = 0;
476
+ ctx->rest = 0;
477
+
478
+ return NGX_OK;
467
479
  }
468
480
 
469
481
  ctx->rest -= b->last - last;
@@ -471,6 +483,10 @@ ngx_http_memcached_filter(void *data, ssize_t bytes)
471
483
  cl->buf->last = last;
472
484
  u->length = ctx->rest;
473
485
 
486
+ if (u->length == 0) {
487
+ u->keepalive = 1;
488
+ }
489
+
474
490
  return NGX_OK;
475
491
  }
476
492
 
@@ -442,6 +442,10 @@ ngx_http_mp4_handler(ngx_http_request_t *r)
442
442
  of.errors = clcf->open_file_cache_errors;
443
443
  of.events = clcf->open_file_cache_events;
444
444
 
445
+ if (ngx_http_set_disable_symlinks(r, clcf, &path, &of) != NGX_OK) {
446
+ return NGX_HTTP_INTERNAL_SERVER_ERROR;
447
+ }
448
+
445
449
  if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
446
450
  != NGX_OK)
447
451
  {
@@ -459,6 +463,10 @@ ngx_http_mp4_handler(ngx_http_request_t *r)
459
463
  break;
460
464
 
461
465
  case NGX_EACCES:
466
+ #if (NGX_HAVE_OPENAT)
467
+ case NGX_EMLINK:
468
+ case NGX_ELOOP:
469
+ #endif
462
470
 
463
471
  level = NGX_LOG_ERR;
464
472
  rc = NGX_HTTP_FORBIDDEN;
@@ -10,25 +10,23 @@
10
10
  #include <ngx_http.h>
11
11
 
12
12
 
13
- typedef struct ngx_http_proxy_redirect_s ngx_http_proxy_redirect_t;
13
+ typedef struct ngx_http_proxy_rewrite_s ngx_http_proxy_rewrite_t;
14
14
 
15
- typedef ngx_int_t (*ngx_http_proxy_redirect_pt)(ngx_http_request_t *r,
16
- ngx_table_elt_t *h, size_t prefix, ngx_http_proxy_redirect_t *pr);
15
+ typedef ngx_int_t (*ngx_http_proxy_rewrite_pt)(ngx_http_request_t *r,
16
+ ngx_table_elt_t *h, size_t prefix, size_t len,
17
+ ngx_http_proxy_rewrite_t *pr);
17
18
 
18
- struct ngx_http_proxy_redirect_s {
19
- ngx_http_proxy_redirect_pt handler;
20
- ngx_str_t redirect;
19
+ struct ngx_http_proxy_rewrite_s {
20
+ ngx_http_proxy_rewrite_pt handler;
21
21
 
22
22
  union {
23
- ngx_str_t text;
24
-
25
- struct {
26
- void *lengths;
27
- void *values;
28
- } vars;
23
+ ngx_http_complex_value_t complex;
24
+ #if (NGX_PCRE)
25
+ ngx_http_regex_t *regex;
26
+ #endif
27
+ } pattern;
29
28
 
30
- void *regex;
31
- } replacement;
29
+ ngx_http_complex_value_t replacement;
32
30
  };
33
31
 
34
32
 
@@ -57,6 +55,8 @@ typedef struct {
57
55
  ngx_array_t *proxy_values;
58
56
 
59
57
  ngx_array_t *redirects;
58
+ ngx_array_t *cookie_domains;
59
+ ngx_array_t *cookie_paths;
60
60
 
61
61
  ngx_str_t body_source;
62
62
 
@@ -72,6 +72,8 @@ typedef struct {
72
72
 
73
73
  ngx_flag_t redirect;
74
74
 
75
+ ngx_uint_t http_version;
76
+
75
77
  ngx_uint_t headers_hash_max_size;
76
78
  ngx_uint_t headers_hash_bucket_size;
77
79
  } ngx_http_proxy_loc_conf_t;
@@ -81,6 +83,12 @@ typedef struct {
81
83
  ngx_http_status_t status;
82
84
  ngx_http_proxy_vars_t vars;
83
85
  size_t internal_body_length;
86
+
87
+ ngx_uint_t state;
88
+ off_t size;
89
+ off_t length;
90
+
91
+ ngx_uint_t head; /* unsigned head:1 */
84
92
  } ngx_http_proxy_ctx_t;
85
93
 
86
94
 
@@ -93,6 +101,15 @@ static ngx_int_t ngx_http_proxy_create_request(ngx_http_request_t *r);
93
101
  static ngx_int_t ngx_http_proxy_reinit_request(ngx_http_request_t *r);
94
102
  static ngx_int_t ngx_http_proxy_process_status_line(ngx_http_request_t *r);
95
103
  static ngx_int_t ngx_http_proxy_process_header(ngx_http_request_t *r);
104
+ static ngx_int_t ngx_http_proxy_input_filter_init(void *data);
105
+ static ngx_int_t ngx_http_proxy_copy_filter(ngx_event_pipe_t *p,
106
+ ngx_buf_t *buf);
107
+ static ngx_int_t ngx_http_proxy_chunked_filter(ngx_event_pipe_t *p,
108
+ ngx_buf_t *buf);
109
+ static ngx_int_t ngx_http_proxy_non_buffered_copy_filter(void *data,
110
+ ssize_t bytes);
111
+ static ngx_int_t ngx_http_proxy_non_buffered_chunked_filter(void *data,
112
+ ssize_t bytes);
96
113
  static void ngx_http_proxy_abort_request(ngx_http_request_t *r);
97
114
  static void ngx_http_proxy_finalize_request(ngx_http_request_t *r,
98
115
  ngx_int_t rc);
@@ -109,6 +126,12 @@ static ngx_int_t
109
126
  ngx_http_variable_value_t *v, uintptr_t data);
110
127
  static ngx_int_t ngx_http_proxy_rewrite_redirect(ngx_http_request_t *r,
111
128
  ngx_table_elt_t *h, size_t prefix);
129
+ static ngx_int_t ngx_http_proxy_rewrite_cookie(ngx_http_request_t *r,
130
+ ngx_table_elt_t *h);
131
+ static ngx_int_t ngx_http_proxy_rewrite_cookie_value(ngx_http_request_t *r,
132
+ ngx_table_elt_t *h, u_char *value, ngx_array_t *rewrites);
133
+ static ngx_int_t ngx_http_proxy_rewrite(ngx_http_request_t *r,
134
+ ngx_table_elt_t *h, size_t prefix, size_t len, ngx_str_t *replacement);
112
135
 
113
136
  static ngx_int_t ngx_http_proxy_add_variables(ngx_conf_t *cf);
114
137
  static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf);
@@ -121,6 +144,10 @@ static char *ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd,
121
144
  void *conf);
122
145
  static char *ngx_http_proxy_redirect(ngx_conf_t *cf, ngx_command_t *cmd,
123
146
  void *conf);
147
+ static char *ngx_http_proxy_cookie_domain(ngx_conf_t *cf, ngx_command_t *cmd,
148
+ void *conf);
149
+ static char *ngx_http_proxy_cookie_path(ngx_conf_t *cf, ngx_command_t *cmd,
150
+ void *conf);
124
151
  static char *ngx_http_proxy_store(ngx_conf_t *cf, ngx_command_t *cmd,
125
152
  void *conf);
126
153
  #if (NGX_HTTP_CACHE)
@@ -132,6 +159,9 @@ static char *ngx_http_proxy_cache_key(ngx_conf_t *cf, ngx_command_t *cmd,
132
159
 
133
160
  static char *ngx_http_proxy_lowat_check(ngx_conf_t *cf, void *post, void *data);
134
161
 
162
+ static ngx_int_t ngx_http_proxy_rewrite_regex(ngx_conf_t *cf,
163
+ ngx_http_proxy_rewrite_t *pr, ngx_str_t *regex, ngx_uint_t caseless);
164
+
135
165
  #if (NGX_HTTP_SSL)
136
166
  static ngx_int_t ngx_http_proxy_set_ssl(ngx_conf_t *cf,
137
167
  ngx_http_proxy_loc_conf_t *plcf);
@@ -158,6 +188,13 @@ static ngx_conf_bitmask_t ngx_http_proxy_next_upstream_masks[] = {
158
188
  };
159
189
 
160
190
 
191
+ static ngx_conf_enum_t ngx_http_proxy_http_version[] = {
192
+ { ngx_string("1.0"), NGX_HTTP_VERSION_10 },
193
+ { ngx_string("1.1"), NGX_HTTP_VERSION_11 },
194
+ { ngx_null_string, 0 }
195
+ };
196
+
197
+
161
198
  ngx_module_t ngx_http_proxy_module;
162
199
 
163
200
 
@@ -177,6 +214,20 @@ static ngx_command_t ngx_http_proxy_commands[] = {
177
214
  0,
178
215
  NULL },
179
216
 
217
+ { ngx_string("proxy_cookie_domain"),
218
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
219
+ ngx_http_proxy_cookie_domain,
220
+ NGX_HTTP_LOC_CONF_OFFSET,
221
+ 0,
222
+ NULL },
223
+
224
+ { ngx_string("proxy_cookie_path"),
225
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
226
+ ngx_http_proxy_cookie_path,
227
+ NGX_HTTP_LOC_CONF_OFFSET,
228
+ 0,
229
+ NULL },
230
+
180
231
  { ngx_string("proxy_store"),
181
232
  NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
182
233
  ngx_http_proxy_store,
@@ -382,6 +433,20 @@ static ngx_command_t ngx_http_proxy_commands[] = {
382
433
  offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_methods),
383
434
  &ngx_http_upstream_cache_method_mask },
384
435
 
436
+ { ngx_string("proxy_cache_lock"),
437
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
438
+ ngx_conf_set_flag_slot,
439
+ NGX_HTTP_LOC_CONF_OFFSET,
440
+ offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_lock),
441
+ NULL },
442
+
443
+ { ngx_string("proxy_cache_lock_timeout"),
444
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
445
+ ngx_conf_set_msec_slot,
446
+ NGX_HTTP_LOC_CONF_OFFSET,
447
+ offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_lock_timeout),
448
+ NULL },
449
+
385
450
  #endif
386
451
 
387
452
  { ngx_string("proxy_temp_path"),
@@ -433,6 +498,13 @@ static ngx_command_t ngx_http_proxy_commands[] = {
433
498
  offsetof(ngx_http_proxy_loc_conf_t, upstream.ignore_headers),
434
499
  &ngx_http_upstream_ignore_headers_masks },
435
500
 
501
+ { ngx_string("proxy_http_version"),
502
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
503
+ ngx_conf_set_enum_slot,
504
+ NGX_HTTP_LOC_CONF_OFFSET,
505
+ offsetof(ngx_http_proxy_loc_conf_t, http_version),
506
+ &ngx_http_proxy_http_version },
507
+
436
508
  #if (NGX_HTTP_SSL)
437
509
 
438
510
  { ngx_string("proxy_ssl_session_reuse"),
@@ -480,6 +552,7 @@ ngx_module_t ngx_http_proxy_module = {
480
552
 
481
553
 
482
554
  static char ngx_http_proxy_version[] = " HTTP/1.0" CRLF;
555
+ static char ngx_http_proxy_version_11[] = " HTTP/1.1" CRLF;
483
556
 
484
557
 
485
558
  static ngx_keyval_t ngx_http_proxy_headers[] = {
@@ -487,6 +560,7 @@ static ngx_keyval_t ngx_http_proxy_headers[] = {
487
560
  { ngx_string("Connection"), ngx_string("close") },
488
561
  { ngx_string("Keep-Alive"), ngx_string("") },
489
562
  { ngx_string("Expect"), ngx_string("") },
563
+ { ngx_string("Upgrade"), ngx_string("") },
490
564
  { ngx_null_string, ngx_null_string }
491
565
  };
492
566
 
@@ -511,6 +585,7 @@ static ngx_keyval_t ngx_http_proxy_cache_headers[] = {
511
585
  { ngx_string("Connection"), ngx_string("close") },
512
586
  { ngx_string("Keep-Alive"), ngx_string("") },
513
587
  { ngx_string("Expect"), ngx_string("") },
588
+ { ngx_string("Upgrade"), ngx_string("") },
514
589
  { ngx_string("If-Modified-Since"), ngx_string("") },
515
590
  { ngx_string("If-Unmodified-Since"), ngx_string("") },
516
591
  { ngx_string("If-None-Match"), ngx_string("") },
@@ -604,6 +679,10 @@ ngx_http_proxy_handler(ngx_http_request_t *r)
604
679
  u->rewrite_redirect = ngx_http_proxy_rewrite_redirect;
605
680
  }
606
681
 
682
+ if (plcf->cookie_domains || plcf->cookie_paths) {
683
+ u->rewrite_cookie = ngx_http_proxy_rewrite_cookie;
684
+ }
685
+
607
686
  u->buffering = plcf->upstream.buffering;
608
687
 
609
688
  u->pipe = ngx_pcalloc(r->pool, sizeof(ngx_event_pipe_t));
@@ -611,7 +690,12 @@ ngx_http_proxy_handler(ngx_http_request_t *r)
611
690
  return NGX_HTTP_INTERNAL_SERVER_ERROR;
612
691
  }
613
692
 
614
- u->pipe->input_filter = ngx_event_pipe_copy_input_filter;
693
+ u->pipe->input_filter = ngx_http_proxy_copy_filter;
694
+ u->pipe->input_ctx = r;
695
+
696
+ u->input_filter_init = ngx_http_proxy_input_filter_init;
697
+ u->input_filter = ngx_http_proxy_non_buffered_copy_filter;
698
+ u->input_filter_ctx = r;
615
699
 
616
700
  u->accel = 1;
617
701
 
@@ -701,9 +785,6 @@ ngx_http_proxy_eval(ngx_http_request_t *r, ngx_http_proxy_ctx_t *ctx,
701
785
  url.uri.len++;
702
786
  url.uri.data = p - 1;
703
787
  }
704
-
705
- } else {
706
- url.uri = r->unparsed_uri;
707
788
  }
708
789
 
709
790
  ctx->vars.key_start = u->schema;
@@ -771,7 +852,7 @@ ngx_http_proxy_create_key(ngx_http_request_t *r)
771
852
  return NGX_ERROR;
772
853
  }
773
854
 
774
- if (plcf->proxy_lengths) {
855
+ if (plcf->proxy_lengths && ctx->vars.uri.len) {
775
856
 
776
857
  *key = ctx->vars.uri;
777
858
  u->uri = ctx->vars.uri;
@@ -867,15 +948,21 @@ ngx_http_proxy_create_request(ngx_http_request_t *r)
867
948
  method.len++;
868
949
  }
869
950
 
951
+ ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
952
+
953
+ if (method.len == 5
954
+ && ngx_strncasecmp(method.data, (u_char *) "HEAD ", 5) == 0)
955
+ {
956
+ ctx->head = 1;
957
+ }
958
+
870
959
  len = method.len + sizeof(ngx_http_proxy_version) - 1 + sizeof(CRLF) - 1;
871
960
 
872
961
  escape = 0;
873
962
  loc_len = 0;
874
963
  unparsed_uri = 0;
875
964
 
876
- ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
877
-
878
- if (plcf->proxy_lengths) {
965
+ if (plcf->proxy_lengths && ctx->vars.uri.len) {
879
966
  uri_len = ctx->vars.uri.len;
880
967
 
881
968
  } else if (ctx->vars.uri.len == 0 && r->valid_unparsed_uri && r == r->main)
@@ -981,7 +1068,7 @@ ngx_http_proxy_create_request(ngx_http_request_t *r)
981
1068
 
982
1069
  u->uri.data = b->last;
983
1070
 
984
- if (plcf->proxy_lengths) {
1071
+ if (plcf->proxy_lengths && ctx->vars.uri.len) {
985
1072
  b->last = ngx_copy(b->last, ctx->vars.uri.data, ctx->vars.uri.len);
986
1073
 
987
1074
  } else if (unparsed_uri) {
@@ -1010,8 +1097,14 @@ ngx_http_proxy_create_request(ngx_http_request_t *r)
1010
1097
 
1011
1098
  u->uri.len = b->last - u->uri.data;
1012
1099
 
1013
- b->last = ngx_cpymem(b->last, ngx_http_proxy_version,
1014
- sizeof(ngx_http_proxy_version) - 1);
1100
+ if (plcf->http_version == NGX_HTTP_VERSION_11) {
1101
+ b->last = ngx_cpymem(b->last, ngx_http_proxy_version_11,
1102
+ sizeof(ngx_http_proxy_version_11) - 1);
1103
+
1104
+ } else {
1105
+ b->last = ngx_cpymem(b->last, ngx_http_proxy_version,
1106
+ sizeof(ngx_http_proxy_version) - 1);
1107
+ }
1015
1108
 
1016
1109
  ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
1017
1110
 
@@ -1159,8 +1252,11 @@ ngx_http_proxy_reinit_request(ngx_http_request_t *r)
1159
1252
  ctx->status.count = 0;
1160
1253
  ctx->status.start = NULL;
1161
1254
  ctx->status.end = NULL;
1255
+ ctx->state = 0;
1162
1256
 
1163
1257
  r->upstream->process_header = ngx_http_proxy_process_status_line;
1258
+ r->upstream->pipe->input_filter = ngx_http_proxy_copy_filter;
1259
+ r->upstream->input_filter = ngx_http_proxy_non_buffered_copy_filter;
1164
1260
  r->state = 0;
1165
1261
 
1166
1262
  return NGX_OK;
@@ -1211,6 +1307,7 @@ ngx_http_proxy_process_status_line(ngx_http_request_t *r)
1211
1307
 
1212
1308
  r->http_version = NGX_HTTP_VERSION_9;
1213
1309
  u->state->status = NGX_HTTP_OK;
1310
+ u->headers_in.connection_close = 1;
1214
1311
 
1215
1312
  return NGX_OK;
1216
1313
  }
@@ -1235,6 +1332,10 @@ ngx_http_proxy_process_status_line(ngx_http_request_t *r)
1235
1332
  "http proxy status %ui \"%V\"",
1236
1333
  u->headers_in.status_n, &u->headers_in.status_line);
1237
1334
 
1335
+ if (ctx->status.http_version < NGX_HTTP_VERSION_11) {
1336
+ u->headers_in.connection_close = 1;
1337
+ }
1338
+
1238
1339
  u->process_header = ngx_http_proxy_process_header;
1239
1340
 
1240
1341
  return ngx_http_proxy_process_header(r);
@@ -1246,6 +1347,8 @@ ngx_http_proxy_process_header(ngx_http_request_t *r)
1246
1347
  {
1247
1348
  ngx_int_t rc;
1248
1349
  ngx_table_elt_t *h;
1350
+ ngx_http_upstream_t *u;
1351
+ ngx_http_proxy_ctx_t *ctx;
1249
1352
  ngx_http_upstream_header_t *hh;
1250
1353
  ngx_http_upstream_main_conf_t *umcf;
1251
1354
 
@@ -1343,6 +1446,30 @@ ngx_http_proxy_process_header(ngx_http_request_t *r)
1343
1446
  h->lowcase_key = (u_char *) "date";
1344
1447
  }
1345
1448
 
1449
+ /* clear content length if response is chunked */
1450
+
1451
+ u = r->upstream;
1452
+
1453
+ if (u->headers_in.chunked) {
1454
+ u->headers_in.content_length_n = -1;
1455
+ }
1456
+
1457
+ /*
1458
+ * set u->keepalive if response has no body; this allows to keep
1459
+ * connections alive in case of r->header_only or X-Accel-Redirect
1460
+ */
1461
+
1462
+ ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
1463
+
1464
+ if (u->headers_in.status_n == NGX_HTTP_NO_CONTENT
1465
+ || u->headers_in.status_n == NGX_HTTP_NOT_MODIFIED
1466
+ || ctx->head
1467
+ || (!u->headers_in.chunked
1468
+ && u->headers_in.content_length_n == 0))
1469
+ {
1470
+ u->keepalive = !u->headers_in.connection_close;
1471
+ }
1472
+
1346
1473
  return NGX_OK;
1347
1474
  }
1348
1475
 
@@ -1360,256 +1487,1080 @@ ngx_http_proxy_process_header(ngx_http_request_t *r)
1360
1487
  }
1361
1488
 
1362
1489
 
1363
- static void
1364
- ngx_http_proxy_abort_request(ngx_http_request_t *r)
1365
- {
1366
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1367
- "abort http proxy request");
1368
-
1369
- return;
1370
- }
1371
-
1372
-
1373
- static void
1374
- ngx_http_proxy_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
1375
- {
1376
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1377
- "finalize http proxy request");
1378
-
1379
- return;
1380
- }
1381
-
1382
-
1383
1490
  static ngx_int_t
1384
- ngx_http_proxy_host_variable(ngx_http_request_t *r,
1385
- ngx_http_variable_value_t *v, uintptr_t data)
1491
+ ngx_http_proxy_input_filter_init(void *data)
1386
1492
  {
1493
+ ngx_http_request_t *r = data;
1494
+ ngx_http_upstream_t *u;
1387
1495
  ngx_http_proxy_ctx_t *ctx;
1388
1496
 
1497
+ u = r->upstream;
1389
1498
  ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
1390
1499
 
1391
1500
  if (ctx == NULL) {
1392
- v->not_found = 1;
1393
- return NGX_OK;
1501
+ return NGX_ERROR;
1394
1502
  }
1395
1503
 
1396
- v->len = ctx->vars.host_header.len;
1397
- v->valid = 1;
1398
- v->no_cacheable = 0;
1399
- v->not_found = 0;
1400
- v->data = ctx->vars.host_header.data;
1504
+ ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1505
+ "http proxy filter init s:%d h:%d c:%d l:%O",
1506
+ u->headers_in.status_n, ctx->head, u->headers_in.chunked,
1507
+ u->headers_in.content_length_n);
1401
1508
 
1402
- return NGX_OK;
1403
- }
1509
+ /* as per RFC2616, 4.4 Message Length */
1404
1510
 
1511
+ if (u->headers_in.status_n == NGX_HTTP_NO_CONTENT
1512
+ || u->headers_in.status_n == NGX_HTTP_NOT_MODIFIED
1513
+ || ctx->head)
1514
+ {
1515
+ /* 1xx, 204, and 304 and replies to HEAD requests */
1516
+ /* no 1xx since we don't send Expect and Upgrade */
1405
1517
 
1406
- static ngx_int_t
1407
- ngx_http_proxy_port_variable(ngx_http_request_t *r,
1408
- ngx_http_variable_value_t *v, uintptr_t data)
1409
- {
1410
- ngx_http_proxy_ctx_t *ctx;
1518
+ u->pipe->length = 0;
1519
+ u->length = 0;
1520
+ u->keepalive = !u->headers_in.connection_close;
1411
1521
 
1412
- ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
1522
+ } else if (u->headers_in.chunked) {
1523
+ /* chunked */
1413
1524
 
1414
- if (ctx == NULL) {
1415
- v->not_found = 1;
1416
- return NGX_OK;
1417
- }
1525
+ u->pipe->input_filter = ngx_http_proxy_chunked_filter;
1526
+ u->pipe->length = 3; /* "0" LF LF */
1418
1527
 
1419
- v->len = ctx->vars.port.len;
1420
- v->valid = 1;
1421
- v->no_cacheable = 0;
1422
- v->not_found = 0;
1423
- v->data = ctx->vars.port.data;
1528
+ u->input_filter = ngx_http_proxy_non_buffered_chunked_filter;
1529
+ u->length = -1;
1530
+
1531
+ } else if (u->headers_in.content_length_n == 0) {
1532
+ /* empty body: special case as filter won't be called */
1533
+
1534
+ u->pipe->length = 0;
1535
+ u->length = 0;
1536
+ u->keepalive = !u->headers_in.connection_close;
1537
+
1538
+ } else {
1539
+ /* content length or connection close */
1540
+
1541
+ u->pipe->length = u->headers_in.content_length_n;
1542
+ u->length = u->headers_in.content_length_n;
1543
+ }
1424
1544
 
1425
1545
  return NGX_OK;
1426
1546
  }
1427
1547
 
1428
1548
 
1429
1549
  static ngx_int_t
1430
- ngx_http_proxy_add_x_forwarded_for_variable(ngx_http_request_t *r,
1431
- ngx_http_variable_value_t *v, uintptr_t data)
1550
+ ngx_http_proxy_copy_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
1432
1551
  {
1433
- u_char *p;
1434
-
1435
- v->valid = 1;
1436
- v->no_cacheable = 0;
1437
- v->not_found = 0;
1552
+ ngx_buf_t *b;
1553
+ ngx_chain_t *cl;
1554
+ ngx_http_request_t *r;
1438
1555
 
1439
- if (r->headers_in.x_forwarded_for == NULL) {
1440
- v->len = r->connection->addr_text.len;
1441
- v->data = r->connection->addr_text.data;
1556
+ if (buf->pos == buf->last) {
1442
1557
  return NGX_OK;
1443
1558
  }
1444
1559
 
1445
- v->len = r->headers_in.x_forwarded_for->value.len
1446
- + sizeof(", ") - 1 + r->connection->addr_text.len;
1560
+ if (p->free) {
1561
+ cl = p->free;
1562
+ b = cl->buf;
1563
+ p->free = cl->next;
1564
+ ngx_free_chain(p->pool, cl);
1447
1565
 
1448
- p = ngx_pnalloc(r->pool, v->len);
1449
- if (p == NULL) {
1566
+ } else {
1567
+ b = ngx_alloc_buf(p->pool);
1568
+ if (b == NULL) {
1569
+ return NGX_ERROR;
1570
+ }
1571
+ }
1572
+
1573
+ ngx_memcpy(b, buf, sizeof(ngx_buf_t));
1574
+ b->shadow = buf;
1575
+ b->tag = p->tag;
1576
+ b->last_shadow = 1;
1577
+ b->recycled = 1;
1578
+ buf->shadow = b;
1579
+
1580
+ cl = ngx_alloc_chain_link(p->pool);
1581
+ if (cl == NULL) {
1450
1582
  return NGX_ERROR;
1451
1583
  }
1452
1584
 
1453
- v->data = p;
1585
+ cl->buf = b;
1586
+ cl->next = NULL;
1454
1587
 
1455
- p = ngx_copy(p, r->headers_in.x_forwarded_for->value.data,
1456
- r->headers_in.x_forwarded_for->value.len);
1588
+ ngx_log_debug1(NGX_LOG_DEBUG_EVENT, p->log, 0, "input buf #%d", b->num);
1457
1589
 
1458
- *p++ = ','; *p++ = ' ';
1590
+ if (p->in) {
1591
+ *p->last_in = cl;
1592
+ } else {
1593
+ p->in = cl;
1594
+ }
1595
+ p->last_in = &cl->next;
1459
1596
 
1460
- ngx_memcpy(p, r->connection->addr_text.data, r->connection->addr_text.len);
1597
+ if (p->length == -1) {
1598
+ return NGX_OK;
1599
+ }
1600
+
1601
+ p->length -= b->last - b->pos;
1602
+
1603
+ if (p->length == 0) {
1604
+ r = p->input_ctx;
1605
+ p->upstream_done = 1;
1606
+ r->upstream->keepalive = !r->upstream->headers_in.connection_close;
1607
+
1608
+ } else if (p->length < 0) {
1609
+ r = p->input_ctx;
1610
+ p->upstream_done = 1;
1611
+
1612
+ ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
1613
+ "upstream sent too much data");
1614
+ }
1461
1615
 
1462
1616
  return NGX_OK;
1463
1617
  }
1464
1618
 
1465
1619
 
1466
- static ngx_int_t
1467
- ngx_http_proxy_internal_body_length_variable(ngx_http_request_t *r,
1468
- ngx_http_variable_value_t *v, uintptr_t data)
1620
+ static ngx_inline ngx_int_t
1621
+ ngx_http_proxy_parse_chunked(ngx_http_request_t *r, ngx_buf_t *buf)
1469
1622
  {
1623
+ u_char *pos, ch, c;
1624
+ ngx_int_t rc;
1470
1625
  ngx_http_proxy_ctx_t *ctx;
1626
+ enum {
1627
+ sw_chunk_start = 0,
1628
+ sw_chunk_size,
1629
+ sw_chunk_extension,
1630
+ sw_chunk_extension_almost_done,
1631
+ sw_chunk_data,
1632
+ sw_after_data,
1633
+ sw_after_data_almost_done,
1634
+ sw_last_chunk_extension,
1635
+ sw_last_chunk_extension_almost_done,
1636
+ sw_trailer,
1637
+ sw_trailer_almost_done,
1638
+ sw_trailer_header,
1639
+ sw_trailer_header_almost_done
1640
+ } state;
1471
1641
 
1472
1642
  ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
1473
1643
 
1474
1644
  if (ctx == NULL) {
1475
- v->not_found = 1;
1476
- return NGX_OK;
1645
+ return NGX_ERROR;
1477
1646
  }
1478
1647
 
1479
- v->valid = 1;
1480
- v->no_cacheable = 0;
1481
- v->not_found = 0;
1482
-
1483
- v->data = ngx_pnalloc(r->connection->pool, NGX_SIZE_T_LEN);
1648
+ state = ctx->state;
1484
1649
 
1485
- if (v->data == NULL) {
1486
- return NGX_ERROR;
1650
+ if (state == sw_chunk_data && ctx->size == 0) {
1651
+ state = sw_after_data;
1487
1652
  }
1488
1653
 
1489
- v->len = ngx_sprintf(v->data, "%uz", ctx->internal_body_length) - v->data;
1654
+ rc = NGX_AGAIN;
1490
1655
 
1491
- return NGX_OK;
1492
- }
1656
+ for (pos = buf->pos; pos < buf->last; pos++) {
1493
1657
 
1658
+ ch = *pos;
1494
1659
 
1495
- static ngx_int_t
1496
- ngx_http_proxy_rewrite_redirect(ngx_http_request_t *r, ngx_table_elt_t *h,
1497
- size_t prefix)
1498
- {
1499
- ngx_int_t rc;
1500
- ngx_uint_t i;
1501
- ngx_http_proxy_loc_conf_t *plcf;
1502
- ngx_http_proxy_redirect_t *pr;
1660
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1661
+ "http proxy chunked byte: %02Xd s:%d", ch, state);
1503
1662
 
1504
- plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
1663
+ switch (state) {
1505
1664
 
1506
- pr = plcf->redirects->elts;
1665
+ case sw_chunk_start:
1666
+ if (ch >= '0' && ch <= '9') {
1667
+ state = sw_chunk_size;
1668
+ ctx->size = ch - '0';
1669
+ break;
1670
+ }
1507
1671
 
1508
- if (pr == NULL) {
1509
- return NGX_DECLINED;
1510
- }
1672
+ c = (u_char) (ch | 0x20);
1511
1673
 
1512
- for (i = 0; i < plcf->redirects->nelts; i++) {
1513
- rc = pr[i].handler(r, h, prefix, &pr[i]);
1674
+ if (c >= 'a' && c <= 'f') {
1675
+ state = sw_chunk_size;
1676
+ ctx->size = c - 'a' + 10;
1677
+ break;
1678
+ }
1514
1679
 
1515
- if (rc != NGX_DECLINED) {
1516
- return rc;
1517
- }
1518
- }
1680
+ goto invalid;
1519
1681
 
1520
- return NGX_DECLINED;
1521
- }
1682
+ case sw_chunk_size:
1683
+ if (ch >= '0' && ch <= '9') {
1684
+ ctx->size = ctx->size * 16 + (ch - '0');
1685
+ break;
1686
+ }
1522
1687
 
1688
+ c = (u_char) (ch | 0x20);
1523
1689
 
1524
- static ngx_int_t
1525
- ngx_http_proxy_rewrite_redirect_text(ngx_http_request_t *r, ngx_table_elt_t *h,
1526
- size_t prefix, ngx_http_proxy_redirect_t *pr)
1527
- {
1528
- size_t len;
1529
- u_char *data, *p;
1690
+ if (c >= 'a' && c <= 'f') {
1691
+ ctx->size = ctx->size * 16 + (c - 'a' + 10);
1692
+ break;
1693
+ }
1530
1694
 
1531
- if (pr->redirect.len > h->value.len - prefix
1532
- || ngx_rstrncmp(h->value.data + prefix, pr->redirect.data,
1533
- pr->redirect.len) != 0)
1534
- {
1535
- return NGX_DECLINED;
1536
- }
1695
+ if (ctx->size == 0) {
1537
1696
 
1538
- len = pr->replacement.text.len + h->value.len - pr->redirect.len;
1697
+ switch (ch) {
1698
+ case CR:
1699
+ state = sw_last_chunk_extension_almost_done;
1700
+ break;
1701
+ case LF:
1702
+ state = sw_trailer;
1703
+ break;
1704
+ case ';':
1705
+ case ' ':
1706
+ case '\t':
1707
+ state = sw_last_chunk_extension;
1708
+ break;
1709
+ default:
1710
+ goto invalid;
1711
+ }
1539
1712
 
1540
- data = ngx_pnalloc(r->pool, len);
1541
- if (data == NULL) {
1542
- return NGX_ERROR;
1543
- }
1713
+ break;
1714
+ }
1715
+
1716
+ switch (ch) {
1717
+ case CR:
1718
+ state = sw_chunk_extension_almost_done;
1719
+ break;
1720
+ case LF:
1721
+ state = sw_chunk_data;
1722
+ break;
1723
+ case ';':
1724
+ case ' ':
1725
+ case '\t':
1726
+ state = sw_chunk_extension;
1727
+ break;
1728
+ default:
1729
+ goto invalid;
1730
+ }
1731
+
1732
+ break;
1733
+
1734
+ case sw_chunk_extension:
1735
+ switch (ch) {
1736
+ case CR:
1737
+ state = sw_chunk_extension_almost_done;
1738
+ break;
1739
+ case LF:
1740
+ state = sw_chunk_data;
1741
+ }
1742
+ break;
1743
+
1744
+ case sw_chunk_extension_almost_done:
1745
+ if (ch == LF) {
1746
+ state = sw_chunk_data;
1747
+ break;
1748
+ }
1749
+ goto invalid;
1750
+
1751
+ case sw_chunk_data:
1752
+ rc = NGX_OK;
1753
+ goto data;
1754
+
1755
+ case sw_after_data:
1756
+ switch (ch) {
1757
+ case CR:
1758
+ state = sw_after_data_almost_done;
1759
+ break;
1760
+ case LF:
1761
+ state = sw_chunk_start;
1762
+ }
1763
+ break;
1764
+
1765
+ case sw_after_data_almost_done:
1766
+ if (ch == LF) {
1767
+ state = sw_chunk_start;
1768
+ break;
1769
+ }
1770
+ goto invalid;
1771
+
1772
+ case sw_last_chunk_extension:
1773
+ switch (ch) {
1774
+ case CR:
1775
+ state = sw_last_chunk_extension_almost_done;
1776
+ break;
1777
+ case LF:
1778
+ state = sw_trailer;
1779
+ }
1780
+ break;
1781
+
1782
+ case sw_last_chunk_extension_almost_done:
1783
+ if (ch == LF) {
1784
+ state = sw_trailer;
1785
+ break;
1786
+ }
1787
+ goto invalid;
1788
+
1789
+ case sw_trailer:
1790
+ switch (ch) {
1791
+ case CR:
1792
+ state = sw_trailer_almost_done;
1793
+ break;
1794
+ case LF:
1795
+ goto done;
1796
+ default:
1797
+ state = sw_trailer_header;
1798
+ }
1799
+ break;
1800
+
1801
+ case sw_trailer_almost_done:
1802
+ if (ch == LF) {
1803
+ goto done;
1804
+ }
1805
+ goto invalid;
1806
+
1807
+ case sw_trailer_header:
1808
+ switch (ch) {
1809
+ case CR:
1810
+ state = sw_trailer_header_almost_done;
1811
+ break;
1812
+ case LF:
1813
+ state = sw_trailer;
1814
+ }
1815
+ break;
1544
1816
 
1545
- p = ngx_copy(data, h->value.data, prefix);
1817
+ case sw_trailer_header_almost_done:
1818
+ if (ch == LF) {
1819
+ state = sw_trailer;
1820
+ break;
1821
+ }
1822
+ goto invalid;
1546
1823
 
1547
- if (pr->replacement.text.len) {
1548
- p = ngx_copy(p, pr->replacement.text.data, pr->replacement.text.len);
1824
+ }
1549
1825
  }
1550
1826
 
1551
- ngx_memcpy(p, h->value.data + prefix + pr->redirect.len,
1552
- h->value.len - pr->redirect.len - prefix);
1827
+ data:
1828
+
1829
+ ctx->state = state;
1830
+ buf->pos = pos;
1831
+
1832
+ switch (state) {
1833
+
1834
+ case sw_chunk_start:
1835
+ ctx->length = 3 /* "0" LF LF */;
1836
+ break;
1837
+ case sw_chunk_size:
1838
+ ctx->length = 2 /* LF LF */
1839
+ + (ctx->size ? ctx->size + 4 /* LF "0" LF LF */ : 0);
1840
+ break;
1841
+ case sw_chunk_extension:
1842
+ case sw_chunk_extension_almost_done:
1843
+ ctx->length = 1 /* LF */ + ctx->size + 4 /* LF "0" LF LF */;
1844
+ break;
1845
+ case sw_chunk_data:
1846
+ ctx->length = ctx->size + 4 /* LF "0" LF LF */;
1847
+ break;
1848
+ case sw_after_data:
1849
+ case sw_after_data_almost_done:
1850
+ ctx->length = 4 /* LF "0" LF LF */;
1851
+ break;
1852
+ case sw_last_chunk_extension:
1853
+ case sw_last_chunk_extension_almost_done:
1854
+ ctx->length = 2 /* LF LF */;
1855
+ break;
1856
+ case sw_trailer:
1857
+ case sw_trailer_almost_done:
1858
+ ctx->length = 1 /* LF */;
1859
+ break;
1860
+ case sw_trailer_header:
1861
+ case sw_trailer_header_almost_done:
1862
+ ctx->length = 2 /* LF LF */;
1863
+ break;
1864
+
1865
+ }
1866
+
1867
+ return rc;
1868
+
1869
+ done:
1553
1870
 
1554
- h->value.len = len;
1555
- h->value.data = data;
1871
+ return NGX_DONE;
1556
1872
 
1557
- return NGX_OK;
1873
+ invalid:
1874
+
1875
+ return NGX_ERROR;
1558
1876
  }
1559
1877
 
1560
1878
 
1561
1879
  static ngx_int_t
1562
- ngx_http_proxy_rewrite_redirect_vars(ngx_http_request_t *r, ngx_table_elt_t *h,
1563
- size_t prefix, ngx_http_proxy_redirect_t *pr)
1880
+ ngx_http_proxy_chunked_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
1564
1881
  {
1565
- size_t len;
1566
- u_char *data, *p;
1567
- ngx_http_script_code_pt code;
1568
- ngx_http_script_engine_t e;
1569
- ngx_http_script_len_code_pt lcode;
1882
+ ngx_int_t rc;
1883
+ ngx_buf_t *b, **prev;
1884
+ ngx_chain_t *cl;
1885
+ ngx_http_request_t *r;
1886
+ ngx_http_proxy_ctx_t *ctx;
1570
1887
 
1571
- if (pr->redirect.len > h->value.len - prefix
1572
- || ngx_rstrncmp(h->value.data + prefix, pr->redirect.data,
1573
- pr->redirect.len) != 0)
1574
- {
1575
- return NGX_DECLINED;
1888
+ if (buf->pos == buf->last) {
1889
+ return NGX_OK;
1576
1890
  }
1577
1891
 
1578
- ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
1892
+ r = p->input_ctx;
1893
+ ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
1579
1894
 
1580
- e.ip = pr->replacement.vars.lengths;
1581
- e.request = r;
1895
+ if (ctx == NULL) {
1896
+ return NGX_ERROR;
1897
+ }
1582
1898
 
1583
- len = h->value.len - pr->redirect.len;
1899
+ b = NULL;
1900
+ prev = &buf->shadow;
1584
1901
 
1585
- while (*(uintptr_t *) e.ip) {
1586
- lcode = *(ngx_http_script_len_code_pt *) e.ip;
1587
- len += lcode(&e);
1588
- }
1902
+ for ( ;; ) {
1589
1903
 
1590
- data = ngx_pnalloc(r->pool, len);
1591
- if (data == NULL) {
1592
- return NGX_ERROR;
1593
- }
1904
+ rc = ngx_http_proxy_parse_chunked(r, buf);
1594
1905
 
1595
- p = ngx_copy(data, h->value.data, prefix);
1906
+ if (rc == NGX_OK) {
1596
1907
 
1597
- e.ip = pr->replacement.vars.values;
1598
- e.pos = p;
1908
+ /* a chunk has been parsed successfully */
1599
1909
 
1600
- while (*(uintptr_t *) e.ip) {
1601
- code = *(ngx_http_script_code_pt *) e.ip;
1602
- code(&e);
1603
- }
1910
+ if (p->free) {
1911
+ cl = p->free;
1912
+ b = cl->buf;
1913
+ p->free = cl->next;
1914
+ ngx_free_chain(p->pool, cl);
1604
1915
 
1605
- ngx_memcpy(e.pos, h->value.data + prefix + pr->redirect.len,
1606
- h->value.len - pr->redirect.len - prefix);
1916
+ } else {
1917
+ b = ngx_alloc_buf(p->pool);
1918
+ if (b == NULL) {
1919
+ return NGX_ERROR;
1920
+ }
1921
+ }
1607
1922
 
1608
- h->value.len = len;
1609
- h->value.data = data;
1923
+ ngx_memzero(b, sizeof(ngx_buf_t));
1610
1924
 
1611
- return NGX_OK;
1612
- }
1925
+ b->pos = buf->pos;
1926
+ b->start = buf->start;
1927
+ b->end = buf->end;
1928
+ b->tag = p->tag;
1929
+ b->temporary = 1;
1930
+ b->recycled = 1;
1931
+
1932
+ *prev = b;
1933
+ prev = &b->shadow;
1934
+
1935
+ cl = ngx_alloc_chain_link(p->pool);
1936
+ if (cl == NULL) {
1937
+ return NGX_ERROR;
1938
+ }
1939
+
1940
+ cl->buf = b;
1941
+ cl->next = NULL;
1942
+
1943
+ if (p->in) {
1944
+ *p->last_in = cl;
1945
+ } else {
1946
+ p->in = cl;
1947
+ }
1948
+ p->last_in = &cl->next;
1949
+
1950
+ /* STUB */ b->num = buf->num;
1951
+
1952
+ ngx_log_debug2(NGX_LOG_DEBUG_EVENT, p->log, 0,
1953
+ "input buf #%d %p", b->num, b->pos);
1954
+
1955
+ if (buf->last - buf->pos >= ctx->size) {
1956
+
1957
+ buf->pos += ctx->size;
1958
+ b->last = buf->pos;
1959
+ ctx->size = 0;
1960
+
1961
+ continue;
1962
+ }
1963
+
1964
+ ctx->size -= buf->last - buf->pos;
1965
+ buf->pos = buf->last;
1966
+ b->last = buf->last;
1967
+
1968
+ continue;
1969
+ }
1970
+
1971
+ if (rc == NGX_DONE) {
1972
+
1973
+ /* a whole response has been parsed successfully */
1974
+
1975
+ p->upstream_done = 1;
1976
+ r->upstream->keepalive = !r->upstream->headers_in.connection_close;
1977
+
1978
+ break;
1979
+ }
1980
+
1981
+ if (rc == NGX_AGAIN) {
1982
+
1983
+ /* set p->length, minimal amount of data we want to see */
1984
+
1985
+ p->length = ctx->length;
1986
+
1987
+ break;
1988
+ }
1989
+
1990
+ /* invalid response */
1991
+
1992
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
1993
+ "upstream sent invalid chunked response");
1994
+
1995
+ return NGX_ERROR;
1996
+ }
1997
+
1998
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1999
+ "http proxy chunked state %d, length %d",
2000
+ ctx->state, p->length);
2001
+
2002
+ if (b) {
2003
+ b->shadow = buf;
2004
+ b->last_shadow = 1;
2005
+
2006
+ ngx_log_debug2(NGX_LOG_DEBUG_EVENT, p->log, 0,
2007
+ "input buf %p %z", b->pos, b->last - b->pos);
2008
+
2009
+ return NGX_OK;
2010
+ }
2011
+
2012
+ /* there is no data record in the buf, add it to free chain */
2013
+
2014
+ if (ngx_event_pipe_add_free_buf(p, buf) != NGX_OK) {
2015
+ return NGX_ERROR;
2016
+ }
2017
+
2018
+ return NGX_OK;
2019
+ }
2020
+
2021
+
2022
+ static ngx_int_t
2023
+ ngx_http_proxy_non_buffered_copy_filter(void *data, ssize_t bytes)
2024
+ {
2025
+ ngx_http_request_t *r = data;
2026
+
2027
+ ngx_buf_t *b;
2028
+ ngx_chain_t *cl, **ll;
2029
+ ngx_http_upstream_t *u;
2030
+
2031
+ u = r->upstream;
2032
+
2033
+ for (cl = u->out_bufs, ll = &u->out_bufs; cl; cl = cl->next) {
2034
+ ll = &cl->next;
2035
+ }
2036
+
2037
+ cl = ngx_chain_get_free_buf(r->pool, &u->free_bufs);
2038
+ if (cl == NULL) {
2039
+ return NGX_ERROR;
2040
+ }
2041
+
2042
+ *ll = cl;
2043
+
2044
+ cl->buf->flush = 1;
2045
+ cl->buf->memory = 1;
2046
+
2047
+ b = &u->buffer;
2048
+
2049
+ cl->buf->pos = b->last;
2050
+ b->last += bytes;
2051
+ cl->buf->last = b->last;
2052
+ cl->buf->tag = u->output.tag;
2053
+
2054
+ if (u->length == -1) {
2055
+ return NGX_OK;
2056
+ }
2057
+
2058
+ u->length -= bytes;
2059
+
2060
+ if (u->length == 0) {
2061
+ u->keepalive = !u->headers_in.connection_close;
2062
+ }
2063
+
2064
+ return NGX_OK;
2065
+ }
2066
+
2067
+
2068
+ static ngx_int_t
2069
+ ngx_http_proxy_non_buffered_chunked_filter(void *data, ssize_t bytes)
2070
+ {
2071
+ ngx_http_request_t *r = data;
2072
+
2073
+ ngx_int_t rc;
2074
+ ngx_buf_t *b, *buf;
2075
+ ngx_chain_t *cl, **ll;
2076
+ ngx_http_upstream_t *u;
2077
+ ngx_http_proxy_ctx_t *ctx;
2078
+
2079
+ ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
2080
+
2081
+ if (ctx == NULL) {
2082
+ return NGX_ERROR;
2083
+ }
2084
+
2085
+ u = r->upstream;
2086
+ buf = &u->buffer;
2087
+
2088
+ buf->pos = buf->last;
2089
+ buf->last += bytes;
2090
+
2091
+ for (cl = u->out_bufs, ll = &u->out_bufs; cl; cl = cl->next) {
2092
+ ll = &cl->next;
2093
+ }
2094
+
2095
+ for ( ;; ) {
2096
+
2097
+ rc = ngx_http_proxy_parse_chunked(r, buf);
2098
+
2099
+ if (rc == NGX_OK) {
2100
+
2101
+ /* a chunk has been parsed successfully */
2102
+
2103
+ cl = ngx_chain_get_free_buf(r->pool, &u->free_bufs);
2104
+ if (cl == NULL) {
2105
+ return NGX_ERROR;
2106
+ }
2107
+
2108
+ *ll = cl;
2109
+ ll = &cl->next;
2110
+
2111
+ b = cl->buf;
2112
+
2113
+ b->flush = 1;
2114
+ b->memory = 1;
2115
+
2116
+ b->pos = buf->pos;
2117
+ b->tag = u->output.tag;
2118
+
2119
+ if (buf->last - buf->pos >= ctx->size) {
2120
+ buf->pos += ctx->size;
2121
+ b->last = buf->pos;
2122
+ ctx->size = 0;
2123
+
2124
+ } else {
2125
+ ctx->size -= buf->last - buf->pos;
2126
+ buf->pos = buf->last;
2127
+ b->last = buf->last;
2128
+ }
2129
+
2130
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2131
+ "http proxy out buf %p %z",
2132
+ b->pos, b->last - b->pos);
2133
+
2134
+ continue;
2135
+ }
2136
+
2137
+ if (rc == NGX_DONE) {
2138
+
2139
+ /* a whole response has been parsed successfully */
2140
+
2141
+ u->keepalive = !u->headers_in.connection_close;
2142
+ u->length = 0;
2143
+
2144
+ break;
2145
+ }
2146
+
2147
+ if (rc == NGX_AGAIN) {
2148
+ break;
2149
+ }
2150
+
2151
+ /* invalid response */
2152
+
2153
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
2154
+ "upstream sent invalid chunked response");
2155
+
2156
+ return NGX_ERROR;
2157
+ }
2158
+
2159
+ /* provide continuous buffer for subrequests in memory */
2160
+
2161
+ if (r->subrequest_in_memory) {
2162
+
2163
+ cl = u->out_bufs;
2164
+
2165
+ if (cl) {
2166
+ buf->pos = cl->buf->pos;
2167
+ }
2168
+
2169
+ buf->last = buf->pos;
2170
+
2171
+ for (cl = u->out_bufs; cl; cl = cl->next) {
2172
+ ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2173
+ "http proxy in memory %p-%p %uz",
2174
+ cl->buf->pos, cl->buf->last, ngx_buf_size(cl->buf));
2175
+
2176
+ if (buf->last == cl->buf->pos) {
2177
+ buf->last = cl->buf->last;
2178
+ continue;
2179
+ }
2180
+
2181
+ buf->last = ngx_movemem(buf->last, cl->buf->pos,
2182
+ cl->buf->last - cl->buf->pos);
2183
+
2184
+ cl->buf->pos = buf->last - (cl->buf->last - cl->buf->pos);
2185
+ cl->buf->last = buf->last;
2186
+ }
2187
+ }
2188
+
2189
+ return NGX_OK;
2190
+ }
2191
+
2192
+
2193
+ static void
2194
+ ngx_http_proxy_abort_request(ngx_http_request_t *r)
2195
+ {
2196
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2197
+ "abort http proxy request");
2198
+
2199
+ return;
2200
+ }
2201
+
2202
+
2203
+ static void
2204
+ ngx_http_proxy_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
2205
+ {
2206
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2207
+ "finalize http proxy request");
2208
+
2209
+ return;
2210
+ }
2211
+
2212
+
2213
+ static ngx_int_t
2214
+ ngx_http_proxy_host_variable(ngx_http_request_t *r,
2215
+ ngx_http_variable_value_t *v, uintptr_t data)
2216
+ {
2217
+ ngx_http_proxy_ctx_t *ctx;
2218
+
2219
+ ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
2220
+
2221
+ if (ctx == NULL) {
2222
+ v->not_found = 1;
2223
+ return NGX_OK;
2224
+ }
2225
+
2226
+ v->len = ctx->vars.host_header.len;
2227
+ v->valid = 1;
2228
+ v->no_cacheable = 0;
2229
+ v->not_found = 0;
2230
+ v->data = ctx->vars.host_header.data;
2231
+
2232
+ return NGX_OK;
2233
+ }
2234
+
2235
+
2236
+ static ngx_int_t
2237
+ ngx_http_proxy_port_variable(ngx_http_request_t *r,
2238
+ ngx_http_variable_value_t *v, uintptr_t data)
2239
+ {
2240
+ ngx_http_proxy_ctx_t *ctx;
2241
+
2242
+ ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
2243
+
2244
+ if (ctx == NULL) {
2245
+ v->not_found = 1;
2246
+ return NGX_OK;
2247
+ }
2248
+
2249
+ v->len = ctx->vars.port.len;
2250
+ v->valid = 1;
2251
+ v->no_cacheable = 0;
2252
+ v->not_found = 0;
2253
+ v->data = ctx->vars.port.data;
2254
+
2255
+ return NGX_OK;
2256
+ }
2257
+
2258
+
2259
+ static ngx_int_t
2260
+ ngx_http_proxy_add_x_forwarded_for_variable(ngx_http_request_t *r,
2261
+ ngx_http_variable_value_t *v, uintptr_t data)
2262
+ {
2263
+ u_char *p;
2264
+
2265
+ v->valid = 1;
2266
+ v->no_cacheable = 0;
2267
+ v->not_found = 0;
2268
+
2269
+ if (r->headers_in.x_forwarded_for == NULL) {
2270
+ v->len = r->connection->addr_text.len;
2271
+ v->data = r->connection->addr_text.data;
2272
+ return NGX_OK;
2273
+ }
2274
+
2275
+ v->len = r->headers_in.x_forwarded_for->value.len
2276
+ + sizeof(", ") - 1 + r->connection->addr_text.len;
2277
+
2278
+ p = ngx_pnalloc(r->pool, v->len);
2279
+ if (p == NULL) {
2280
+ return NGX_ERROR;
2281
+ }
2282
+
2283
+ v->data = p;
2284
+
2285
+ p = ngx_copy(p, r->headers_in.x_forwarded_for->value.data,
2286
+ r->headers_in.x_forwarded_for->value.len);
2287
+
2288
+ *p++ = ','; *p++ = ' ';
2289
+
2290
+ ngx_memcpy(p, r->connection->addr_text.data, r->connection->addr_text.len);
2291
+
2292
+ return NGX_OK;
2293
+ }
2294
+
2295
+
2296
+ static ngx_int_t
2297
+ ngx_http_proxy_internal_body_length_variable(ngx_http_request_t *r,
2298
+ ngx_http_variable_value_t *v, uintptr_t data)
2299
+ {
2300
+ ngx_http_proxy_ctx_t *ctx;
2301
+
2302
+ ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
2303
+
2304
+ if (ctx == NULL) {
2305
+ v->not_found = 1;
2306
+ return NGX_OK;
2307
+ }
2308
+
2309
+ v->valid = 1;
2310
+ v->no_cacheable = 0;
2311
+ v->not_found = 0;
2312
+
2313
+ v->data = ngx_pnalloc(r->connection->pool, NGX_SIZE_T_LEN);
2314
+
2315
+ if (v->data == NULL) {
2316
+ return NGX_ERROR;
2317
+ }
2318
+
2319
+ v->len = ngx_sprintf(v->data, "%uz", ctx->internal_body_length) - v->data;
2320
+
2321
+ return NGX_OK;
2322
+ }
2323
+
2324
+
2325
+ static ngx_int_t
2326
+ ngx_http_proxy_rewrite_redirect(ngx_http_request_t *r, ngx_table_elt_t *h,
2327
+ size_t prefix)
2328
+ {
2329
+ size_t len;
2330
+ ngx_int_t rc;
2331
+ ngx_uint_t i;
2332
+ ngx_http_proxy_rewrite_t *pr;
2333
+ ngx_http_proxy_loc_conf_t *plcf;
2334
+
2335
+ plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
2336
+
2337
+ pr = plcf->redirects->elts;
2338
+
2339
+ if (pr == NULL) {
2340
+ return NGX_DECLINED;
2341
+ }
2342
+
2343
+ len = h->value.len - prefix;
2344
+
2345
+ for (i = 0; i < plcf->redirects->nelts; i++) {
2346
+ rc = pr[i].handler(r, h, prefix, len, &pr[i]);
2347
+
2348
+ if (rc != NGX_DECLINED) {
2349
+ return rc;
2350
+ }
2351
+ }
2352
+
2353
+ return NGX_DECLINED;
2354
+ }
2355
+
2356
+
2357
+ static ngx_int_t
2358
+ ngx_http_proxy_rewrite_cookie(ngx_http_request_t *r, ngx_table_elt_t *h)
2359
+ {
2360
+ size_t prefix;
2361
+ u_char *p;
2362
+ ngx_int_t rc, rv;
2363
+ ngx_http_proxy_loc_conf_t *plcf;
2364
+
2365
+ p = (u_char *) ngx_strchr(h->value.data, ';');
2366
+ if (p == NULL) {
2367
+ return NGX_DECLINED;
2368
+ }
2369
+
2370
+ prefix = p + 1 - h->value.data;
2371
+
2372
+ rv = NGX_DECLINED;
2373
+
2374
+ plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
2375
+
2376
+ if (plcf->cookie_domains) {
2377
+ p = ngx_strcasestrn(h->value.data + prefix, "domain=", 7 - 1);
2378
+
2379
+ if (p) {
2380
+ rc = ngx_http_proxy_rewrite_cookie_value(r, h, p + 7,
2381
+ plcf->cookie_domains);
2382
+ if (rc == NGX_ERROR) {
2383
+ return NGX_ERROR;
2384
+ }
2385
+
2386
+ if (rc != NGX_DECLINED) {
2387
+ rv = rc;
2388
+ }
2389
+ }
2390
+ }
2391
+
2392
+ if (plcf->cookie_paths) {
2393
+ p = ngx_strcasestrn(h->value.data + prefix, "path=", 5 - 1);
2394
+
2395
+ if (p) {
2396
+ rc = ngx_http_proxy_rewrite_cookie_value(r, h, p + 5,
2397
+ plcf->cookie_paths);
2398
+ if (rc == NGX_ERROR) {
2399
+ return NGX_ERROR;
2400
+ }
2401
+
2402
+ if (rc != NGX_DECLINED) {
2403
+ rv = rc;
2404
+ }
2405
+ }
2406
+ }
2407
+
2408
+ return rv;
2409
+ }
2410
+
2411
+
2412
+ static ngx_int_t
2413
+ ngx_http_proxy_rewrite_cookie_value(ngx_http_request_t *r, ngx_table_elt_t *h,
2414
+ u_char *value, ngx_array_t *rewrites)
2415
+ {
2416
+ size_t len, prefix;
2417
+ u_char *p;
2418
+ ngx_int_t rc;
2419
+ ngx_uint_t i;
2420
+ ngx_http_proxy_rewrite_t *pr;
2421
+
2422
+ prefix = value - h->value.data;
2423
+
2424
+ p = (u_char *) ngx_strchr(value, ';');
2425
+
2426
+ len = p ? (size_t) (p - value) : (h->value.len - prefix);
2427
+
2428
+ pr = rewrites->elts;
2429
+
2430
+ for (i = 0; i < rewrites->nelts; i++) {
2431
+ rc = pr[i].handler(r, h, prefix, len, &pr[i]);
2432
+
2433
+ if (rc != NGX_DECLINED) {
2434
+ return rc;
2435
+ }
2436
+ }
2437
+
2438
+ return NGX_DECLINED;
2439
+ }
2440
+
2441
+
2442
+ static ngx_int_t
2443
+ ngx_http_proxy_rewrite_complex_handler(ngx_http_request_t *r,
2444
+ ngx_table_elt_t *h, size_t prefix, size_t len, ngx_http_proxy_rewrite_t *pr)
2445
+ {
2446
+ ngx_str_t pattern, replacement;
2447
+
2448
+ if (ngx_http_complex_value(r, &pr->pattern.complex, &pattern) != NGX_OK) {
2449
+ return NGX_ERROR;
2450
+ }
2451
+
2452
+ if (pattern.len > len
2453
+ || ngx_rstrncmp(h->value.data + prefix, pattern.data,
2454
+ pattern.len) != 0)
2455
+ {
2456
+ return NGX_DECLINED;
2457
+ }
2458
+
2459
+ if (ngx_http_complex_value(r, &pr->replacement, &replacement) != NGX_OK) {
2460
+ return NGX_ERROR;
2461
+ }
2462
+
2463
+ return ngx_http_proxy_rewrite(r, h, prefix, pattern.len, &replacement);
2464
+ }
2465
+
2466
+
2467
+ #if (NGX_PCRE)
2468
+
2469
+ static ngx_int_t
2470
+ ngx_http_proxy_rewrite_regex_handler(ngx_http_request_t *r, ngx_table_elt_t *h,
2471
+ size_t prefix, size_t len, ngx_http_proxy_rewrite_t *pr)
2472
+ {
2473
+ ngx_str_t pattern, replacement;
2474
+
2475
+ pattern.len = len;
2476
+ pattern.data = h->value.data + prefix;
2477
+
2478
+ if (ngx_http_regex_exec(r, pr->pattern.regex, &pattern) != NGX_OK) {
2479
+ return NGX_DECLINED;
2480
+ }
2481
+
2482
+ if (ngx_http_complex_value(r, &pr->replacement, &replacement) != NGX_OK) {
2483
+ return NGX_ERROR;
2484
+ }
2485
+
2486
+ if (prefix == 0 && h->value.len == len) {
2487
+ h->value = replacement;
2488
+ return NGX_OK;
2489
+ }
2490
+
2491
+ return ngx_http_proxy_rewrite(r, h, prefix, len, &replacement);
2492
+ }
2493
+
2494
+ #endif
2495
+
2496
+
2497
+ static ngx_int_t
2498
+ ngx_http_proxy_rewrite_domain_handler(ngx_http_request_t *r,
2499
+ ngx_table_elt_t *h, size_t prefix, size_t len, ngx_http_proxy_rewrite_t *pr)
2500
+ {
2501
+ u_char *p;
2502
+ ngx_str_t pattern, replacement;
2503
+
2504
+ if (ngx_http_complex_value(r, &pr->pattern.complex, &pattern) != NGX_OK) {
2505
+ return NGX_ERROR;
2506
+ }
2507
+
2508
+ p = h->value.data + prefix;
2509
+
2510
+ if (p[0] == '.') {
2511
+ p++;
2512
+ prefix++;
2513
+ len--;
2514
+ }
2515
+
2516
+ if (pattern.len != len || ngx_rstrncasecmp(pattern.data, p, len) != 0) {
2517
+ return NGX_DECLINED;
2518
+ }
2519
+
2520
+ if (ngx_http_complex_value(r, &pr->replacement, &replacement) != NGX_OK) {
2521
+ return NGX_ERROR;
2522
+ }
2523
+
2524
+ return ngx_http_proxy_rewrite(r, h, prefix, len, &replacement);
2525
+ }
2526
+
2527
+
2528
+ static ngx_int_t
2529
+ ngx_http_proxy_rewrite(ngx_http_request_t *r, ngx_table_elt_t *h, size_t prefix,
2530
+ size_t len, ngx_str_t *replacement)
2531
+ {
2532
+ u_char *p, *data;
2533
+ size_t new_len;
2534
+
2535
+ new_len = replacement->len + h->value.len - len;
2536
+
2537
+ if (replacement->len > len) {
2538
+
2539
+ data = ngx_pnalloc(r->pool, new_len);
2540
+ if (data == NULL) {
2541
+ return NGX_ERROR;
2542
+ }
2543
+
2544
+ p = ngx_copy(data, h->value.data, prefix);
2545
+ p = ngx_copy(p, replacement->data, replacement->len);
2546
+
2547
+ ngx_memcpy(p, h->value.data + prefix + len,
2548
+ h->value.len - len - prefix);
2549
+
2550
+ h->value.data = data;
2551
+
2552
+ } else {
2553
+ p = ngx_copy(h->value.data + prefix, replacement->data,
2554
+ replacement->len);
2555
+
2556
+ ngx_memmove(p, h->value.data + prefix + len,
2557
+ h->value.len - len - prefix);
2558
+ }
2559
+
2560
+ h->value.len = new_len;
2561
+
2562
+ return NGX_OK;
2563
+ }
1613
2564
 
1614
2565
 
1615
2566
  static ngx_int_t
@@ -1692,6 +2643,8 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
1692
2643
  conf->upstream.cache_bypass = NGX_CONF_UNSET_PTR;
1693
2644
  conf->upstream.no_cache = NGX_CONF_UNSET_PTR;
1694
2645
  conf->upstream.cache_valid = NGX_CONF_UNSET_PTR;
2646
+ conf->upstream.cache_lock = NGX_CONF_UNSET;
2647
+ conf->upstream.cache_lock_timeout = NGX_CONF_UNSET_MSEC;
1695
2648
  #endif
1696
2649
 
1697
2650
  conf->upstream.hide_headers = NGX_CONF_UNSET_PTR;
@@ -1708,6 +2661,11 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
1708
2661
  conf->redirect = NGX_CONF_UNSET;
1709
2662
  conf->upstream.change_buffering = 1;
1710
2663
 
2664
+ conf->cookie_domains = NGX_CONF_UNSET_PTR;
2665
+ conf->cookie_paths = NGX_CONF_UNSET_PTR;
2666
+
2667
+ conf->http_version = NGX_CONF_UNSET_UINT;
2668
+
1711
2669
  conf->headers_hash_max_size = NGX_CONF_UNSET_UINT;
1712
2670
  conf->headers_hash_bucket_size = NGX_CONF_UNSET_UINT;
1713
2671
 
@@ -1727,7 +2685,7 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
1727
2685
  size_t size;
1728
2686
  ngx_hash_init_t hash;
1729
2687
  ngx_http_core_loc_conf_t *clcf;
1730
- ngx_http_proxy_redirect_t *pr;
2688
+ ngx_http_proxy_rewrite_t *pr;
1731
2689
  ngx_http_script_compile_t sc;
1732
2690
 
1733
2691
  if (conf->upstream.store != 0) {
@@ -1794,8 +2752,8 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
1794
2752
 
1795
2753
  if (conf->upstream.busy_buffers_size < size) {
1796
2754
  ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1797
- "\"proxy_busy_buffers_size\" must be equal or bigger than "
1798
- "maximum of the value of \"proxy_buffer_size\" and "
2755
+ "\"proxy_busy_buffers_size\" must be equal to or greater than "
2756
+ "the maximum of the value of \"proxy_buffer_size\" and "
1799
2757
  "one of the \"proxy_buffers\"");
1800
2758
 
1801
2759
  return NGX_CONF_ERROR;
@@ -1825,8 +2783,8 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
1825
2783
 
1826
2784
  if (conf->upstream.temp_file_write_size < size) {
1827
2785
  ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1828
- "\"proxy_temp_file_write_size\" must be equal or bigger than "
1829
- "maximum of the value of \"proxy_buffer_size\" and "
2786
+ "\"proxy_temp_file_write_size\" must be equal to or greater "
2787
+ "than the maximum of the value of \"proxy_buffer_size\" and "
1830
2788
  "one of the \"proxy_buffers\"");
1831
2789
 
1832
2790
  return NGX_CONF_ERROR;
@@ -1848,8 +2806,8 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
1848
2806
  {
1849
2807
  ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1850
2808
  "\"proxy_max_temp_file_size\" must be equal to zero to disable "
1851
- "the temporary files usage or must be equal or bigger than "
1852
- "maximum of the value of \"proxy_buffer_size\" and "
2809
+ "temporary files usage or must be equal to or greater than "
2810
+ "the maximum of the value of \"proxy_buffer_size\" and "
1853
2811
  "one of the \"proxy_buffers\"");
1854
2812
 
1855
2813
  return NGX_CONF_ERROR;
@@ -1940,6 +2898,12 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
1940
2898
  conf->cache_key = prev->cache_key;
1941
2899
  }
1942
2900
 
2901
+ ngx_conf_merge_value(conf->upstream.cache_lock,
2902
+ prev->upstream.cache_lock, 0);
2903
+
2904
+ ngx_conf_merge_msec_value(conf->upstream.cache_lock_timeout,
2905
+ prev->upstream.cache_lock_timeout, 5000);
2906
+
1943
2907
  #endif
1944
2908
 
1945
2909
  if (conf->method.len == 0) {
@@ -1974,7 +2938,7 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
1974
2938
  if (conf->redirects == NULL && conf->url.data) {
1975
2939
 
1976
2940
  conf->redirects = ngx_array_create(cf->pool, 1,
1977
- sizeof(ngx_http_proxy_redirect_t));
2941
+ sizeof(ngx_http_proxy_rewrite_t));
1978
2942
  if (conf->redirects == NULL) {
1979
2943
  return NGX_CONF_ERROR;
1980
2944
  }
@@ -1984,36 +2948,49 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
1984
2948
  return NGX_CONF_ERROR;
1985
2949
  }
1986
2950
 
1987
- pr->handler = ngx_http_proxy_rewrite_redirect_text;
2951
+ ngx_memzero(&pr->pattern.complex,
2952
+ sizeof(ngx_http_complex_value_t));
2953
+
2954
+ ngx_memzero(&pr->replacement, sizeof(ngx_http_complex_value_t));
2955
+
2956
+ pr->handler = ngx_http_proxy_rewrite_complex_handler;
1988
2957
 
1989
2958
  if (conf->vars.uri.len) {
1990
- pr->redirect = conf->url;
1991
- pr->replacement.text = conf->location;
2959
+ pr->pattern.complex.value = conf->url;
2960
+ pr->replacement.value = conf->location;
1992
2961
 
1993
2962
  } else {
1994
- pr->redirect.len = conf->url.len + sizeof("/") - 1;
2963
+ pr->pattern.complex.value.len = conf->url.len
2964
+ + sizeof("/") - 1;
1995
2965
 
1996
- p = ngx_pnalloc(cf->pool, pr->redirect.len);
2966
+ p = ngx_pnalloc(cf->pool, pr->pattern.complex.value.len);
1997
2967
  if (p == NULL) {
1998
2968
  return NGX_CONF_ERROR;
1999
2969
  }
2000
2970
 
2001
- pr->redirect.data = p;
2971
+ pr->pattern.complex.value.data = p;
2002
2972
 
2003
2973
  p = ngx_cpymem(p, conf->url.data, conf->url.len);
2004
2974
  *p = '/';
2005
2975
 
2006
- ngx_str_set(&pr->replacement.text, "/");
2976
+ ngx_str_set(&pr->replacement.value, "/");
2007
2977
  }
2008
2978
  }
2009
2979
  }
2010
2980
 
2981
+ ngx_conf_merge_ptr_value(conf->cookie_domains, prev->cookie_domains, NULL);
2982
+
2983
+ ngx_conf_merge_ptr_value(conf->cookie_paths, prev->cookie_paths, NULL);
2984
+
2011
2985
  #if (NGX_HTTP_SSL)
2012
2986
  if (conf->upstream.ssl == NULL) {
2013
2987
  conf->upstream.ssl = prev->upstream.ssl;
2014
2988
  }
2015
2989
  #endif
2016
2990
 
2991
+ ngx_conf_merge_uint_value(conf->http_version, prev->http_version,
2992
+ NGX_HTTP_VERSION_10);
2993
+
2017
2994
  ngx_conf_merge_uint_value(conf->headers_hash_max_size,
2018
2995
  prev->headers_hash_max_size, 512);
2019
2996
 
@@ -2466,11 +3443,11 @@ ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
2466
3443
  {
2467
3444
  if (plcf->vars.uri.len) {
2468
3445
  ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2469
- "\"proxy_pass\" may not have URI part in "
3446
+ "\"proxy_pass\" cannot have URI part in "
2470
3447
  "location given by regular expression, "
2471
3448
  "or inside named location, "
2472
- "or inside the \"if\" statement, "
2473
- "or inside the \"limit_except\" block");
3449
+ "or inside \"if\" statement, "
3450
+ "or inside \"limit_except\" block");
2474
3451
  return NGX_CONF_ERROR;
2475
3452
  }
2476
3453
 
@@ -2488,11 +3465,10 @@ ngx_http_proxy_redirect(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
2488
3465
  {
2489
3466
  ngx_http_proxy_loc_conf_t *plcf = conf;
2490
3467
 
2491
- u_char *p;
2492
- ngx_str_t *value;
2493
- ngx_array_t *vars_lengths, *vars_values;
2494
- ngx_http_script_compile_t sc;
2495
- ngx_http_proxy_redirect_t *pr;
3468
+ u_char *p;
3469
+ ngx_str_t *value;
3470
+ ngx_http_proxy_rewrite_t *pr;
3471
+ ngx_http_compile_complex_value_t ccv;
2496
3472
 
2497
3473
  if (plcf->redirect == 0) {
2498
3474
  return NGX_CONF_OK;
@@ -2526,7 +3502,7 @@ ngx_http_proxy_redirect(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
2526
3502
 
2527
3503
  if (plcf->redirects == NULL) {
2528
3504
  plcf->redirects = ngx_array_create(cf->pool, 1,
2529
- sizeof(ngx_http_proxy_redirect_t));
3505
+ sizeof(ngx_http_proxy_rewrite_t));
2530
3506
  if (plcf->redirects == NULL) {
2531
3507
  return NGX_CONF_ERROR;
2532
3508
  }
@@ -2540,76 +3516,307 @@ ngx_http_proxy_redirect(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
2540
3516
  if (ngx_strcmp(value[1].data, "default") == 0) {
2541
3517
  if (plcf->proxy_lengths) {
2542
3518
  ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2543
- "\"proxy_redirect default\" may not be used "
3519
+ "\"proxy_redirect default\" cannot be used "
2544
3520
  "with \"proxy_pass\" directive with variables");
2545
3521
  return NGX_CONF_ERROR;
2546
3522
  }
2547
3523
 
2548
3524
  if (plcf->url.data == NULL) {
2549
3525
  ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2550
- "\"proxy_redirect default\" must go "
3526
+ "\"proxy_redirect default\" should be placed "
2551
3527
  "after the \"proxy_pass\" directive");
2552
3528
  return NGX_CONF_ERROR;
2553
3529
  }
2554
3530
 
2555
- pr->handler = ngx_http_proxy_rewrite_redirect_text;
3531
+ pr->handler = ngx_http_proxy_rewrite_complex_handler;
3532
+
3533
+ ngx_memzero(&pr->pattern.complex, sizeof(ngx_http_complex_value_t));
3534
+
3535
+ ngx_memzero(&pr->replacement, sizeof(ngx_http_complex_value_t));
2556
3536
 
2557
3537
  if (plcf->vars.uri.len) {
2558
- pr->redirect = plcf->url;
2559
- pr->replacement.text = plcf->location;
3538
+ pr->pattern.complex.value = plcf->url;
3539
+ pr->replacement.value = plcf->location;
2560
3540
 
2561
3541
  } else {
2562
- pr->redirect.len = plcf->url.len + sizeof("/") - 1;
3542
+ pr->pattern.complex.value.len = plcf->url.len + sizeof("/") - 1;
2563
3543
 
2564
- p = ngx_pnalloc(cf->pool, pr->redirect.len);
3544
+ p = ngx_pnalloc(cf->pool, pr->pattern.complex.value.len);
2565
3545
  if (p == NULL) {
2566
3546
  return NGX_CONF_ERROR;
2567
3547
  }
2568
3548
 
2569
- pr->redirect.data = p;
3549
+ pr->pattern.complex.value.data = p;
2570
3550
 
2571
3551
  p = ngx_cpymem(p, plcf->url.data, plcf->url.len);
2572
3552
  *p = '/';
2573
3553
 
2574
- ngx_str_set(&pr->replacement.text, "/");
3554
+ ngx_str_set(&pr->replacement.value, "/");
3555
+ }
3556
+
3557
+ return NGX_CONF_OK;
3558
+ }
3559
+
3560
+
3561
+ if (value[1].data[0] == '~') {
3562
+ value[1].len--;
3563
+ value[1].data++;
3564
+
3565
+ if (value[1].data[0] == '*') {
3566
+ value[1].len--;
3567
+ value[1].data++;
3568
+
3569
+ if (ngx_http_proxy_rewrite_regex(cf, pr, &value[1], 1) != NGX_OK) {
3570
+ return NGX_CONF_ERROR;
3571
+ }
3572
+
3573
+ } else {
3574
+ if (ngx_http_proxy_rewrite_regex(cf, pr, &value[1], 0) != NGX_OK) {
3575
+ return NGX_CONF_ERROR;
3576
+ }
3577
+ }
3578
+
3579
+ } else {
3580
+
3581
+ ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
3582
+
3583
+ ccv.cf = cf;
3584
+ ccv.value = &value[1];
3585
+ ccv.complex_value = &pr->pattern.complex;
3586
+
3587
+ if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
3588
+ return NGX_CONF_ERROR;
2575
3589
  }
2576
3590
 
3591
+ pr->handler = ngx_http_proxy_rewrite_complex_handler;
3592
+ }
3593
+
3594
+
3595
+ ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
3596
+
3597
+ ccv.cf = cf;
3598
+ ccv.value = &value[2];
3599
+ ccv.complex_value = &pr->replacement;
3600
+
3601
+ if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
3602
+ return NGX_CONF_ERROR;
3603
+ }
3604
+
3605
+ return NGX_CONF_OK;
3606
+ }
3607
+
3608
+
3609
+ static char *
3610
+ ngx_http_proxy_cookie_domain(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3611
+ {
3612
+ ngx_http_proxy_loc_conf_t *plcf = conf;
3613
+
3614
+ ngx_str_t *value;
3615
+ ngx_http_proxy_rewrite_t *pr;
3616
+ ngx_http_compile_complex_value_t ccv;
3617
+
3618
+ if (plcf->cookie_domains == NULL) {
2577
3619
  return NGX_CONF_OK;
2578
3620
  }
2579
3621
 
2580
- if (ngx_http_script_variables_count(&value[2]) == 0) {
2581
- pr->handler = ngx_http_proxy_rewrite_redirect_text;
2582
- pr->redirect = value[1];
2583
- pr->replacement.text = value[2];
3622
+ value = cf->args->elts;
3623
+
3624
+ if (cf->args->nelts == 2) {
3625
+
3626
+ if (ngx_strcmp(value[1].data, "off") == 0) {
3627
+ plcf->cookie_domains = NULL;
3628
+ return NGX_CONF_OK;
3629
+ }
3630
+
3631
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3632
+ "invalid parameter \"%V\"", &value[1]);
3633
+ return NGX_CONF_ERROR;
3634
+ }
3635
+
3636
+ if (plcf->cookie_domains == NGX_CONF_UNSET_PTR) {
3637
+ plcf->cookie_domains = ngx_array_create(cf->pool, 1,
3638
+ sizeof(ngx_http_proxy_rewrite_t));
3639
+ if (plcf->cookie_domains == NULL) {
3640
+ return NGX_CONF_ERROR;
3641
+ }
3642
+ }
3643
+
3644
+ pr = ngx_array_push(plcf->cookie_domains);
3645
+ if (pr == NULL) {
3646
+ return NGX_CONF_ERROR;
3647
+ }
3648
+
3649
+ if (value[1].data[0] == '~') {
3650
+ value[1].len--;
3651
+ value[1].data++;
3652
+
3653
+ if (ngx_http_proxy_rewrite_regex(cf, pr, &value[1], 1) != NGX_OK) {
3654
+ return NGX_CONF_ERROR;
3655
+ }
3656
+
3657
+ } else {
3658
+
3659
+ if (value[1].data[0] == '.') {
3660
+ value[1].len--;
3661
+ value[1].data++;
3662
+ }
3663
+
3664
+ ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
3665
+
3666
+ ccv.cf = cf;
3667
+ ccv.value = &value[1];
3668
+ ccv.complex_value = &pr->pattern.complex;
3669
+
3670
+ if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
3671
+ return NGX_CONF_ERROR;
3672
+ }
3673
+
3674
+ pr->handler = ngx_http_proxy_rewrite_domain_handler;
3675
+
3676
+ if (value[2].data[0] == '.') {
3677
+ value[2].len--;
3678
+ value[2].data++;
3679
+ }
3680
+ }
3681
+
3682
+ ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
3683
+
3684
+ ccv.cf = cf;
3685
+ ccv.value = &value[2];
3686
+ ccv.complex_value = &pr->replacement;
3687
+
3688
+ if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
3689
+ return NGX_CONF_ERROR;
3690
+ }
3691
+
3692
+ return NGX_CONF_OK;
3693
+ }
3694
+
3695
+
3696
+ static char *
3697
+ ngx_http_proxy_cookie_path(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3698
+ {
3699
+ ngx_http_proxy_loc_conf_t *plcf = conf;
3700
+
3701
+ ngx_str_t *value;
3702
+ ngx_http_proxy_rewrite_t *pr;
3703
+ ngx_http_compile_complex_value_t ccv;
2584
3704
 
3705
+ if (plcf->cookie_paths == NULL) {
2585
3706
  return NGX_CONF_OK;
2586
3707
  }
2587
3708
 
2588
- ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
3709
+ value = cf->args->elts;
2589
3710
 
2590
- vars_lengths = NULL;
2591
- vars_values = NULL;
3711
+ if (cf->args->nelts == 2) {
2592
3712
 
2593
- sc.cf = cf;
2594
- sc.source = &value[2];
2595
- sc.lengths = &vars_lengths;
2596
- sc.values = &vars_values;
2597
- sc.complete_lengths = 1;
2598
- sc.complete_values = 1;
3713
+ if (ngx_strcmp(value[1].data, "off") == 0) {
3714
+ plcf->cookie_paths = NULL;
3715
+ return NGX_CONF_OK;
3716
+ }
2599
3717
 
2600
- if (ngx_http_script_compile(&sc) != NGX_OK) {
3718
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3719
+ "invalid parameter \"%V\"", &value[1]);
3720
+ return NGX_CONF_ERROR;
3721
+ }
3722
+
3723
+ if (plcf->cookie_paths == NGX_CONF_UNSET_PTR) {
3724
+ plcf->cookie_paths = ngx_array_create(cf->pool, 1,
3725
+ sizeof(ngx_http_proxy_rewrite_t));
3726
+ if (plcf->cookie_paths == NULL) {
3727
+ return NGX_CONF_ERROR;
3728
+ }
3729
+ }
3730
+
3731
+ pr = ngx_array_push(plcf->cookie_paths);
3732
+ if (pr == NULL) {
2601
3733
  return NGX_CONF_ERROR;
2602
3734
  }
2603
3735
 
2604
- pr->handler = ngx_http_proxy_rewrite_redirect_vars;
2605
- pr->redirect = value[1];
2606
- pr->replacement.vars.lengths = vars_lengths->elts;
2607
- pr->replacement.vars.values = vars_values->elts;
3736
+ if (value[1].data[0] == '~') {
3737
+ value[1].len--;
3738
+ value[1].data++;
3739
+
3740
+ if (value[1].data[0] == '*') {
3741
+ value[1].len--;
3742
+ value[1].data++;
3743
+
3744
+ if (ngx_http_proxy_rewrite_regex(cf, pr, &value[1], 1) != NGX_OK) {
3745
+ return NGX_CONF_ERROR;
3746
+ }
3747
+
3748
+ } else {
3749
+ if (ngx_http_proxy_rewrite_regex(cf, pr, &value[1], 0) != NGX_OK) {
3750
+ return NGX_CONF_ERROR;
3751
+ }
3752
+ }
3753
+
3754
+ } else {
3755
+
3756
+ ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
3757
+
3758
+ ccv.cf = cf;
3759
+ ccv.value = &value[1];
3760
+ ccv.complex_value = &pr->pattern.complex;
3761
+
3762
+ if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
3763
+ return NGX_CONF_ERROR;
3764
+ }
3765
+
3766
+ pr->handler = ngx_http_proxy_rewrite_complex_handler;
3767
+ }
3768
+
3769
+ ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
3770
+
3771
+ ccv.cf = cf;
3772
+ ccv.value = &value[2];
3773
+ ccv.complex_value = &pr->replacement;
3774
+
3775
+ if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
3776
+ return NGX_CONF_ERROR;
3777
+ }
2608
3778
 
2609
3779
  return NGX_CONF_OK;
2610
3780
  }
2611
3781
 
2612
3782
 
3783
+ static ngx_int_t
3784
+ ngx_http_proxy_rewrite_regex(ngx_conf_t *cf, ngx_http_proxy_rewrite_t *pr,
3785
+ ngx_str_t *regex, ngx_uint_t caseless)
3786
+ {
3787
+ #if (NGX_PCRE)
3788
+ u_char errstr[NGX_MAX_CONF_ERRSTR];
3789
+ ngx_regex_compile_t rc;
3790
+
3791
+ ngx_memzero(&rc, sizeof(ngx_regex_compile_t));
3792
+
3793
+ rc.pattern = *regex;
3794
+ rc.err.len = NGX_MAX_CONF_ERRSTR;
3795
+ rc.err.data = errstr;
3796
+
3797
+ if (caseless) {
3798
+ rc.options = NGX_REGEX_CASELESS;
3799
+ }
3800
+
3801
+ pr->pattern.regex = ngx_http_regex_compile(cf, &rc);
3802
+ if (pr->pattern.regex == NULL) {
3803
+ return NGX_ERROR;
3804
+ }
3805
+
3806
+ pr->handler = ngx_http_proxy_rewrite_regex_handler;
3807
+
3808
+ return NGX_OK;
3809
+
3810
+ #else
3811
+
3812
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3813
+ "using regex \"%V\" requires PCRE library", regex);
3814
+ return NGX_ERROR;
3815
+
3816
+ #endif
3817
+ }
3818
+
3819
+
2613
3820
  static char *
2614
3821
  ngx_http_proxy_store(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
2615
3822
  {