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.
- data/VERSION +1 -1
- data/bin/nginxtra +1 -1
- data/lib/nginxtra/action.rb +10 -0
- data/lib/nginxtra/actions/compile.rb +16 -2
- data/lib/nginxtra/actions/start.rb +18 -2
- data/lib/nginxtra/actions/status.rb +1 -10
- data/lib/nginxtra/actions/stop.rb +18 -0
- data/lib/nginxtra/cli.rb +12 -3
- data/lib/nginxtra/config.rb +10 -0
- data/src/nginx/CHANGES +311 -90
- data/src/nginx/CHANGES.ru +315 -88
- data/src/nginx/auto/lib/pcre/conf +22 -5
- data/src/nginx/auto/lib/pcre/make +1 -1
- data/src/nginx/auto/modules +14 -3
- data/src/nginx/auto/options +17 -3
- data/src/nginx/auto/os/freebsd +8 -0
- data/src/nginx/auto/os/linux +5 -4
- data/src/nginx/auto/os/solaris +2 -1
- data/src/nginx/auto/sources +10 -2
- data/src/nginx/auto/summary +2 -0
- data/src/nginx/auto/types/sizeof +2 -1
- data/src/nginx/auto/types/typedef +1 -1
- data/src/nginx/auto/types/uintptr_t +7 -4
- data/src/nginx/auto/unix +82 -21
- data/src/nginx/conf/fastcgi.conf +1 -0
- data/src/nginx/conf/fastcgi_params +1 -0
- data/src/nginx/conf/scgi_params +1 -0
- data/src/nginx/conf/uwsgi_params +1 -0
- data/src/nginx/man/nginx.8 +49 -49
- data/src/nginx/src/core/nginx.c +10 -12
- data/src/nginx/src/core/nginx.h +2 -2
- data/src/nginx/src/core/ngx_buf.c +9 -7
- data/src/nginx/src/core/ngx_buf.h +2 -2
- data/src/nginx/src/core/ngx_conf_file.c +4 -11
- data/src/nginx/src/core/ngx_conf_file.h +1 -1
- data/src/nginx/src/core/ngx_connection.c +52 -1
- data/src/nginx/src/core/ngx_connection.h +6 -0
- data/src/nginx/src/core/ngx_core.h +5 -0
- data/src/nginx/src/core/ngx_cycle.c +1 -1
- data/src/nginx/src/core/ngx_cycle.h +2 -2
- data/src/nginx/src/core/ngx_file.c +1 -1
- data/src/nginx/src/core/ngx_inet.c +11 -8
- data/src/nginx/src/core/ngx_murmurhash.h +1 -1
- data/src/nginx/src/core/ngx_open_file_cache.c +343 -38
- data/src/nginx/src/core/ngx_open_file_cache.h +10 -0
- data/src/nginx/src/core/ngx_output_chain.c +2 -1
- data/src/nginx/src/core/ngx_parse.h +0 -3
- data/src/nginx/src/core/ngx_rbtree.c +1 -2
- data/src/nginx/src/core/ngx_regex.c +263 -5
- data/src/nginx/src/core/ngx_regex.h +6 -2
- data/src/nginx/src/core/ngx_resolver.c +88 -21
- data/src/nginx/src/core/ngx_resolver.h +7 -8
- data/src/nginx/src/core/ngx_shmtx.c +69 -44
- data/src/nginx/src/core/ngx_shmtx.h +12 -1
- data/src/nginx/src/core/ngx_slab.c +3 -3
- data/src/nginx/src/core/ngx_slab.h +1 -1
- data/src/nginx/src/core/ngx_string.c +19 -16
- data/src/nginx/src/core/ngx_times.c +2 -2
- data/src/nginx/src/event/modules/ngx_epoll_module.c +2 -2
- data/src/nginx/src/event/modules/ngx_eventport_module.c +1 -1
- data/src/nginx/src/event/modules/ngx_kqueue_module.c +1 -1
- data/src/nginx/src/event/ngx_event.c +25 -17
- data/src/nginx/src/event/ngx_event_openssl.c +3 -1
- data/src/nginx/src/event/ngx_event_pipe.c +108 -85
- data/src/nginx/src/event/ngx_event_pipe.h +1 -2
- data/src/nginx/src/event/ngx_event_timer.c +2 -3
- data/src/nginx/src/http/modules/ngx_http_access_module.c +9 -4
- data/src/nginx/src/http/modules/ngx_http_browser_module.c +5 -3
- data/src/nginx/src/http/modules/ngx_http_chunked_filter_module.c +1 -1
- data/src/nginx/src/http/modules/ngx_http_degradation_module.c +1 -1
- data/src/nginx/src/http/modules/ngx_http_fastcgi_module.c +144 -22
- data/src/nginx/src/http/modules/ngx_http_flv_module.c +8 -0
- data/src/nginx/src/http/modules/ngx_http_geo_module.c +3 -3
- data/src/nginx/src/http/modules/ngx_http_gzip_filter_module.c +20 -6
- data/src/nginx/src/http/modules/ngx_http_gzip_static_module.c +8 -0
- data/src/nginx/src/http/modules/ngx_http_headers_filter_module.c +23 -27
- data/src/nginx/src/http/modules/ngx_http_image_filter_module.c +1 -3
- data/src/nginx/src/http/modules/ngx_http_index_module.c +24 -0
- data/src/nginx/src/http/modules/ngx_http_limit_conn_module.c +747 -0
- data/src/nginx/src/http/modules/ngx_http_limit_req_module.c +289 -133
- data/src/nginx/src/http/modules/ngx_http_log_module.c +34 -6
- data/src/nginx/src/http/modules/ngx_http_memcached_module.c +19 -3
- data/src/nginx/src/http/modules/ngx_http_mp4_module.c +8 -0
- data/src/nginx/src/http/modules/ngx_http_proxy_module.c +1446 -239
- data/src/nginx/src/http/modules/ngx_http_realip_module.c +4 -10
- data/src/nginx/src/http/modules/ngx_http_scgi_module.c +90 -21
- data/src/nginx/src/http/modules/ngx_http_split_clients_module.c +8 -11
- data/src/nginx/src/http/modules/ngx_http_ssi_filter_module.c +16 -6
- data/src/nginx/src/http/modules/ngx_http_static_module.c +8 -0
- data/src/nginx/src/http/modules/ngx_http_upstream_ip_hash_module.c +2 -2
- data/src/nginx/src/http/modules/ngx_http_upstream_keepalive_module.c +570 -0
- data/src/nginx/src/http/modules/ngx_http_userid_filter_module.c +1 -5
- data/src/nginx/src/http/modules/ngx_http_uwsgi_module.c +77 -26
- data/src/nginx/src/http/modules/ngx_http_xslt_filter_module.c +171 -37
- data/src/nginx/src/http/modules/perl/nginx.pm +2 -1
- data/src/nginx/src/http/modules/perl/nginx.xs +4 -0
- data/src/nginx/src/http/ngx_http.c +8 -1
- data/src/nginx/src/http/ngx_http.h +1 -0
- data/src/nginx/src/http/ngx_http_busy_lock.c +2 -2
- data/src/nginx/src/http/ngx_http_cache.h +12 -1
- data/src/nginx/src/http/ngx_http_copy_filter_module.c +4 -3
- data/src/nginx/src/http/ngx_http_core_module.c +303 -37
- data/src/nginx/src/http/ngx_http_core_module.h +15 -0
- data/src/nginx/src/http/ngx_http_file_cache.c +226 -52
- data/src/nginx/src/http/ngx_http_parse.c +69 -3
- data/src/nginx/src/http/ngx_http_postpone_filter_module.c +4 -4
- data/src/nginx/src/http/ngx_http_request.c +61 -27
- data/src/nginx/src/http/ngx_http_request.h +3 -3
- data/src/nginx/src/http/ngx_http_request_body.c +1 -1
- data/src/nginx/src/http/ngx_http_script.c +6 -0
- data/src/nginx/src/http/ngx_http_upstream.c +200 -47
- data/src/nginx/src/http/ngx_http_upstream.h +20 -1
- data/src/nginx/src/http/ngx_http_upstream_round_robin.c +22 -6
- data/src/nginx/src/http/ngx_http_upstream_round_robin.h +1 -0
- data/src/nginx/src/http/ngx_http_variables.c +123 -4
- data/src/nginx/src/mail/ngx_mail.c +13 -0
- data/src/nginx/src/mail/ngx_mail.h +12 -0
- data/src/nginx/src/mail/ngx_mail_core_module.c +100 -15
- data/src/nginx/src/os/unix/ngx_daemon.c +2 -1
- data/src/nginx/src/os/unix/ngx_darwin.h +3 -0
- data/src/nginx/src/os/unix/ngx_darwin_config.h +1 -0
- data/src/nginx/src/os/unix/ngx_darwin_init.c +30 -0
- data/src/nginx/src/os/unix/ngx_darwin_sendfile_chain.c +11 -5
- data/src/nginx/src/os/unix/ngx_errno.h +5 -0
- data/src/nginx/src/os/unix/ngx_files.h +50 -1
- data/src/nginx/src/os/unix/ngx_freebsd.h +2 -1
- data/src/nginx/src/os/unix/ngx_freebsd_config.h +2 -0
- data/src/nginx/src/os/unix/ngx_freebsd_init.c +4 -3
- data/src/nginx/src/os/unix/ngx_freebsd_rfork_thread.c +2 -2
- data/src/nginx/src/os/unix/ngx_freebsd_sendfile_chain.c +12 -6
- data/src/nginx/src/os/unix/ngx_gcc_atomic_sparc64.h +1 -1
- data/src/nginx/src/os/unix/ngx_linux_config.h +1 -0
- data/src/nginx/src/os/unix/ngx_linux_sendfile_chain.c +6 -4
- data/src/nginx/src/os/unix/ngx_os.h +0 -1
- data/src/nginx/src/os/unix/ngx_posix_config.h +3 -0
- data/src/nginx/src/os/unix/ngx_process.c +50 -11
- data/src/nginx/src/os/unix/ngx_process.h +1 -0
- data/src/nginx/src/os/unix/ngx_process_cycle.c +6 -15
- data/src/nginx/src/os/unix/ngx_readv_chain.c +8 -0
- data/src/nginx/src/os/unix/ngx_setaffinity.c +69 -0
- data/src/nginx/src/os/unix/ngx_setaffinity.h +23 -0
- data/src/nginx/src/os/unix/ngx_setproctitle.c +1 -1
- data/src/nginx/src/os/unix/ngx_solaris_config.h +2 -0
- data/src/nginx/src/os/unix/ngx_solaris_sendfilev_chain.c +11 -3
- data/src/nginx/src/os/unix/ngx_writev_chain.c +7 -3
- metadata +7 -4
- 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, "%
|
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
|
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
|
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
|
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
|
-
|
349
|
-
if (
|
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
|
13
|
+
typedef struct ngx_http_proxy_rewrite_s ngx_http_proxy_rewrite_t;
|
14
14
|
|
15
|
-
typedef ngx_int_t (*
|
16
|
-
ngx_table_elt_t *h, size_t prefix,
|
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
|
19
|
-
|
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
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
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
|
-
|
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 =
|
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
|
-
|
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
|
-
|
1014
|
-
|
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
|
-
|
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
|
-
|
1393
|
-
return NGX_OK;
|
1501
|
+
return NGX_ERROR;
|
1394
1502
|
}
|
1395
1503
|
|
1396
|
-
|
1397
|
-
|
1398
|
-
|
1399
|
-
|
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
|
-
|
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
|
-
|
1407
|
-
|
1408
|
-
|
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
|
-
|
1522
|
+
} else if (u->headers_in.chunked) {
|
1523
|
+
/* chunked */
|
1413
1524
|
|
1414
|
-
|
1415
|
-
|
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
|
-
|
1420
|
-
|
1421
|
-
|
1422
|
-
|
1423
|
-
|
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
|
-
|
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
|
-
|
1434
|
-
|
1435
|
-
|
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 (
|
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
|
-
|
1446
|
-
|
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
|
-
|
1449
|
-
|
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
|
-
|
1585
|
+
cl->buf = b;
|
1586
|
+
cl->next = NULL;
|
1454
1587
|
|
1455
|
-
p
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
1476
|
-
return NGX_OK;
|
1645
|
+
return NGX_ERROR;
|
1477
1646
|
}
|
1478
1647
|
|
1479
|
-
|
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 (
|
1486
|
-
|
1650
|
+
if (state == sw_chunk_data && ctx->size == 0) {
|
1651
|
+
state = sw_after_data;
|
1487
1652
|
}
|
1488
1653
|
|
1489
|
-
|
1654
|
+
rc = NGX_AGAIN;
|
1490
1655
|
|
1491
|
-
|
1492
|
-
}
|
1656
|
+
for (pos = buf->pos; pos < buf->last; pos++) {
|
1493
1657
|
|
1658
|
+
ch = *pos;
|
1494
1659
|
|
1495
|
-
|
1496
|
-
|
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
|
-
|
1663
|
+
switch (state) {
|
1505
1664
|
|
1506
|
-
|
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
|
-
|
1509
|
-
return NGX_DECLINED;
|
1510
|
-
}
|
1672
|
+
c = (u_char) (ch | 0x20);
|
1511
1673
|
|
1512
|
-
|
1513
|
-
|
1674
|
+
if (c >= 'a' && c <= 'f') {
|
1675
|
+
state = sw_chunk_size;
|
1676
|
+
ctx->size = c - 'a' + 10;
|
1677
|
+
break;
|
1678
|
+
}
|
1514
1679
|
|
1515
|
-
|
1516
|
-
return rc;
|
1517
|
-
}
|
1518
|
-
}
|
1680
|
+
goto invalid;
|
1519
1681
|
|
1520
|
-
|
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
|
-
|
1525
|
-
|
1526
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
1541
|
-
|
1542
|
-
|
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
|
-
|
1817
|
+
case sw_trailer_header_almost_done:
|
1818
|
+
if (ch == LF) {
|
1819
|
+
state = sw_trailer;
|
1820
|
+
break;
|
1821
|
+
}
|
1822
|
+
goto invalid;
|
1546
1823
|
|
1547
|
-
|
1548
|
-
p = ngx_copy(p, pr->replacement.text.data, pr->replacement.text.len);
|
1824
|
+
}
|
1549
1825
|
}
|
1550
1826
|
|
1551
|
-
|
1552
|
-
|
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
|
-
|
1555
|
-
h->value.data = data;
|
1871
|
+
return NGX_DONE;
|
1556
1872
|
|
1557
|
-
|
1873
|
+
invalid:
|
1874
|
+
|
1875
|
+
return NGX_ERROR;
|
1558
1876
|
}
|
1559
1877
|
|
1560
1878
|
|
1561
1879
|
static ngx_int_t
|
1562
|
-
|
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
|
-
|
1566
|
-
|
1567
|
-
|
1568
|
-
|
1569
|
-
|
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 (
|
1572
|
-
|
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
|
-
|
1892
|
+
r = p->input_ctx;
|
1893
|
+
ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
|
1579
1894
|
|
1580
|
-
|
1581
|
-
|
1895
|
+
if (ctx == NULL) {
|
1896
|
+
return NGX_ERROR;
|
1897
|
+
}
|
1582
1898
|
|
1583
|
-
|
1899
|
+
b = NULL;
|
1900
|
+
prev = &buf->shadow;
|
1584
1901
|
|
1585
|
-
|
1586
|
-
lcode = *(ngx_http_script_len_code_pt *) e.ip;
|
1587
|
-
len += lcode(&e);
|
1588
|
-
}
|
1902
|
+
for ( ;; ) {
|
1589
1903
|
|
1590
|
-
|
1591
|
-
if (data == NULL) {
|
1592
|
-
return NGX_ERROR;
|
1593
|
-
}
|
1904
|
+
rc = ngx_http_proxy_parse_chunked(r, buf);
|
1594
1905
|
|
1595
|
-
|
1906
|
+
if (rc == NGX_OK) {
|
1596
1907
|
|
1597
|
-
|
1598
|
-
e.pos = p;
|
1908
|
+
/* a chunk has been parsed successfully */
|
1599
1909
|
|
1600
|
-
|
1601
|
-
|
1602
|
-
|
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
|
-
|
1606
|
-
|
1916
|
+
} else {
|
1917
|
+
b = ngx_alloc_buf(p->pool);
|
1918
|
+
if (b == NULL) {
|
1919
|
+
return NGX_ERROR;
|
1920
|
+
}
|
1921
|
+
}
|
1607
1922
|
|
1608
|
-
|
1609
|
-
h->value.data = data;
|
1923
|
+
ngx_memzero(b, sizeof(ngx_buf_t));
|
1610
1924
|
|
1611
|
-
|
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
|
-
|
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
|
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
|
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
|
-
"
|
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
|
-
|
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->
|
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->
|
1991
|
-
pr->replacement.
|
2959
|
+
pr->pattern.complex.value = conf->url;
|
2960
|
+
pr->replacement.value = conf->location;
|
1992
2961
|
|
1993
2962
|
} else {
|
1994
|
-
pr->
|
2963
|
+
pr->pattern.complex.value.len = conf->url.len
|
2964
|
+
+ sizeof("/") - 1;
|
1995
2965
|
|
1996
|
-
p = ngx_pnalloc(cf->pool, pr->
|
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->
|
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.
|
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\"
|
3446
|
+
"\"proxy_pass\" cannot have URI part in "
|
2470
3447
|
"location given by regular expression, "
|
2471
3448
|
"or inside named location, "
|
2472
|
-
"or inside
|
2473
|
-
"or inside
|
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
|
2492
|
-
ngx_str_t
|
2493
|
-
|
2494
|
-
|
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(
|
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\"
|
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\"
|
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 =
|
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->
|
2559
|
-
pr->replacement.
|
3538
|
+
pr->pattern.complex.value = plcf->url;
|
3539
|
+
pr->replacement.value = plcf->location;
|
2560
3540
|
|
2561
3541
|
} else {
|
2562
|
-
pr->
|
3542
|
+
pr->pattern.complex.value.len = plcf->url.len + sizeof("/") - 1;
|
2563
3543
|
|
2564
|
-
p = ngx_pnalloc(cf->pool, pr->
|
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->
|
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.
|
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
|
-
|
2581
|
-
|
2582
|
-
|
2583
|
-
|
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
|
-
|
3709
|
+
value = cf->args->elts;
|
2589
3710
|
|
2590
|
-
|
2591
|
-
vars_values = NULL;
|
3711
|
+
if (cf->args->nelts == 2) {
|
2592
3712
|
|
2593
|
-
|
2594
|
-
|
2595
|
-
|
2596
|
-
|
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
|
-
|
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
|
-
|
2605
|
-
|
2606
|
-
|
2607
|
-
|
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
|
{
|