@@ -45,6 +45,7 @@ typedef struct {
45
45
typedef struct {
46
46
ngx_msec_t resolve_time ;
47
47
ngx_msec_t connect_time ;
48
+ ngx_msec_t first_byte_time ;
48
49
49
50
/* TODO:
50
51
off_t bytes_received;
@@ -133,6 +134,8 @@ static ngx_int_t ngx_http_proxy_connect_resolve_time_variable(ngx_http_request_t
133
134
ngx_http_variable_value_t * v , uintptr_t data );
134
135
static ngx_int_t ngx_http_proxy_connect_connect_time_variable (ngx_http_request_t * r ,
135
136
ngx_http_variable_value_t * v , uintptr_t data );
137
+ static ngx_int_t ngx_http_proxy_connect_first_byte_time_variable (ngx_http_request_t * r ,
138
+ ngx_http_variable_value_t * v , uintptr_t data );
136
139
static ngx_int_t ngx_http_proxy_connect_variable_get_response (ngx_http_request_t * r ,
137
140
ngx_http_variable_value_t * v , uintptr_t data );
138
141
static void ngx_http_proxy_connect_variable_set_response (ngx_http_request_t * r ,
@@ -277,6 +280,10 @@ static ngx_http_variable_t ngx_http_proxy_connect_vars[] = {
277
280
ngx_http_proxy_connect_connect_time_variable , 0 ,
278
281
NGX_HTTP_VAR_NOCACHEABLE , 0 },
279
282
283
+ { ngx_string ("proxy_connect_first_byte_time" ), NULL ,
284
+ ngx_http_proxy_connect_first_byte_time_variable , 0 ,
285
+ NGX_HTTP_VAR_NOCACHEABLE , 0 },
286
+
280
287
{ ngx_string ("proxy_connect_response" ),
281
288
ngx_http_proxy_connect_variable_set_response ,
282
289
ngx_http_proxy_connect_variable_get_response ,
@@ -722,6 +729,13 @@ ngx_http_proxy_connect_tunnel(ngx_http_request_t *r,
722
729
do_write = 1 ;
723
730
b -> last += n ;
724
731
732
+ if (from_upstream ) {
733
+ if (u -> state .first_byte_time == (ngx_msec_t ) - 1 ) {
734
+ u -> state .first_byte_time = ngx_current_msec
735
+ - u -> start_time ;
736
+ }
737
+ }
738
+
725
739
continue ;
726
740
}
727
741
@@ -1042,6 +1056,7 @@ ngx_http_proxy_connect_process_connect(ngx_http_request_t *r,
1042
1056
1043
1057
u -> start_time = ngx_current_msec ;
1044
1058
u -> state .connect_time = (ngx_msec_t ) - 1 ;
1059
+ u -> state .first_byte_time = (ngx_msec_t ) - 1 ;
1045
1060
1046
1061
rc = ngx_event_connect_peer (& u -> peer );
1047
1062
@@ -2194,6 +2209,63 @@ ngx_http_proxy_connect_connect_time_variable(ngx_http_request_t *r,
2194
2209
}
2195
2210
2196
2211
2212
+ static ngx_int_t
2213
+ ngx_http_proxy_connect_first_byte_time_variable (ngx_http_request_t * r ,
2214
+ ngx_http_variable_value_t * v , uintptr_t data )
2215
+ {
2216
+ u_char * p ;
2217
+ size_t len ;
2218
+ ngx_msec_int_t ms ;
2219
+ ngx_http_proxy_connect_ctx_t * ctx ;
2220
+ ngx_http_proxy_connect_upstream_t * u ;
2221
+
2222
+ if (r -> method != NGX_HTTP_CONNECT ) {
2223
+ return NGX_OK ;
2224
+ }
2225
+
2226
+ v -> valid = 1 ;
2227
+ v -> no_cacheable = 0 ;
2228
+ v -> not_found = 0 ;
2229
+
2230
+ ctx = ngx_http_get_module_ctx (r , ngx_http_proxy_connect_module );
2231
+
2232
+ if (ctx == NULL ) {
2233
+ v -> not_found = 1 ;
2234
+ return NGX_OK ;
2235
+ }
2236
+
2237
+ u = ctx -> u ;
2238
+
2239
+ if (u == NULL || !u -> connected ) {
2240
+ v -> not_found = 1 ;
2241
+ return NGX_OK ;
2242
+ }
2243
+
2244
+ len = NGX_TIME_T_LEN + 4 ;
2245
+
2246
+ p = ngx_pnalloc (r -> pool , len );
2247
+ if (p == NULL ) {
2248
+ return NGX_ERROR ;
2249
+ }
2250
+
2251
+ v -> data = p ;
2252
+
2253
+ ms = u -> state .first_byte_time ;
2254
+
2255
+ if (ms != -1 ) {
2256
+ ms = ngx_max (ms , 0 );
2257
+ p = ngx_sprintf (p , "%T.%03M" , (time_t ) ms / 1000 , ms % 1000 );
2258
+
2259
+ } else {
2260
+ * p ++ = '-' ;
2261
+ }
2262
+
2263
+ v -> len = p - v -> data ;
2264
+
2265
+ return NGX_OK ;
2266
+ }
2267
+
2268
+
2197
2269
static ngx_int_t
2198
2270
ngx_http_proxy_connect_variable_get_response (ngx_http_request_t * r ,
2199
2271
ngx_http_variable_value_t * v , uintptr_t data )
0 commit comments