Skip to content

Commit 724013e

Browse files
authored
Merge pull request chobits#85 from chobits/for_pull_request
Added $proxy_connect_*_timeout that control timeout of connect/write/read upstream
2 parents 0c4ea42 + 0e80309 commit 724013e

File tree

3 files changed

+500
-23
lines changed

3 files changed

+500
-23
lines changed

README.md

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ Table of Contents
2525
* [$connect_host](#connect_host)
2626
* [$connect_port](#connect_port)
2727
* [$connect_addr](#connect_addr)
28+
* [$proxy_connect_connect_timeout](#proxy_connect_connect_timeout-1)
29+
* [$proxy_connect_read_timeout](#proxy_connect_read_timeout-1)
30+
* [$proxy_connect_send_timeout](#proxy_connect_send_timeout-1)
2831
* [Nginx Compatibility](#nginx-compatibility)
2932
* [Tengine Compatibility](#tengine-compatibility)
3033
* [Author](#author)
@@ -232,7 +235,7 @@ The timeout is set only between two successive read operations, not for the tran
232235
If the proxied server does not transmit anything within this time, the connection is closed.
233236

234237
proxy_connect_send_timeout
235-
---------------------------
238+
--------------------------
236239

237240
Syntax: **proxy_connect_send_timeout `time`**
238241
Default: `60s`
@@ -294,6 +297,39 @@ $connect_addr
294297
IP address and port of the remote host, e.g. "192.168.1.5:12345".
295298
IP address is resolved from host name of CONNECT request line.
296299

300+
$proxy_connect_connect_timeout
301+
------------------------------
302+
303+
Get or set timeout of [`proxy_connect_connect_timeout` directive](#proxy_connect_connect_timeout).
304+
305+
For example:
306+
307+
```
308+
# Set default value
309+
310+
proxy_connect_connect_timeout 10s;
311+
proxy_connect_read_timeout 10s;
312+
proxy_connect_send_timeout 10s;
313+
314+
# Overlap default value
315+
316+
if ($host = "test.com") {
317+
set $proxy_connect_connect_timeout "10ms";
318+
set $proxy_connect_read_timeout "10ms";
319+
set $proxy_connect_send_timeout "10ms";
320+
}
321+
```
322+
323+
$proxy_connect_read_timeout
324+
---------------------------
325+
326+
Get or set a timeout of [`proxy_connect_read_timeout` directive](#proxy_connect_read_timeout).
327+
328+
$proxy_connect_send_timeout
329+
---------------------------
330+
331+
Get or set a timeout of [`proxy_connect_send_timeout` directive](#proxy_connect_send_timeout).
332+
297333
Nginx Compatibility
298334
===================
299335

ngx_http_proxy_connect_module.c

Lines changed: 139 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ typedef struct {
7777

7878
ngx_buf_t buf;
7979

80+
ngx_msec_t connect_timeout;
81+
ngx_msec_t send_timeout;
82+
ngx_msec_t read_timeout;
83+
8084
} ngx_http_proxy_connect_ctx_t;
8185

8286

@@ -102,7 +106,10 @@ static ngx_int_t ngx_http_proxy_connect_set_local(ngx_http_request_t *r,
102106
ngx_http_proxy_connect_upstream_t *u, ngx_http_proxy_connect_address_t *local);
103107
static ngx_int_t ngx_http_proxy_connect_set_address(ngx_http_request_t *r,
104108
ngx_http_proxy_connect_upstream_t *u, ngx_http_proxy_connect_address_t *address);
105-
109+
static ngx_int_t ngx_http_proxy_connect_variable_get_time(ngx_http_request_t *r,
110+
ngx_http_variable_value_t *v, uintptr_t data);
111+
static void ngx_http_proxy_connect_variable_set_time(ngx_http_request_t *r,
112+
ngx_http_variable_value_t *v, uintptr_t data);
106113

107114

108115

@@ -206,6 +213,24 @@ static ngx_http_variable_t ngx_http_proxy_connect_vars[] = {
206213
ngx_http_proxy_connect_connect_addr_variable,
207214
0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
208215

216+
{ ngx_string("proxy_connect_connect_timeout"),
217+
ngx_http_proxy_connect_variable_set_time,
218+
ngx_http_proxy_connect_variable_get_time,
219+
offsetof(ngx_http_proxy_connect_ctx_t, connect_timeout),
220+
NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_CHANGEABLE, 0 },
221+
222+
{ ngx_string("proxy_connect_read_timeout"),
223+
ngx_http_proxy_connect_variable_set_time,
224+
ngx_http_proxy_connect_variable_get_time,
225+
offsetof(ngx_http_proxy_connect_ctx_t, read_timeout),
226+
NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_CHANGEABLE, 0 },
227+
228+
{ ngx_string("proxy_connect_send_timeout"),
229+
ngx_http_proxy_connect_variable_set_time,
230+
ngx_http_proxy_connect_variable_get_time,
231+
offsetof(ngx_http_proxy_connect_ctx_t, send_timeout),
232+
NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_CHANGEABLE, 0 },
233+
209234
{ ngx_null_string, NULL, NULL, 0, 0, 0 }
210235
};
211236

@@ -456,6 +481,9 @@ ngx_http_proxy_connect_send_connection_established(ngx_http_request_t *r)
456481
n = c->send(c, b->pos, b->last - b->pos);
457482

458483
if (n >= 0) {
484+
485+
r->headers_out.status = 200; /* fixed that $status is 000 */
486+
459487
b->pos += n;
460488

461489
if (b->pos == b->last) {
@@ -504,7 +532,7 @@ ngx_http_proxy_connect_send_connection_established(ngx_http_request_t *r)
504532
/* n == NGX_AGAIN */
505533
r->write_event_handler = ngx_http_proxy_connect_send_handler;
506534

507-
ngx_add_timer(c->write, clcf->send_timeout);
535+
ngx_add_timer(c->write, ctx->send_timeout);
508536

509537
if (ngx_handle_write_event(c->write, clcf->send_lowat) != NGX_OK) {
510538
ngx_http_proxy_connect_finalize_request(r, u,
@@ -645,7 +673,7 @@ ngx_http_proxy_connect_tunnel(ngx_http_request_t *r,
645673
}
646674

647675
if (upstream->write->active && !upstream->write->ready) {
648-
ngx_add_timer(upstream->write, u->conf->send_timeout);
676+
ngx_add_timer(upstream->write, ctx->send_timeout);
649677

650678
} else if (upstream->write->timer_set) {
651679
ngx_del_timer(upstream->write);
@@ -658,7 +686,7 @@ ngx_http_proxy_connect_tunnel(ngx_http_request_t *r,
658686

659687
if (upstream->read->active && !upstream->read->ready) {
660688
if (from_upstream) {
661-
ngx_add_timer(upstream->read, u->conf->read_timeout);
689+
ngx_add_timer(upstream->read, ctx->read_timeout);
662690
}
663691

664692
} else if (upstream->read->timer_set) {
@@ -907,7 +935,9 @@ ngx_http_proxy_connect_process_connect(ngx_http_request_t *r,
907935
ngx_connection_t *c;
908936
ngx_peer_connection_t *pc;
909937
ngx_http_upstream_resolved_t *ur;
938+
ngx_http_proxy_connect_ctx_t *ctx;
910939

940+
ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_connect_module);
911941

912942
r->connection->log->action = "connecting to upstream(proxy_connect)";
913943

@@ -978,7 +1008,7 @@ ngx_http_proxy_connect_process_connect(ngx_http_request_t *r,
9781008
c->write->log = c->log;
9791009

9801010
if (rc == NGX_AGAIN) {
981-
ngx_add_timer(c->write, u->conf->connect_timeout);
1011+
ngx_add_timer(c->write, ctx->connect_timeout);
9821012
return;
9831013
}
9841014

@@ -1366,17 +1396,7 @@ ngx_http_proxy_connect_handler(ngx_http_request_t *r)
13661396
return NGX_HTTP_FORBIDDEN;
13671397
}
13681398

1369-
ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_proxy_connect_ctx_t));
1370-
if (ctx == NULL) {
1371-
return NGX_ERROR;
1372-
}
1373-
1374-
ctx->buf.pos = (u_char *) NGX_HTTP_PROXY_CONNECT_ESTABLISTHED;
1375-
ctx->buf.last = ctx->buf.pos +
1376-
sizeof(NGX_HTTP_PROXY_CONNECT_ESTABLISTHED) - 1;
1377-
ctx->buf.memory = 1;
1378-
1379-
ngx_http_set_ctx(r, ctx, ngx_http_proxy_connect_module);
1399+
ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_connect_module);;
13801400

13811401
if (ngx_http_proxy_connect_upstream_create(r, ctx) != NGX_OK) {
13821402
return NGX_HTTP_INTERNAL_SERVER_ERROR;
@@ -1957,6 +1977,82 @@ ngx_http_proxy_connect_connect_addr_variable(ngx_http_request_t *r,
19571977
}
19581978

19591979

1980+
static ngx_int_t
1981+
ngx_http_proxy_connect_variable_get_time(ngx_http_request_t *r,
1982+
ngx_http_variable_value_t *v, uintptr_t data)
1983+
{
1984+
u_char *p;
1985+
ngx_msec_t *msp, ms;
1986+
ngx_http_proxy_connect_ctx_t *ctx;
1987+
1988+
if (r->method != NGX_HTTP_CONNECT) {
1989+
return NGX_OK;
1990+
}
1991+
1992+
ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_connect_module);
1993+
1994+
if (ctx == NULL) {
1995+
v->not_found = 1;
1996+
return NGX_OK;
1997+
}
1998+
1999+
msp = (ngx_msec_t *) ((char *) ctx + data);
2000+
ms = *msp;
2001+
2002+
p = ngx_pnalloc(r->pool, NGX_TIME_T_LEN);
2003+
if (p == NULL) {
2004+
return NGX_ERROR;
2005+
}
2006+
2007+
v->len = ngx_sprintf(p, "%M", ms) - p;
2008+
v->valid = 1;
2009+
v->no_cacheable = 0;
2010+
v->not_found = 0;
2011+
v->data = p;
2012+
2013+
return NGX_OK;
2014+
}
2015+
2016+
2017+
static void
2018+
ngx_http_proxy_connect_variable_set_time(ngx_http_request_t *r,
2019+
ngx_http_variable_value_t *v, uintptr_t data)
2020+
{
2021+
ngx_str_t s;
2022+
ngx_msec_t *msp, ms;
2023+
ngx_http_proxy_connect_ctx_t *ctx;
2024+
2025+
if (r->method != NGX_HTTP_CONNECT) {
2026+
return;
2027+
}
2028+
2029+
s.len = v->len;
2030+
s.data = v->data;
2031+
2032+
ms = ngx_parse_time(&s, 0);
2033+
2034+
if (ms == (ngx_msec_t) NGX_ERROR) {
2035+
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
2036+
"[proxy_connect] invalid msec \"%V\" (ctx offset=%ui)", &s, data);
2037+
return;
2038+
}
2039+
2040+
ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_connect_module);
2041+
2042+
if (ctx == NULL) {
2043+
#if 0
2044+
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
2045+
"[proxy_connect] no ctx found");
2046+
#endif
2047+
return;
2048+
}
2049+
2050+
msp = (ngx_msec_t *) ((char *) ctx + data);
2051+
2052+
*msp = ms;
2053+
}
2054+
2055+
19602056
static ngx_int_t
19612057
ngx_http_proxy_connect_add_variables(ngx_conf_t *cf)
19622058
{
@@ -1968,8 +2064,7 @@ ngx_http_proxy_connect_add_variables(ngx_conf_t *cf)
19682064
return NGX_ERROR;
19692065
}
19702066

1971-
var->get_handler = v->get_handler;
1972-
var->data = v->data;
2067+
*var = *v;
19732068
}
19742069

19752070
return NGX_OK;
@@ -1979,14 +2074,36 @@ ngx_http_proxy_connect_add_variables(ngx_conf_t *cf)
19792074
static ngx_int_t
19802075
ngx_http_proxy_connect_post_read_handler(ngx_http_request_t *r)
19812076
{
2077+
ngx_http_proxy_connect_ctx_t *ctx;
19822078
ngx_http_proxy_connect_loc_conf_t *pclcf;
19832079

19842080
pclcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_connect_module);
19852081

1986-
if (r->method == NGX_HTTP_CONNECT && !pclcf->accept_connect) {
1987-
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1988-
"client sent connect method");
1989-
return NGX_HTTP_BAD_REQUEST;
2082+
if (r->method == NGX_HTTP_CONNECT) {
2083+
2084+
if (!pclcf->accept_connect) {
2085+
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
2086+
"client sent connect method");
2087+
return NGX_HTTP_BAD_REQUEST;
2088+
}
2089+
2090+
/* init ctx */
2091+
2092+
ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_proxy_connect_ctx_t));
2093+
if (ctx == NULL) {
2094+
return NGX_ERROR;
2095+
}
2096+
2097+
ctx->buf.pos = (u_char *) NGX_HTTP_PROXY_CONNECT_ESTABLISTHED;
2098+
ctx->buf.last = ctx->buf.pos +
2099+
sizeof(NGX_HTTP_PROXY_CONNECT_ESTABLISTHED) - 1;
2100+
ctx->buf.memory = 1;
2101+
2102+
ctx->connect_timeout = pclcf->connect_timeout;
2103+
ctx->send_timeout = pclcf->send_timeout;
2104+
ctx->read_timeout = pclcf->read_timeout;
2105+
2106+
ngx_http_set_ctx(r, ctx, ngx_http_proxy_connect_module);
19902107
}
19912108

19922109
return NGX_DECLINED;

0 commit comments

Comments
 (0)