~ubuntu-branches/ubuntu/trusty/nginx/trusty-proposed

« back to all changes in this revision

Viewing changes to src/http/ngx_http_upstream.c

  • Committer: Package Import Robot
  • Author(s): Kartik Mistry
  • Date: 2013-04-25 12:51:45 UTC
  • mfrom: (1.3.28)
  • mto: (1.3.29) (15.1.2 experimental)
  • mto: This revision was merged to the branch mainline in revision 64.
  • Revision ID: package-import@ubuntu.com-20130425125145-ugl0wor6bq0u5eae
Tags: upstream-1.4.0
ImportĀ upstreamĀ versionĀ 1.4.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
 
2
2
/*
3
3
 * Copyright (C) Igor Sysoev
 
4
 * Copyright (C) Nginx, Inc.
4
5
 */
5
6
 
6
7
 
9
10
#include <ngx_http.h>
10
11
 
11
12
 
 
13
#if (NGX_HTTP_CACHE)
 
14
static ngx_int_t ngx_http_upstream_cache(ngx_http_request_t *r,
 
15
    ngx_http_upstream_t *u);
 
16
static ngx_int_t ngx_http_upstream_cache_send(ngx_http_request_t *r,
 
17
    ngx_http_upstream_t *u);
 
18
static ngx_int_t ngx_http_upstream_cache_status(ngx_http_request_t *r,
 
19
    ngx_http_variable_value_t *v, uintptr_t data);
 
20
#endif
 
21
 
 
22
static void ngx_http_upstream_init_request(ngx_http_request_t *r);
12
23
static void ngx_http_upstream_resolve_handler(ngx_resolver_ctx_t *ctx);
13
24
static void ngx_http_upstream_rd_check_broken_connection(ngx_http_request_t *r);
14
25
static void ngx_http_upstream_wr_check_broken_connection(ngx_http_request_t *r);
20
31
    ngx_http_upstream_t *u);
21
32
static void ngx_http_upstream_send_request(ngx_http_request_t *r,
22
33
    ngx_http_upstream_t *u);
23
 
static void ngx_http_upstream_send_request_handler(ngx_event_t *wev);
24
 
static void ngx_http_upstream_process_header(ngx_event_t *rev);
 
34
static void ngx_http_upstream_send_request_handler(ngx_http_request_t *r,
 
35
    ngx_http_upstream_t *u);
 
36
static void ngx_http_upstream_process_header(ngx_http_request_t *r,
 
37
    ngx_http_upstream_t *u);
 
38
static ngx_int_t ngx_http_upstream_test_next(ngx_http_request_t *r,
 
39
    ngx_http_upstream_t *u);
 
40
static ngx_int_t ngx_http_upstream_intercept_errors(ngx_http_request_t *r,
 
41
    ngx_http_upstream_t *u);
25
42
static ngx_int_t ngx_http_upstream_test_connect(ngx_connection_t *c);
26
 
static void ngx_http_upstream_process_body_in_memory(ngx_event_t *rev);
 
43
static ngx_int_t ngx_http_upstream_process_headers(ngx_http_request_t *r,
 
44
    ngx_http_upstream_t *u);
 
45
static void ngx_http_upstream_process_body_in_memory(ngx_http_request_t *r,
 
46
    ngx_http_upstream_t *u);
27
47
static void ngx_http_upstream_send_response(ngx_http_request_t *r,
28
48
    ngx_http_upstream_t *u);
 
49
static void ngx_http_upstream_upgrade(ngx_http_request_t *r,
 
50
    ngx_http_upstream_t *u);
 
51
static void ngx_http_upstream_upgraded_read_downstream(ngx_http_request_t *r);
 
52
static void ngx_http_upstream_upgraded_write_downstream(ngx_http_request_t *r);
 
53
static void ngx_http_upstream_upgraded_read_upstream(ngx_http_request_t *r,
 
54
    ngx_http_upstream_t *u);
 
55
static void ngx_http_upstream_upgraded_write_upstream(ngx_http_request_t *r,
 
56
    ngx_http_upstream_t *u);
 
57
static void ngx_http_upstream_process_upgraded(ngx_http_request_t *r,
 
58
    ngx_uint_t from_upstream, ngx_uint_t do_write);
29
59
static void
30
60
    ngx_http_upstream_process_non_buffered_downstream(ngx_http_request_t *r);
31
 
static void ngx_http_upstream_process_non_buffered_body(ngx_event_t *ev);
 
61
static void
 
62
    ngx_http_upstream_process_non_buffered_upstream(ngx_http_request_t *r,
 
63
    ngx_http_upstream_t *u);
 
64
static void
 
65
    ngx_http_upstream_process_non_buffered_request(ngx_http_request_t *r,
 
66
    ngx_uint_t do_write);
32
67
static ngx_int_t ngx_http_upstream_non_buffered_filter_init(void *data);
33
68
static ngx_int_t ngx_http_upstream_non_buffered_filter(void *data,
34
69
    ssize_t bytes);
35
70
static void ngx_http_upstream_process_downstream(ngx_http_request_t *r);
36
 
static void ngx_http_upstream_process_body(ngx_event_t *ev);
 
71
static void ngx_http_upstream_process_upstream(ngx_http_request_t *r,
 
72
    ngx_http_upstream_t *u);
 
73
static void ngx_http_upstream_process_request(ngx_http_request_t *r);
37
74
static void ngx_http_upstream_store(ngx_http_request_t *r,
38
75
    ngx_http_upstream_t *u);
39
 
static void ngx_http_upstream_dummy_handler(ngx_event_t *wev);
 
76
static void ngx_http_upstream_dummy_handler(ngx_http_request_t *r,
 
77
    ngx_http_upstream_t *u);
40
78
static void ngx_http_upstream_next(ngx_http_request_t *r,
41
79
    ngx_http_upstream_t *u, ngx_uint_t ft_type);
42
80
static void ngx_http_upstream_cleanup(void *data);
45
83
 
46
84
static ngx_int_t ngx_http_upstream_process_header_line(ngx_http_request_t *r,
47
85
    ngx_table_elt_t *h, ngx_uint_t offset);
 
86
static ngx_int_t ngx_http_upstream_process_content_length(ngx_http_request_t *r,
 
87
    ngx_table_elt_t *h, ngx_uint_t offset);
 
88
static ngx_int_t ngx_http_upstream_process_set_cookie(ngx_http_request_t *r,
 
89
    ngx_table_elt_t *h, ngx_uint_t offset);
48
90
static ngx_int_t
49
 
    ngx_http_upstream_process_multi_header_lines(ngx_http_request_t *r,
 
91
    ngx_http_upstream_process_cache_control(ngx_http_request_t *r,
50
92
    ngx_table_elt_t *h, ngx_uint_t offset);
51
93
static ngx_int_t ngx_http_upstream_ignore_header_line(ngx_http_request_t *r,
52
94
    ngx_table_elt_t *h, ngx_uint_t offset);
 
95
static ngx_int_t ngx_http_upstream_process_expires(ngx_http_request_t *r,
 
96
    ngx_table_elt_t *h, ngx_uint_t offset);
 
97
static ngx_int_t ngx_http_upstream_process_accel_expires(ngx_http_request_t *r,
 
98
    ngx_table_elt_t *h, ngx_uint_t offset);
53
99
static ngx_int_t ngx_http_upstream_process_limit_rate(ngx_http_request_t *r,
54
100
    ngx_table_elt_t *h, ngx_uint_t offset);
55
101
static ngx_int_t ngx_http_upstream_process_buffering(ngx_http_request_t *r,
56
102
    ngx_table_elt_t *h, ngx_uint_t offset);
57
103
static ngx_int_t ngx_http_upstream_process_charset(ngx_http_request_t *r,
58
104
    ngx_table_elt_t *h, ngx_uint_t offset);
 
105
static ngx_int_t ngx_http_upstream_process_connection(ngx_http_request_t *r,
 
106
    ngx_table_elt_t *h, ngx_uint_t offset);
 
107
static ngx_int_t
 
108
    ngx_http_upstream_process_transfer_encoding(ngx_http_request_t *r,
 
109
    ngx_table_elt_t *h, ngx_uint_t offset);
59
110
static ngx_int_t ngx_http_upstream_copy_header_line(ngx_http_request_t *r,
60
111
    ngx_table_elt_t *h, ngx_uint_t offset);
61
112
static ngx_int_t
63
114
    ngx_table_elt_t *h, ngx_uint_t offset);
64
115
static ngx_int_t ngx_http_upstream_copy_content_type(ngx_http_request_t *r,
65
116
    ngx_table_elt_t *h, ngx_uint_t offset);
66
 
static ngx_int_t ngx_http_upstream_copy_content_length(ngx_http_request_t *r,
 
117
static ngx_int_t ngx_http_upstream_copy_last_modified(ngx_http_request_t *r,
67
118
    ngx_table_elt_t *h, ngx_uint_t offset);
68
119
static ngx_int_t ngx_http_upstream_rewrite_location(ngx_http_request_t *r,
69
120
    ngx_table_elt_t *h, ngx_uint_t offset);
70
121
static ngx_int_t ngx_http_upstream_rewrite_refresh(ngx_http_request_t *r,
71
122
    ngx_table_elt_t *h, ngx_uint_t offset);
 
123
static ngx_int_t ngx_http_upstream_rewrite_set_cookie(ngx_http_request_t *r,
 
124
    ngx_table_elt_t *h, ngx_uint_t offset);
 
125
static ngx_int_t ngx_http_upstream_copy_allow_ranges(ngx_http_request_t *r,
 
126
    ngx_table_elt_t *h, ngx_uint_t offset);
 
127
 
72
128
#if (NGX_HTTP_GZIP)
73
129
static ngx_int_t ngx_http_upstream_copy_content_encoding(ngx_http_request_t *r,
74
130
    ngx_table_elt_t *h, ngx_uint_t offset);
81
137
    ngx_http_variable_value_t *v, uintptr_t data);
82
138
static ngx_int_t ngx_http_upstream_response_time_variable(ngx_http_request_t *r,
83
139
    ngx_http_variable_value_t *v, uintptr_t data);
 
140
static ngx_int_t ngx_http_upstream_response_length_variable(
 
141
    ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data);
84
142
 
85
143
static char *ngx_http_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy);
86
144
static char *ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd,
87
145
    void *conf);
88
146
 
 
147
static ngx_addr_t *ngx_http_upstream_get_local(ngx_http_request_t *r,
 
148
    ngx_http_upstream_local_t *local);
 
149
 
89
150
static void *ngx_http_upstream_create_main_conf(ngx_conf_t *cf);
90
151
static char *ngx_http_upstream_init_main_conf(ngx_conf_t *cf, void *conf);
91
152
 
109
170
                 ngx_http_upstream_copy_content_type, 0, 1 },
110
171
 
111
172
    { ngx_string("Content-Length"),
112
 
                 ngx_http_upstream_process_header_line,
 
173
                 ngx_http_upstream_process_content_length,
113
174
                 offsetof(ngx_http_upstream_headers_in_t, content_length),
114
 
                 ngx_http_upstream_copy_content_length, 0, 0 },
 
175
                 ngx_http_upstream_ignore_header_line, 0, 0 },
115
176
 
116
177
    { ngx_string("Date"),
117
178
                 ngx_http_upstream_process_header_line,
122
183
    { ngx_string("Last-Modified"),
123
184
                 ngx_http_upstream_process_header_line,
124
185
                 offsetof(ngx_http_upstream_headers_in_t, last_modified),
 
186
                 ngx_http_upstream_copy_last_modified, 0, 0 },
 
187
 
 
188
    { ngx_string("ETag"),
 
189
                 ngx_http_upstream_process_header_line,
 
190
                 offsetof(ngx_http_upstream_headers_in_t, etag),
125
191
                 ngx_http_upstream_copy_header_line,
126
 
                 offsetof(ngx_http_headers_out_t, last_modified), 0 },
 
192
                 offsetof(ngx_http_headers_out_t, etag), 0 },
127
193
 
128
194
    { ngx_string("Server"),
129
195
                 ngx_http_upstream_process_header_line,
146
212
                 ngx_http_upstream_rewrite_refresh, 0, 0 },
147
213
 
148
214
    { ngx_string("Set-Cookie"),
149
 
                 ngx_http_upstream_ignore_header_line, 0,
150
 
                 ngx_http_upstream_copy_header_line, 0, 1 },
 
215
                 ngx_http_upstream_process_set_cookie, 0,
 
216
                 ngx_http_upstream_rewrite_set_cookie, 0, 1 },
151
217
 
152
218
    { ngx_string("Content-Disposition"),
153
219
                 ngx_http_upstream_ignore_header_line, 0,
154
220
                 ngx_http_upstream_copy_header_line, 0, 1 },
155
221
 
156
222
    { ngx_string("Cache-Control"),
157
 
                 ngx_http_upstream_process_multi_header_lines,
158
 
                 offsetof(ngx_http_upstream_headers_in_t, cache_control),
 
223
                 ngx_http_upstream_process_cache_control, 0,
159
224
                 ngx_http_upstream_copy_multi_header_lines,
160
225
                 offsetof(ngx_http_headers_out_t, cache_control), 1 },
161
226
 
162
227
    { ngx_string("Expires"),
163
 
                 ngx_http_upstream_process_header_line,
164
 
                 offsetof(ngx_http_upstream_headers_in_t, expires),
 
228
                 ngx_http_upstream_process_expires, 0,
165
229
                 ngx_http_upstream_copy_header_line,
166
230
                 offsetof(ngx_http_headers_out_t, expires), 1 },
167
231
 
168
232
    { ngx_string("Accept-Ranges"),
169
233
                 ngx_http_upstream_process_header_line,
170
234
                 offsetof(ngx_http_upstream_headers_in_t, accept_ranges),
171
 
                 ngx_http_upstream_copy_header_line,
 
235
                 ngx_http_upstream_copy_allow_ranges,
172
236
                 offsetof(ngx_http_headers_out_t, accept_ranges), 1 },
173
237
 
174
238
    { ngx_string("Connection"),
175
 
                 ngx_http_upstream_ignore_header_line, 0,
 
239
                 ngx_http_upstream_process_connection, 0,
176
240
                 ngx_http_upstream_ignore_header_line, 0, 0 },
177
241
 
178
242
    { ngx_string("Keep-Alive"),
184
248
                 ngx_http_upstream_copy_header_line, 0, 0 },
185
249
 
186
250
    { ngx_string("X-Accel-Expires"),
187
 
                 ngx_http_upstream_process_header_line,
188
 
                 offsetof(ngx_http_upstream_headers_in_t, x_accel_expires),
 
251
                 ngx_http_upstream_process_accel_expires, 0,
189
252
                 ngx_http_upstream_copy_header_line, 0, 0 },
190
253
 
191
254
    { ngx_string("X-Accel-Redirect"),
192
255
                 ngx_http_upstream_process_header_line,
193
256
                 offsetof(ngx_http_upstream_headers_in_t, x_accel_redirect),
194
 
                 ngx_http_upstream_ignore_header_line, 0, 0 },
 
257
                 ngx_http_upstream_copy_header_line, 0, 0 },
195
258
 
196
259
    { ngx_string("X-Accel-Limit-Rate"),
197
260
                 ngx_http_upstream_process_limit_rate, 0,
198
 
                 ngx_http_upstream_ignore_header_line, 0, 0 },
 
261
                 ngx_http_upstream_copy_header_line, 0, 0 },
199
262
 
200
263
    { ngx_string("X-Accel-Buffering"),
201
264
                 ngx_http_upstream_process_buffering, 0,
202
 
                 ngx_http_upstream_ignore_header_line, 0, 0 },
 
265
                 ngx_http_upstream_copy_header_line, 0, 0 },
203
266
 
204
267
    { ngx_string("X-Accel-Charset"),
205
268
                 ngx_http_upstream_process_charset, 0,
 
269
                 ngx_http_upstream_copy_header_line, 0, 0 },
 
270
 
 
271
    { ngx_string("Transfer-Encoding"),
 
272
                 ngx_http_upstream_process_transfer_encoding, 0,
206
273
                 ngx_http_upstream_ignore_header_line, 0, 0 },
207
274
 
208
275
#if (NGX_HTTP_GZIP)
270
337
static ngx_http_variable_t  ngx_http_upstream_vars[] = {
271
338
 
272
339
    { ngx_string("upstream_addr"), NULL,
273
 
      ngx_http_upstream_addr_variable, 0, NGX_HTTP_VAR_NOHASH, 0 },
 
340
      ngx_http_upstream_addr_variable, 0,
 
341
      NGX_HTTP_VAR_NOCACHEABLE, 0 },
274
342
 
275
343
    { ngx_string("upstream_status"), NULL,
276
 
      ngx_http_upstream_status_variable, 0, NGX_HTTP_VAR_NOHASH, 0 },
 
344
      ngx_http_upstream_status_variable, 0,
 
345
      NGX_HTTP_VAR_NOCACHEABLE, 0 },
277
346
 
278
347
    { ngx_string("upstream_response_time"), NULL,
279
 
      ngx_http_upstream_response_time_variable, 0, NGX_HTTP_VAR_NOHASH, 0 },
 
348
      ngx_http_upstream_response_time_variable, 0,
 
349
      NGX_HTTP_VAR_NOCACHEABLE, 0 },
 
350
 
 
351
    { ngx_string("upstream_response_length"), NULL,
 
352
      ngx_http_upstream_response_length_variable, 0,
 
353
      NGX_HTTP_VAR_NOCACHEABLE, 0 },
 
354
 
 
355
#if (NGX_HTTP_CACHE)
 
356
 
 
357
    { ngx_string("upstream_cache_status"), NULL,
 
358
      ngx_http_upstream_cache_status, 0,
 
359
      NGX_HTTP_VAR_NOCACHEABLE, 0 },
 
360
 
 
361
#endif
280
362
 
281
363
    { ngx_null_string, NULL, NULL, 0, 0, 0 }
282
364
};
283
365
 
284
366
 
 
367
static ngx_http_upstream_next_t  ngx_http_upstream_next_errors[] = {
 
368
    { 500, NGX_HTTP_UPSTREAM_FT_HTTP_500 },
 
369
    { 502, NGX_HTTP_UPSTREAM_FT_HTTP_502 },
 
370
    { 503, NGX_HTTP_UPSTREAM_FT_HTTP_503 },
 
371
    { 504, NGX_HTTP_UPSTREAM_FT_HTTP_504 },
 
372
    { 404, NGX_HTTP_UPSTREAM_FT_HTTP_404 },
 
373
    { 0, 0 }
 
374
};
 
375
 
 
376
 
 
377
ngx_conf_bitmask_t  ngx_http_upstream_cache_method_mask[] = {
 
378
   { ngx_string("GET"),  NGX_HTTP_GET},
 
379
   { ngx_string("HEAD"), NGX_HTTP_HEAD },
 
380
   { ngx_string("POST"), NGX_HTTP_POST },
 
381
   { ngx_null_string, 0 }
 
382
};
 
383
 
 
384
 
 
385
ngx_conf_bitmask_t  ngx_http_upstream_ignore_headers_masks[] = {
 
386
    { ngx_string("X-Accel-Redirect"), NGX_HTTP_UPSTREAM_IGN_XA_REDIRECT },
 
387
    { ngx_string("X-Accel-Expires"), NGX_HTTP_UPSTREAM_IGN_XA_EXPIRES },
 
388
    { ngx_string("X-Accel-Limit-Rate"), NGX_HTTP_UPSTREAM_IGN_XA_LIMIT_RATE },
 
389
    { ngx_string("X-Accel-Buffering"), NGX_HTTP_UPSTREAM_IGN_XA_BUFFERING },
 
390
    { ngx_string("X-Accel-Charset"), NGX_HTTP_UPSTREAM_IGN_XA_CHARSET },
 
391
    { ngx_string("Expires"), NGX_HTTP_UPSTREAM_IGN_EXPIRES },
 
392
    { ngx_string("Cache-Control"), NGX_HTTP_UPSTREAM_IGN_CACHE_CONTROL },
 
393
    { ngx_string("Set-Cookie"), NGX_HTTP_UPSTREAM_IGN_SET_COOKIE },
 
394
    { ngx_null_string, 0 }
 
395
};
 
396
 
 
397
 
 
398
ngx_int_t
 
399
ngx_http_upstream_create(ngx_http_request_t *r)
 
400
{
 
401
    ngx_http_upstream_t  *u;
 
402
 
 
403
    u = r->upstream;
 
404
 
 
405
    if (u && u->cleanup) {
 
406
        r->main->count++;
 
407
        ngx_http_upstream_cleanup(r);
 
408
    }
 
409
 
 
410
    u = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_t));
 
411
    if (u == NULL) {
 
412
        return NGX_ERROR;
 
413
    }
 
414
 
 
415
    r->upstream = u;
 
416
 
 
417
    u->peer.log = r->connection->log;
 
418
    u->peer.log_error = NGX_ERROR_ERR;
 
419
#if (NGX_THREADS)
 
420
    u->peer.lock = &r->connection->lock;
 
421
#endif
 
422
 
 
423
#if (NGX_HTTP_CACHE)
 
424
    r->cache = NULL;
 
425
#endif
 
426
 
 
427
    u->headers_in.content_length_n = -1;
 
428
 
 
429
    return NGX_OK;
 
430
}
 
431
 
 
432
 
285
433
void
286
434
ngx_http_upstream_init(ngx_http_request_t *r)
287
435
{
288
 
    ngx_str_t                      *host;
289
 
    ngx_uint_t                      i;
290
 
    ngx_connection_t               *c;
291
 
    ngx_resolver_ctx_t             *ctx, temp;
292
 
    ngx_http_cleanup_t             *cln;
293
 
    ngx_http_upstream_t            *u;
294
 
    ngx_http_core_loc_conf_t       *clcf;
295
 
    ngx_http_upstream_srv_conf_t   *uscf, **uscfp;
296
 
    ngx_http_upstream_main_conf_t  *umcf;
 
436
    ngx_connection_t     *c;
297
437
 
298
438
    c = r->connection;
299
439
 
300
440
    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
301
441
                   "http init upstream, client timer: %d", c->read->timer_set);
302
442
 
 
443
#if (NGX_HTTP_SPDY)
 
444
    if (r->spdy_stream) {
 
445
        ngx_http_upstream_init_request(r);
 
446
        return;
 
447
    }
 
448
#endif
 
449
 
303
450
    if (c->read->timer_set) {
304
451
        ngx_del_timer(c->read);
305
452
    }
306
453
 
307
 
    u = r->upstream;
308
 
 
309
 
    if (!r->post_action && !u->conf->ignore_client_abort) {
310
 
        r->read_event_handler = ngx_http_upstream_rd_check_broken_connection;
311
 
        r->write_event_handler = ngx_http_upstream_wr_check_broken_connection;
312
 
    }
313
 
 
314
454
    if (ngx_event_flags & NGX_USE_CLEAR_EVENT) {
315
455
 
316
456
        if (!c->write->active) {
323
463
        }
324
464
    }
325
465
 
 
466
    ngx_http_upstream_init_request(r);
 
467
}
 
468
 
 
469
 
 
470
static void
 
471
ngx_http_upstream_init_request(ngx_http_request_t *r)
 
472
{
 
473
    ngx_str_t                      *host;
 
474
    ngx_uint_t                      i;
 
475
    ngx_resolver_ctx_t             *ctx, temp;
 
476
    ngx_http_cleanup_t             *cln;
 
477
    ngx_http_upstream_t            *u;
 
478
    ngx_http_core_loc_conf_t       *clcf;
 
479
    ngx_http_upstream_srv_conf_t   *uscf, **uscfp;
 
480
    ngx_http_upstream_main_conf_t  *umcf;
 
481
 
 
482
    if (r->aio) {
 
483
        return;
 
484
    }
 
485
 
 
486
    u = r->upstream;
 
487
 
 
488
#if (NGX_HTTP_CACHE)
 
489
 
 
490
    if (u->conf->cache) {
 
491
        ngx_int_t  rc;
 
492
 
 
493
        rc = ngx_http_upstream_cache(r, u);
 
494
 
 
495
        if (rc == NGX_BUSY) {
 
496
            r->write_event_handler = ngx_http_upstream_init_request;
 
497
            return;
 
498
        }
 
499
 
 
500
        r->write_event_handler = ngx_http_request_empty_handler;
 
501
 
 
502
        if (rc == NGX_DONE) {
 
503
            return;
 
504
        }
 
505
 
 
506
        if (rc != NGX_DECLINED) {
 
507
            ngx_http_finalize_request(r, rc);
 
508
            return;
 
509
        }
 
510
    }
 
511
 
 
512
#endif
 
513
 
 
514
    u->store = (u->conf->store || u->conf->store_lengths);
 
515
 
 
516
    if (!u->store && !r->post_action && !u->conf->ignore_client_abort) {
 
517
        r->read_event_handler = ngx_http_upstream_rd_check_broken_connection;
 
518
        r->write_event_handler = ngx_http_upstream_wr_check_broken_connection;
 
519
    }
 
520
 
326
521
    if (r->request_body) {
327
522
        u->request_bufs = r->request_body->bufs;
328
523
    }
332
527
        return;
333
528
    }
334
529
 
 
530
    u->peer.local = ngx_http_upstream_get_local(r, u->conf->local);
 
531
 
335
532
    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
336
533
 
 
534
    u->output.alignment = clcf->directio_alignment;
337
535
    u->output.pool = r->pool;
338
536
    u->output.bufs.num = 1;
339
537
    u->output.bufs.size = clcf->client_body_buffer_size;
373
571
    cln->data = r;
374
572
    u->cleanup = &cln->handler;
375
573
 
376
 
    u->store = (u->conf->store || u->conf->store_lengths);
377
 
 
378
574
    if (u->resolved == NULL) {
379
575
 
380
576
        uscf = u->conf->upstream;
381
577
 
382
578
    } else {
383
579
 
 
580
        if (u->resolved->sockaddr) {
 
581
 
 
582
            if (ngx_http_upstream_create_round_robin_peer(r, u->resolved)
 
583
                != NGX_OK)
 
584
            {
 
585
                ngx_http_upstream_finalize_request(r, u,
 
586
                                               NGX_HTTP_INTERNAL_SERVER_ERROR);
 
587
                return;
 
588
            }
 
589
 
 
590
            ngx_http_upstream_connect(r, u);
 
591
 
 
592
            return;
 
593
        }
 
594
 
384
595
        host = &u->resolved->host;
385
596
 
386
597
        umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);
392
603
            uscf = uscfp[i];
393
604
 
394
605
            if (uscf->host.len == host->len
395
 
                && ((uscf->port == 0 && u->resolved->default_port)
 
606
                && ((uscf->port == 0 && u->resolved->no_port)
396
607
                     || uscf->port == u->resolved->port)
397
608
                && ngx_memcmp(uscf->host.data, host->data, host->len) == 0)
398
609
            {
400
611
            }
401
612
        }
402
613
 
 
614
        if (u->resolved->port == 0) {
 
615
            ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
 
616
                          "no port in upstream \"%V\"", host);
 
617
            ngx_http_upstream_finalize_request(r, u,
 
618
                                               NGX_HTTP_INTERNAL_SERVER_ERROR);
 
619
            return;
 
620
        }
 
621
 
403
622
        temp.name = *host;
404
623
 
405
624
        ctx = ngx_resolve_start(clcf->resolver, &temp);
406
625
        if (ctx == NULL) {
407
 
            ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
 
626
            ngx_http_upstream_finalize_request(r, u,
 
627
                                               NGX_HTTP_INTERNAL_SERVER_ERROR);
408
628
            return;
409
629
        }
410
630
 
411
631
        if (ctx == NGX_NO_RESOLVER) {
412
 
            ngx_log_error(NGX_LOG_ERR, c->log, 0,
 
632
            ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
413
633
                          "no resolver defined to resolve %V", host);
414
634
 
415
 
            ngx_http_finalize_request(r, NGX_HTTP_BAD_GATEWAY);
 
635
            ngx_http_upstream_finalize_request(r, u, NGX_HTTP_BAD_GATEWAY);
416
636
            return;
417
637
        }
418
638
 
426
646
 
427
647
        if (ngx_resolve_name(ctx) != NGX_OK) {
428
648
            u->resolved->ctx = NULL;
429
 
            ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
 
649
            ngx_http_upstream_finalize_request(r, u,
 
650
                                               NGX_HTTP_INTERNAL_SERVER_ERROR);
430
651
            return;
431
652
        }
432
653
 
435
656
 
436
657
found:
437
658
 
 
659
    if (uscf == NULL) {
 
660
        ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
 
661
                      "no upstream configuration");
 
662
        ngx_http_upstream_finalize_request(r, u,
 
663
                                           NGX_HTTP_INTERNAL_SERVER_ERROR);
 
664
        return;
 
665
    }
 
666
 
438
667
    if (uscf->peer.init(r, uscf) != NGX_OK) {
439
 
        ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
 
668
        ngx_http_upstream_finalize_request(r, u,
 
669
                                           NGX_HTTP_INTERNAL_SERVER_ERROR);
440
670
        return;
441
671
    }
442
672
 
444
674
}
445
675
 
446
676
 
 
677
#if (NGX_HTTP_CACHE)
 
678
 
 
679
static ngx_int_t
 
680
ngx_http_upstream_cache(ngx_http_request_t *r, ngx_http_upstream_t *u)
 
681
{
 
682
    ngx_int_t          rc;
 
683
    ngx_http_cache_t  *c;
 
684
 
 
685
    c = r->cache;
 
686
 
 
687
    if (c == NULL) {
 
688
 
 
689
        if (!(r->method & u->conf->cache_methods)) {
 
690
            return NGX_DECLINED;
 
691
        }
 
692
 
 
693
        if (r->method & NGX_HTTP_HEAD) {
 
694
            u->method = ngx_http_core_get_method;
 
695
        }
 
696
 
 
697
        if (ngx_http_file_cache_new(r) != NGX_OK) {
 
698
            return NGX_ERROR;
 
699
        }
 
700
 
 
701
        if (u->create_key(r) != NGX_OK) {
 
702
            return NGX_ERROR;
 
703
        }
 
704
 
 
705
        /* TODO: add keys */
 
706
 
 
707
        ngx_http_file_cache_create_key(r);
 
708
 
 
709
        if (r->cache->header_start + 256 >= u->conf->buffer_size) {
 
710
            ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
 
711
                          "%V_buffer_size %uz is not enough for cache key, "
 
712
                          "it should increased at least to %uz",
 
713
                          &u->conf->module, u->conf->buffer_size,
 
714
                          ngx_align(r->cache->header_start + 256, 1024));
 
715
 
 
716
            r->cache = NULL;
 
717
            return NGX_DECLINED;
 
718
        }
 
719
 
 
720
        u->cacheable = 1;
 
721
 
 
722
        switch (ngx_http_test_predicates(r, u->conf->cache_bypass)) {
 
723
 
 
724
        case NGX_ERROR:
 
725
            return NGX_ERROR;
 
726
 
 
727
        case NGX_DECLINED:
 
728
            u->cache_status = NGX_HTTP_CACHE_BYPASS;
 
729
            return NGX_DECLINED;
 
730
 
 
731
        default: /* NGX_OK */
 
732
            break;
 
733
        }
 
734
 
 
735
        c = r->cache;
 
736
 
 
737
        c->min_uses = u->conf->cache_min_uses;
 
738
        c->body_start = u->conf->buffer_size;
 
739
        c->file_cache = u->conf->cache->data;
 
740
 
 
741
        c->lock = u->conf->cache_lock;
 
742
        c->lock_timeout = u->conf->cache_lock_timeout;
 
743
 
 
744
        u->cache_status = NGX_HTTP_CACHE_MISS;
 
745
    }
 
746
 
 
747
    rc = ngx_http_file_cache_open(r);
 
748
 
 
749
    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
 
750
                   "http upstream cache: %i", rc);
 
751
 
 
752
    switch (rc) {
 
753
 
 
754
    case NGX_HTTP_CACHE_UPDATING:
 
755
 
 
756
        if (u->conf->cache_use_stale & NGX_HTTP_UPSTREAM_FT_UPDATING) {
 
757
            u->cache_status = rc;
 
758
            rc = NGX_OK;
 
759
 
 
760
        } else {
 
761
            rc = NGX_HTTP_CACHE_STALE;
 
762
        }
 
763
 
 
764
        break;
 
765
 
 
766
    case NGX_OK:
 
767
        u->cache_status = NGX_HTTP_CACHE_HIT;
 
768
    }
 
769
 
 
770
    switch (rc) {
 
771
 
 
772
    case NGX_OK:
 
773
 
 
774
        rc = ngx_http_upstream_cache_send(r, u);
 
775
 
 
776
        if (rc != NGX_HTTP_UPSTREAM_INVALID_HEADER) {
 
777
            return rc;
 
778
        }
 
779
 
 
780
        break;
 
781
 
 
782
    case NGX_HTTP_CACHE_STALE:
 
783
 
 
784
        c->valid_sec = 0;
 
785
        u->buffer.start = NULL;
 
786
        u->cache_status = NGX_HTTP_CACHE_EXPIRED;
 
787
 
 
788
        break;
 
789
 
 
790
    case NGX_DECLINED:
 
791
 
 
792
        if ((size_t) (u->buffer.end - u->buffer.start) < u->conf->buffer_size) {
 
793
            u->buffer.start = NULL;
 
794
 
 
795
        } else {
 
796
            u->buffer.pos = u->buffer.start + c->header_start;
 
797
            u->buffer.last = u->buffer.pos;
 
798
        }
 
799
 
 
800
        break;
 
801
 
 
802
    case NGX_HTTP_CACHE_SCARCE:
 
803
 
 
804
        u->cacheable = 0;
 
805
 
 
806
        break;
 
807
 
 
808
    case NGX_AGAIN:
 
809
 
 
810
        return NGX_BUSY;
 
811
 
 
812
    case NGX_ERROR:
 
813
 
 
814
        return NGX_ERROR;
 
815
 
 
816
    default:
 
817
 
 
818
        /* cached NGX_HTTP_BAD_GATEWAY, NGX_HTTP_GATEWAY_TIME_OUT, etc. */
 
819
 
 
820
        u->cache_status = NGX_HTTP_CACHE_HIT;
 
821
 
 
822
        return rc;
 
823
    }
 
824
 
 
825
    r->cached = 0;
 
826
 
 
827
    return NGX_DECLINED;
 
828
}
 
829
 
 
830
 
 
831
static ngx_int_t
 
832
ngx_http_upstream_cache_send(ngx_http_request_t *r, ngx_http_upstream_t *u)
 
833
{
 
834
    ngx_int_t          rc;
 
835
    ngx_http_cache_t  *c;
 
836
 
 
837
    r->cached = 1;
 
838
    c = r->cache;
 
839
 
 
840
    if (c->header_start == c->body_start) {
 
841
        r->http_version = NGX_HTTP_VERSION_9;
 
842
        return ngx_http_cache_send(r);
 
843
    }
 
844
 
 
845
    /* TODO: cache stack */
 
846
 
 
847
    u->buffer = *c->buf;
 
848
    u->buffer.pos += c->header_start;
 
849
 
 
850
    ngx_memzero(&u->headers_in, sizeof(ngx_http_upstream_headers_in_t));
 
851
    u->headers_in.content_length_n = -1;
 
852
 
 
853
    if (ngx_list_init(&u->headers_in.headers, r->pool, 8,
 
854
                      sizeof(ngx_table_elt_t))
 
855
        != NGX_OK)
 
856
    {
 
857
        return NGX_ERROR;
 
858
    }
 
859
 
 
860
    rc = u->process_header(r);
 
861
 
 
862
    if (rc == NGX_OK) {
 
863
 
 
864
        if (ngx_http_upstream_process_headers(r, u) != NGX_OK) {
 
865
            return NGX_DONE;
 
866
        }
 
867
 
 
868
        return ngx_http_cache_send(r);
 
869
    }
 
870
 
 
871
    if (rc == NGX_ERROR) {
 
872
        return NGX_ERROR;
 
873
    }
 
874
 
 
875
    /* rc == NGX_HTTP_UPSTREAM_INVALID_HEADER */
 
876
 
 
877
    /* TODO: delete file */
 
878
 
 
879
    return rc;
 
880
}
 
881
 
 
882
#endif
 
883
 
 
884
 
447
885
static void
448
886
ngx_http_upstream_resolve_handler(ngx_resolver_ctx_t *ctx)
449
887
{
 
888
    ngx_connection_t              *c;
450
889
    ngx_http_request_t            *r;
 
890
    ngx_http_upstream_t           *u;
451
891
    ngx_http_upstream_resolved_t  *ur;
452
892
 
453
893
    r = ctx->data;
 
894
    c = r->connection;
454
895
 
455
 
    r->upstream->resolved->ctx = NULL;
 
896
    u = r->upstream;
 
897
    ur = u->resolved;
456
898
 
457
899
    if (ctx->state) {
458
900
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
460
902
                      &ctx->name, ctx->state,
461
903
                      ngx_resolver_strerror(ctx->state));
462
904
 
463
 
        ngx_resolve_name_done(ctx);
464
 
        ngx_http_finalize_request(r, NGX_HTTP_BAD_GATEWAY);
465
 
        return;
 
905
        ngx_http_upstream_finalize_request(r, u, NGX_HTTP_BAD_GATEWAY);
 
906
        goto failed;
466
907
    }
467
908
 
468
 
    ur = r->upstream->resolved;
469
909
    ur->naddrs = ctx->naddrs;
470
910
    ur->addrs = ctx->addrs;
471
911
 
486
926
#endif
487
927
 
488
928
    if (ngx_http_upstream_create_round_robin_peer(r, ur) != NGX_OK) {
489
 
        ngx_resolve_name_done(ctx);
490
 
        ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
491
 
        return;
 
929
        ngx_http_upstream_finalize_request(r, u,
 
930
                                           NGX_HTTP_INTERNAL_SERVER_ERROR);
 
931
        goto failed;
492
932
    }
493
933
 
494
934
    ngx_resolve_name_done(ctx);
495
 
 
496
 
    ngx_http_upstream_connect(r, r->upstream);
 
935
    ur->ctx = NULL;
 
936
 
 
937
    ngx_http_upstream_connect(r, u);
 
938
 
 
939
failed:
 
940
 
 
941
    ngx_http_run_posted_requests(c);
 
942
}
 
943
 
 
944
 
 
945
static void
 
946
ngx_http_upstream_handler(ngx_event_t *ev)
 
947
{
 
948
    ngx_connection_t     *c;
 
949
    ngx_http_request_t   *r;
 
950
    ngx_http_log_ctx_t   *ctx;
 
951
    ngx_http_upstream_t  *u;
 
952
 
 
953
    c = ev->data;
 
954
    r = c->data;
 
955
 
 
956
    u = r->upstream;
 
957
    c = r->connection;
 
958
 
 
959
    ctx = c->log->data;
 
960
    ctx->current_request = r;
 
961
 
 
962
    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
 
963
                   "http upstream request: \"%V?%V\"", &r->uri, &r->args);
 
964
 
 
965
    if (ev->write) {
 
966
        u->write_event_handler(r, u);
 
967
 
 
968
    } else {
 
969
        u->read_event_handler(r, u);
 
970
    }
 
971
 
 
972
    ngx_http_run_posted_requests(c);
497
973
}
498
974
 
499
975
 
518
994
    int                  n;
519
995
    char                 buf[1];
520
996
    ngx_err_t            err;
 
997
    ngx_int_t            event;
521
998
    ngx_connection_t     *c;
522
999
    ngx_http_upstream_t  *u;
523
1000
 
529
1006
    u = r->upstream;
530
1007
 
531
1008
    if (c->error) {
532
 
        ngx_http_upstream_finalize_request(r, u,
533
 
                                           NGX_HTTP_CLIENT_CLOSED_REQUEST);
534
 
        return;
535
 
    }
536
 
 
537
 
    if (u->peer.connection == NULL) {
538
 
        return;
539
 
    }
 
1009
        if ((ngx_event_flags & NGX_USE_LEVEL_EVENT) && ev->active) {
 
1010
 
 
1011
            event = ev->write ? NGX_WRITE_EVENT : NGX_READ_EVENT;
 
1012
 
 
1013
            if (ngx_del_event(ev, event, 0) != NGX_OK) {
 
1014
                ngx_http_upstream_finalize_request(r, u,
 
1015
                                               NGX_HTTP_INTERNAL_SERVER_ERROR);
 
1016
                return;
 
1017
            }
 
1018
        }
 
1019
 
 
1020
        if (!u->cacheable) {
 
1021
            ngx_http_upstream_finalize_request(r, u,
 
1022
                                               NGX_HTTP_CLIENT_CLOSED_REQUEST);
 
1023
        }
 
1024
 
 
1025
        return;
 
1026
    }
 
1027
 
 
1028
#if (NGX_HTTP_SPDY)
 
1029
    if (r->spdy_stream) {
 
1030
        return;
 
1031
    }
 
1032
#endif
540
1033
 
541
1034
#if (NGX_HAVE_KQUEUE)
542
1035
 
553
1046
            ev->error = 1;
554
1047
        }
555
1048
 
556
 
        if (!u->cacheable && !u->store && u->peer.connection) {
 
1049
        if (!u->cacheable && u->peer.connection) {
557
1050
            ngx_log_error(NGX_LOG_INFO, ev->log, ev->kq_errno,
558
 
                          "kevent() reported that client closed prematurely "
 
1051
                          "kevent() reported that client prematurely closed "
559
1052
                          "connection, so upstream connection is closed too");
560
1053
            ngx_http_upstream_finalize_request(r, u,
561
1054
                                               NGX_HTTP_CLIENT_CLOSED_REQUEST);
563
1056
        }
564
1057
 
565
1058
        ngx_log_error(NGX_LOG_INFO, ev->log, ev->kq_errno,
566
 
                      "kevent() reported that client closed "
567
 
                      "prematurely connection");
 
1059
                      "kevent() reported that client prematurely closed "
 
1060
                      "connection");
568
1061
 
569
1062
        if (u->peer.connection == NULL) {
570
1063
            ngx_http_upstream_finalize_request(r, u,
571
1064
                                               NGX_HTTP_CLIENT_CLOSED_REQUEST);
572
 
            return;
573
1065
        }
574
1066
 
575
1067
        return;
584
1076
    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ev->log, err,
585
1077
                   "http upstream recv(): %d", n);
586
1078
 
587
 
    /*
588
 
     * we do not need to disable the write event because
589
 
     * that event has NGX_USE_CLEAR_EVENT type
590
 
     */
591
 
 
592
1079
    if (ev->write && (n >= 0 || err == NGX_EAGAIN)) {
593
1080
        return;
594
1081
    }
595
1082
 
596
1083
    if ((ngx_event_flags & NGX_USE_LEVEL_EVENT) && ev->active) {
597
 
        if (ngx_del_event(ev, NGX_READ_EVENT, 0) == NGX_ERROR) {
 
1084
 
 
1085
        event = ev->write ? NGX_WRITE_EVENT : NGX_READ_EVENT;
 
1086
 
 
1087
        if (ngx_del_event(ev, event, 0) != NGX_OK) {
598
1088
            ngx_http_upstream_finalize_request(r, u,
599
1089
                                               NGX_HTTP_INTERNAL_SERVER_ERROR);
600
1090
            return;
619
1109
    ev->eof = 1;
620
1110
    c->error = 1;
621
1111
 
622
 
    if (!u->cacheable && !u->store && u->peer.connection) {
 
1112
    if (!u->cacheable && u->peer.connection) {
623
1113
        ngx_log_error(NGX_LOG_INFO, ev->log, err,
624
 
                      "client closed prematurely connection, "
 
1114
                      "client prematurely closed connection, "
625
1115
                      "so upstream connection is closed too");
626
1116
        ngx_http_upstream_finalize_request(r, u,
627
1117
                                           NGX_HTTP_CLIENT_CLOSED_REQUEST);
629
1119
    }
630
1120
 
631
1121
    ngx_log_error(NGX_LOG_INFO, ev->log, err,
632
 
                  "client closed prematurely connection");
 
1122
                  "client prematurely closed connection");
633
1123
 
634
1124
    if (u->peer.connection == NULL) {
635
1125
        ngx_http_upstream_finalize_request(r, u,
636
1126
                                           NGX_HTTP_CLIENT_CLOSED_REQUEST);
637
 
        return;
638
1127
    }
639
1128
}
640
1129
 
648
1137
 
649
1138
    r->connection->log->action = "connecting to upstream";
650
1139
 
651
 
    r->connection->single_connection = 0;
652
 
 
653
1140
    if (u->state && u->state->response_sec) {
654
1141
        tp = ngx_timeofday();
655
1142
        u->state->response_sec = tp->sec - u->state->response_sec;
699
1186
 
700
1187
    c->data = r;
701
1188
 
702
 
    c->write->handler = ngx_http_upstream_send_request_handler;
703
 
    c->read->handler = ngx_http_upstream_process_header;
 
1189
    c->write->handler = ngx_http_upstream_handler;
 
1190
    c->read->handler = ngx_http_upstream_handler;
 
1191
 
 
1192
    u->write_event_handler = ngx_http_upstream_send_request_handler;
 
1193
    u->read_event_handler = ngx_http_upstream_process_header;
704
1194
 
705
1195
    c->sendfile &= r->connection->sendfile;
706
1196
    u->output.sendfile = c->sendfile;
707
1197
 
708
 
    c->pool = r->pool;
709
 
    c->read->log = c->write->log = c->log = r->connection->log;
 
1198
    if (c->pool == NULL) {
 
1199
 
 
1200
        /* we need separate pool here to be able to cache SSL connections */
 
1201
 
 
1202
        c->pool = ngx_create_pool(128, r->connection->log);
 
1203
        if (c->pool == NULL) {
 
1204
            ngx_http_upstream_finalize_request(r, u,
 
1205
                                               NGX_HTTP_INTERNAL_SERVER_ERROR);
 
1206
            return;
 
1207
        }
 
1208
    }
 
1209
 
 
1210
    c->log = r->connection->log;
 
1211
    c->pool->log = c->log;
 
1212
    c->read->log = c->log;
 
1213
    c->write->log = c->log;
710
1214
 
711
1215
    /* init or reinit the ngx_output_chain() and ngx_chain_writer() contexts */
712
1216
 
730
1234
    {
731
1235
        /*
732
1236
         * the r->request_body->buf can be reused for one request only,
733
 
         * the subrequests should allocate their own temporay bufs
 
1237
         * the subrequests should allocate their own temporary bufs
734
1238
         */
735
1239
 
736
1240
        u->output.free = ngx_alloc_chain_link(r->pool);
779
1283
 
780
1284
    if (ngx_ssl_create_connection(u->conf->ssl, c,
781
1285
                                  NGX_SSL_BUFFER|NGX_SSL_CLIENT)
782
 
        == NGX_ERROR)
 
1286
        != NGX_OK)
783
1287
    {
784
1288
        ngx_http_upstream_finalize_request(r, u,
785
1289
                                           NGX_HTTP_INTERNAL_SERVER_ERROR);
789
1293
    c->sendfile = 0;
790
1294
    u->output.sendfile = 0;
791
1295
 
792
 
    if (u->peer.set_session(&u->peer, u->peer.data) != NGX_OK) {
793
 
        ngx_http_upstream_finalize_request(r, u,
794
 
                                           NGX_HTTP_INTERNAL_SERVER_ERROR);
795
 
        return;
 
1296
    if (u->conf->ssl_session_reuse) {
 
1297
        if (u->peer.set_session(&u->peer, u->peer.data) != NGX_OK) {
 
1298
            ngx_http_upstream_finalize_request(r, u,
 
1299
                                               NGX_HTTP_INTERNAL_SERVER_ERROR);
 
1300
            return;
 
1301
        }
796
1302
    }
797
1303
 
798
1304
    r->connection->log->action = "SSL handshaking to upstream";
819
1325
 
820
1326
    if (c->ssl->handshaked) {
821
1327
 
822
 
        u->peer.save_session(&u->peer, u->peer.data);
 
1328
        if (u->conf->ssl_session_reuse) {
 
1329
            u->peer.save_session(&u->peer, u->peer.data);
 
1330
        }
823
1331
 
824
 
        c->write->handler = ngx_http_upstream_send_request_handler;
825
 
        c->read->handler = ngx_http_upstream_process_header;
 
1332
        c->write->handler = ngx_http_upstream_handler;
 
1333
        c->read->handler = ngx_http_upstream_handler;
826
1334
 
827
1335
        ngx_http_upstream_send_request(r, u);
828
1336
 
845
1353
        return NGX_ERROR;
846
1354
    }
847
1355
 
 
1356
    u->keepalive = 0;
 
1357
    u->upgrade = 0;
 
1358
 
848
1359
    ngx_memzero(&u->headers_in, sizeof(ngx_http_upstream_headers_in_t));
 
1360
    u->headers_in.content_length_n = -1;
849
1361
 
850
1362
    if (ngx_list_init(&u->headers_in.headers, r->pool, 8,
851
1363
                      sizeof(ngx_table_elt_t))
884
1396
 
885
1397
    /* reinit u->buffer */
886
1398
 
887
 
#if 0
888
 
    if (u->cache) {
889
 
        u->buffer.pos = u->buffer.start + u->cache->ctx.header_size;
890
 
        u->buffer.last = u->buffer.pos;
891
 
 
892
 
    } else {
893
 
        u->buffer.pos = u->buffer.start;
894
 
        u->buffer.last = u->buffer.start;
 
1399
    u->buffer.pos = u->buffer.start;
 
1400
 
 
1401
#if (NGX_HTTP_CACHE)
 
1402
 
 
1403
    if (r->cache) {
 
1404
        u->buffer.pos += r->cache->header_start;
895
1405
    }
896
 
#else
897
 
 
898
 
        u->buffer.pos = u->buffer.start;
899
 
        u->buffer.last = u->buffer.start;
900
1406
 
901
1407
#endif
902
1408
 
 
1409
    u->buffer.last = u->buffer.pos;
 
1410
 
903
1411
    return NGX_OK;
904
1412
}
905
1413
 
938
1446
    if (rc == NGX_AGAIN) {
939
1447
        ngx_add_timer(c->write, u->conf->send_timeout);
940
1448
 
941
 
        if (ngx_handle_write_event(c->write, u->conf->send_lowat) == NGX_ERROR)
942
 
        {
 
1449
        if (ngx_handle_write_event(c->write, u->conf->send_lowat) != NGX_OK) {
943
1450
            ngx_http_upstream_finalize_request(r, u,
944
1451
                                               NGX_HTTP_INTERNAL_SERVER_ERROR);
945
1452
            return;
976
1483
         * it's better to do here because we postpone header buffer allocation
977
1484
         */
978
1485
 
979
 
        ngx_http_upstream_process_header(c->read);
 
1486
        ngx_http_upstream_process_header(r, u);
980
1487
        return;
981
1488
    }
982
1489
#endif
983
1490
 
984
 
    c->write->handler = ngx_http_upstream_dummy_handler;
 
1491
    u->write_event_handler = ngx_http_upstream_dummy_handler;
985
1492
 
986
 
    if (ngx_handle_write_event(c->write, 0) == NGX_ERROR) {
 
1493
    if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
987
1494
        ngx_http_upstream_finalize_request(r, u,
988
1495
                                           NGX_HTTP_INTERNAL_SERVER_ERROR);
989
1496
        return;
992
1499
 
993
1500
 
994
1501
static void
995
 
ngx_http_upstream_send_request_handler(ngx_event_t *wev)
 
1502
ngx_http_upstream_send_request_handler(ngx_http_request_t *r,
 
1503
    ngx_http_upstream_t *u)
996
1504
{
997
 
    ngx_connection_t     *c;
998
 
    ngx_http_request_t   *r;
999
 
    ngx_http_upstream_t  *u;
1000
 
 
1001
 
    c = wev->data;
1002
 
    r = c->data;
1003
 
    u = r->upstream;
1004
 
 
1005
 
    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0,
 
1505
    ngx_connection_t  *c;
 
1506
 
 
1507
    c = u->peer.connection;
 
1508
 
 
1509
    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1006
1510
                   "http upstream send request handler");
1007
1511
 
1008
 
    if (wev->timedout) {
 
1512
    if (c->write->timedout) {
1009
1513
        ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_TIMEOUT);
1010
1514
        return;
1011
1515
    }
1020
1524
#endif
1021
1525
 
1022
1526
    if (u->header_sent) {
1023
 
        wev->handler = ngx_http_upstream_dummy_handler;
 
1527
        u->write_event_handler = ngx_http_upstream_dummy_handler;
1024
1528
 
1025
 
        (void) ngx_handle_write_event(wev, 0);
 
1529
        (void) ngx_handle_write_event(c->write, 0);
1026
1530
 
1027
1531
        return;
1028
1532
    }
1032
1536
 
1033
1537
 
1034
1538
static void
1035
 
ngx_http_upstream_process_header(ngx_event_t *rev)
 
1539
ngx_http_upstream_process_header(ngx_http_request_t *r, ngx_http_upstream_t *u)
1036
1540
{
1037
 
    ssize_t                         n;
1038
 
    ngx_int_t                       rc;
1039
 
    ngx_str_t                      *uri, args;
1040
 
    ngx_uint_t                      i, flags;
1041
 
    ngx_list_part_t                *part;
1042
 
    ngx_table_elt_t                *h;
1043
 
    ngx_connection_t               *c;
1044
 
    ngx_http_request_t             *r;
1045
 
    ngx_http_upstream_t            *u;
1046
 
    ngx_http_err_page_t            *err_page;
1047
 
    ngx_http_core_loc_conf_t       *clcf;
1048
 
    ngx_http_upstream_header_t     *hh;
1049
 
    ngx_http_upstream_main_conf_t  *umcf;
1050
 
 
1051
 
    c = rev->data;
1052
 
    r = c->data;
1053
 
    u = r->upstream;
1054
 
 
1055
 
    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
 
1541
    ssize_t            n;
 
1542
    ngx_int_t          rc;
 
1543
    ngx_connection_t  *c;
 
1544
 
 
1545
    c = u->peer.connection;
 
1546
 
 
1547
    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
1056
1548
                   "http upstream process header");
1057
1549
 
1058
1550
    c->log->action = "reading response header from upstream";
1059
1551
 
1060
 
    if (rev->timedout) {
 
1552
    if (c->read->timedout) {
1061
1553
        ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_TIMEOUT);
1062
1554
        return;
1063
1555
    }
1091
1583
            return;
1092
1584
        }
1093
1585
 
1094
 
#if 0
1095
 
        if (u->cache) {
1096
 
            u->buffer.pos += u->cache->ctx.header_size;
 
1586
#if (NGX_HTTP_CACHE)
 
1587
 
 
1588
        if (r->cache) {
 
1589
            u->buffer.pos += r->cache->header_start;
1097
1590
            u->buffer.last = u->buffer.pos;
1098
1591
        }
1099
1592
#endif
1100
1593
    }
1101
1594
 
1102
 
    n = c->recv(c, u->buffer.last, u->buffer.end - u->buffer.last);
1103
 
 
1104
 
    if (n == NGX_AGAIN) {
1105
 
#if 0
1106
 
        ngx_add_timer(rev, u->read_timeout);
1107
 
#endif
1108
 
 
1109
 
        if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
1110
 
            ngx_http_upstream_finalize_request(r, u,
1111
 
                                               NGX_HTTP_INTERNAL_SERVER_ERROR);
1112
 
            return;
1113
 
        }
1114
 
 
1115
 
        return;
1116
 
    }
1117
 
 
1118
 
    if (n == 0) {
1119
 
        ngx_log_error(NGX_LOG_ERR, rev->log, 0,
1120
 
                      "upstream prematurely closed connection");
1121
 
    }
1122
 
 
1123
 
    if (n == NGX_ERROR || n == 0) {
1124
 
        ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR);
1125
 
        return;
1126
 
    }
1127
 
 
1128
 
    u->buffer.last += n;
1129
 
 
1130
 
#if 0
1131
 
    u->valid_header_in = 0;
1132
 
 
1133
 
    u->peer.cached = 0;
1134
 
#endif
1135
 
 
1136
 
    rc = u->process_header(r);
1137
 
 
1138
 
    if (rc == NGX_AGAIN) {
1139
 
#if 0
1140
 
        ngx_add_timer(rev, u->read_timeout);
1141
 
#endif
1142
 
 
1143
 
        if (u->buffer.pos == u->buffer.end) {
1144
 
            ngx_log_error(NGX_LOG_ERR, rev->log, 0,
1145
 
                          "upstream sent too big header");
1146
 
 
1147
 
            ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_INVALID_HEADER);
1148
 
            return;
1149
 
        }
1150
 
 
1151
 
        if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
1152
 
            ngx_http_upstream_finalize_request(r, u,
1153
 
                                               NGX_HTTP_INTERNAL_SERVER_ERROR);
1154
 
            return;
1155
 
        }
1156
 
 
1157
 
        return;
 
1595
    for ( ;; ) {
 
1596
 
 
1597
        n = c->recv(c, u->buffer.last, u->buffer.end - u->buffer.last);
 
1598
 
 
1599
        if (n == NGX_AGAIN) {
 
1600
#if 0
 
1601
            ngx_add_timer(rev, u->read_timeout);
 
1602
#endif
 
1603
 
 
1604
            if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
 
1605
                ngx_http_upstream_finalize_request(r, u,
 
1606
                                               NGX_HTTP_INTERNAL_SERVER_ERROR);
 
1607
                return;
 
1608
            }
 
1609
 
 
1610
            return;
 
1611
        }
 
1612
 
 
1613
        if (n == 0) {
 
1614
            ngx_log_error(NGX_LOG_ERR, c->log, 0,
 
1615
                          "upstream prematurely closed connection");
 
1616
        }
 
1617
 
 
1618
        if (n == NGX_ERROR || n == 0) {
 
1619
            ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR);
 
1620
            return;
 
1621
        }
 
1622
 
 
1623
        u->buffer.last += n;
 
1624
 
 
1625
#if 0
 
1626
        u->valid_header_in = 0;
 
1627
 
 
1628
        u->peer.cached = 0;
 
1629
#endif
 
1630
 
 
1631
        rc = u->process_header(r);
 
1632
 
 
1633
        if (rc == NGX_AGAIN) {
 
1634
 
 
1635
            if (u->buffer.last == u->buffer.end) {
 
1636
                ngx_log_error(NGX_LOG_ERR, c->log, 0,
 
1637
                              "upstream sent too big header");
 
1638
 
 
1639
                ngx_http_upstream_next(r, u,
 
1640
                                       NGX_HTTP_UPSTREAM_FT_INVALID_HEADER);
 
1641
                return;
 
1642
            }
 
1643
 
 
1644
            continue;
 
1645
        }
 
1646
 
 
1647
        break;
1158
1648
    }
1159
1649
 
1160
1650
    if (rc == NGX_HTTP_UPSTREAM_INVALID_HEADER) {
1170
1660
 
1171
1661
    /* rc == NGX_OK */
1172
1662
 
1173
 
    if (u->headers_in.status_n >= NGX_HTTP_BAD_REQUEST
1174
 
        && r->subrequest_in_memory)
1175
 
    {
1176
 
        u->buffer.last = u->buffer.pos;
1177
 
    }
1178
 
 
1179
 
    if (u->headers_in.status_n == NGX_HTTP_INTERNAL_SERVER_ERROR) {
1180
 
 
1181
 
        if (u->peer.tries > 1
1182
 
            && (u->conf->next_upstream & NGX_HTTP_UPSTREAM_FT_HTTP_500))
1183
 
        {
1184
 
            ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_HTTP_500);
1185
 
            return;
 
1663
    if (u->headers_in.status_n > NGX_HTTP_SPECIAL_RESPONSE) {
 
1664
 
 
1665
        if (r->subrequest_in_memory) {
 
1666
            u->buffer.last = u->buffer.pos;
 
1667
        }
 
1668
 
 
1669
        if (ngx_http_upstream_test_next(r, u) == NGX_OK) {
 
1670
            return;
 
1671
        }
 
1672
 
 
1673
        if (ngx_http_upstream_intercept_errors(r, u) == NGX_OK) {
 
1674
            return;
 
1675
        }
 
1676
    }
 
1677
 
 
1678
    if (ngx_http_upstream_process_headers(r, u) != NGX_OK) {
 
1679
        return;
 
1680
    }
 
1681
 
 
1682
    if (!r->subrequest_in_memory) {
 
1683
        ngx_http_upstream_send_response(r, u);
 
1684
        return;
 
1685
    }
 
1686
 
 
1687
    /* subrequest content in memory */
 
1688
 
 
1689
    if (u->input_filter == NULL) {
 
1690
        u->input_filter_init = ngx_http_upstream_non_buffered_filter_init;
 
1691
        u->input_filter = ngx_http_upstream_non_buffered_filter;
 
1692
        u->input_filter_ctx = r;
 
1693
    }
 
1694
 
 
1695
    if (u->input_filter_init(u->input_filter_ctx) == NGX_ERROR) {
 
1696
        ngx_http_upstream_finalize_request(r, u,
 
1697
                                           NGX_HTTP_INTERNAL_SERVER_ERROR);
 
1698
        return;
 
1699
    }
 
1700
 
 
1701
    n = u->buffer.last - u->buffer.pos;
 
1702
 
 
1703
    if (n) {
 
1704
        u->buffer.last -= n;
 
1705
 
 
1706
        u->state->response_length += n;
 
1707
 
 
1708
        if (u->input_filter(u->input_filter_ctx, n) == NGX_ERROR) {
 
1709
            ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
 
1710
            return;
 
1711
        }
 
1712
 
 
1713
        if (u->length == 0) {
 
1714
            ngx_http_upstream_finalize_request(r, u, 0);
 
1715
            return;
 
1716
        }
 
1717
    }
 
1718
 
 
1719
    u->read_event_handler = ngx_http_upstream_process_body_in_memory;
 
1720
 
 
1721
    ngx_http_upstream_process_body_in_memory(r, u);
 
1722
}
 
1723
 
 
1724
 
 
1725
static ngx_int_t
 
1726
ngx_http_upstream_test_next(ngx_http_request_t *r, ngx_http_upstream_t *u)
 
1727
{
 
1728
    ngx_uint_t                 status;
 
1729
    ngx_http_upstream_next_t  *un;
 
1730
 
 
1731
    status = u->headers_in.status_n;
 
1732
 
 
1733
    for (un = ngx_http_upstream_next_errors; un->status; un++) {
 
1734
 
 
1735
        if (status != un->status) {
 
1736
            continue;
 
1737
        }
 
1738
 
 
1739
        if (u->peer.tries > 1 && (u->conf->next_upstream & un->mask)) {
 
1740
            ngx_http_upstream_next(r, u, un->mask);
 
1741
            return NGX_OK;
1186
1742
        }
1187
1743
 
1188
1744
#if (NGX_HTTP_CACHE)
1189
1745
 
1190
 
        if (u->peer.tries == 0
1191
 
            && u->stale
1192
 
            && (u->conf->use_stale & NGX_HTTP_UPSTREAM_FT_HTTP_500))
 
1746
        if (u->cache_status == NGX_HTTP_CACHE_EXPIRED
 
1747
            && (u->conf->cache_use_stale & un->mask))
1193
1748
        {
1194
 
            ngx_http_upstream_finalize_request(r, u,
1195
 
                                              ngx_http_send_cached_response(r));
1196
 
            return;
 
1749
            ngx_int_t  rc;
 
1750
 
 
1751
            rc = u->reinit_request(r);
 
1752
 
 
1753
            if (rc == NGX_OK) {
 
1754
                u->cache_status = NGX_HTTP_CACHE_STALE;
 
1755
                rc = ngx_http_upstream_cache_send(r, u);
 
1756
            }
 
1757
 
 
1758
            ngx_http_upstream_finalize_request(r, u, rc);
 
1759
            return NGX_OK;
1197
1760
        }
1198
1761
 
1199
1762
#endif
1200
1763
    }
1201
1764
 
1202
 
    if (u->headers_in.status_n == NGX_HTTP_NOT_FOUND) {
1203
 
 
1204
 
        if (u->peer.tries > 1
1205
 
            && u->conf->next_upstream & NGX_HTTP_UPSTREAM_FT_HTTP_404)
1206
 
        {
1207
 
            ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_HTTP_404);
1208
 
            return;
1209
 
        }
1210
 
 
1211
 
        if (u->conf->intercept_404) {
1212
 
            ngx_http_upstream_finalize_request(r, u, NGX_HTTP_NOT_FOUND);
1213
 
            return;
1214
 
        }
1215
 
    }
1216
 
 
1217
 
 
1218
 
    if (u->headers_in.status_n >= NGX_HTTP_BAD_REQUEST
1219
 
        && u->conf->intercept_errors)
1220
 
    {
1221
 
        clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1222
 
 
1223
 
        if (clcf->error_pages) {
1224
 
 
1225
 
            err_page = clcf->error_pages->elts;
1226
 
            for (i = 0; i < clcf->error_pages->nelts; i++) {
1227
 
                if (err_page[i].status == (ngx_int_t) u->headers_in.status_n) {
1228
 
 
1229
 
                    if (u->headers_in.status_n == NGX_HTTP_UNAUTHORIZED) {
1230
 
 
1231
 
                        r->headers_out.www_authenticate =
1232
 
                                        ngx_list_push(&r->headers_out.headers);
1233
 
 
1234
 
                        if (r->headers_out.www_authenticate == NULL) {
1235
 
                            ngx_http_upstream_finalize_request(r, u,
1236
 
                                               NGX_HTTP_INTERNAL_SERVER_ERROR);
1237
 
                            return;
1238
 
                        }
1239
 
 
1240
 
                        *r->headers_out.www_authenticate =
1241
 
                                               *u->headers_in.www_authenticate;
1242
 
                    }
1243
 
 
 
1765
    return NGX_DECLINED;
 
1766
}
 
1767
 
 
1768
 
 
1769
static ngx_int_t
 
1770
ngx_http_upstream_intercept_errors(ngx_http_request_t *r,
 
1771
    ngx_http_upstream_t *u)
 
1772
{
 
1773
    ngx_int_t                  status;
 
1774
    ngx_uint_t                 i;
 
1775
    ngx_table_elt_t           *h;
 
1776
    ngx_http_err_page_t       *err_page;
 
1777
    ngx_http_core_loc_conf_t  *clcf;
 
1778
 
 
1779
    status = u->headers_in.status_n;
 
1780
 
 
1781
    if (status == NGX_HTTP_NOT_FOUND && u->conf->intercept_404) {
 
1782
        ngx_http_upstream_finalize_request(r, u, NGX_HTTP_NOT_FOUND);
 
1783
        return NGX_OK;
 
1784
    }
 
1785
 
 
1786
    if (!u->conf->intercept_errors) {
 
1787
        return NGX_DECLINED;
 
1788
    }
 
1789
 
 
1790
    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
 
1791
 
 
1792
    if (clcf->error_pages == NULL) {
 
1793
        return NGX_DECLINED;
 
1794
    }
 
1795
 
 
1796
    err_page = clcf->error_pages->elts;
 
1797
    for (i = 0; i < clcf->error_pages->nelts; i++) {
 
1798
 
 
1799
        if (err_page[i].status == status) {
 
1800
 
 
1801
            if (status == NGX_HTTP_UNAUTHORIZED
 
1802
                && u->headers_in.www_authenticate)
 
1803
            {
 
1804
                h = ngx_list_push(&r->headers_out.headers);
 
1805
 
 
1806
                if (h == NULL) {
1244
1807
                    ngx_http_upstream_finalize_request(r, u,
1245
 
                                                       u->headers_in.status_n);
1246
 
                    return;
1247
 
                }
1248
 
            }
1249
 
        }
1250
 
    }
 
1808
                                               NGX_HTTP_INTERNAL_SERVER_ERROR);
 
1809
                    return NGX_OK;
 
1810
                }
 
1811
 
 
1812
                *h = *u->headers_in.www_authenticate;
 
1813
 
 
1814
                r->headers_out.www_authenticate = h;
 
1815
            }
 
1816
 
 
1817
#if (NGX_HTTP_CACHE)
 
1818
 
 
1819
            if (r->cache) {
 
1820
                time_t  valid;
 
1821
 
 
1822
                valid = ngx_http_file_cache_valid(u->conf->cache_valid, status);
 
1823
 
 
1824
                if (valid) {
 
1825
                    r->cache->valid_sec = ngx_time() + valid;
 
1826
                    r->cache->error = status;
 
1827
                }
 
1828
 
 
1829
                ngx_http_file_cache_free(r->cache, u->pipe->temp_file);
 
1830
            }
 
1831
#endif
 
1832
            ngx_http_upstream_finalize_request(r, u, status);
 
1833
 
 
1834
            return NGX_OK;
 
1835
        }
 
1836
    }
 
1837
 
 
1838
    return NGX_DECLINED;
 
1839
}
 
1840
 
 
1841
 
 
1842
static ngx_int_t
 
1843
ngx_http_upstream_test_connect(ngx_connection_t *c)
 
1844
{
 
1845
    int        err;
 
1846
    socklen_t  len;
 
1847
 
 
1848
#if (NGX_HAVE_KQUEUE)
 
1849
 
 
1850
    if (ngx_event_flags & NGX_USE_KQUEUE_EVENT)  {
 
1851
        if (c->write->pending_eof || c->read->pending_eof) {
 
1852
            if (c->write->pending_eof) {
 
1853
                err = c->write->kq_errno;
 
1854
 
 
1855
            } else {
 
1856
                err = c->read->kq_errno;
 
1857
            }
 
1858
 
 
1859
            c->log->action = "connecting to upstream";
 
1860
            (void) ngx_connection_error(c, err,
 
1861
                                    "kevent() reported that connect() failed");
 
1862
            return NGX_ERROR;
 
1863
        }
 
1864
 
 
1865
    } else
 
1866
#endif
 
1867
    {
 
1868
        err = 0;
 
1869
        len = sizeof(int);
 
1870
 
 
1871
        /*
 
1872
         * BSDs and Linux return 0 and set a pending error in err
 
1873
         * Solaris returns -1 and sets errno
 
1874
         */
 
1875
 
 
1876
        if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, (void *) &err, &len)
 
1877
            == -1)
 
1878
        {
 
1879
            err = ngx_errno;
 
1880
        }
 
1881
 
 
1882
        if (err) {
 
1883
            c->log->action = "connecting to upstream";
 
1884
            (void) ngx_connection_error(c, err, "connect() failed");
 
1885
            return NGX_ERROR;
 
1886
        }
 
1887
    }
 
1888
 
 
1889
    return NGX_OK;
 
1890
}
 
1891
 
 
1892
 
 
1893
static ngx_int_t
 
1894
ngx_http_upstream_process_headers(ngx_http_request_t *r, ngx_http_upstream_t *u)
 
1895
{
 
1896
    ngx_str_t                      *uri, args;
 
1897
    ngx_uint_t                      i, flags;
 
1898
    ngx_list_part_t                *part;
 
1899
    ngx_table_elt_t                *h;
 
1900
    ngx_http_upstream_header_t     *hh;
 
1901
    ngx_http_upstream_main_conf_t  *umcf;
1251
1902
 
1252
1903
    umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);
1253
1904
 
1254
 
    if (u->headers_in.x_accel_redirect) {
1255
 
 
 
1905
    if (u->headers_in.x_accel_redirect
 
1906
        && !(u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_XA_REDIRECT))
 
1907
    {
1256
1908
        ngx_http_upstream_finalize_request(r, u, NGX_DECLINED);
1257
1909
 
1258
1910
        part = &u->headers_in.headers.part;
1277
1929
                if (hh->copy_handler(r, &h[i], hh->conf) != NGX_OK) {
1278
1930
                    ngx_http_finalize_request(r,
1279
1931
                                              NGX_HTTP_INTERNAL_SERVER_ERROR);
1280
 
                    return;
 
1932
                    return NGX_DONE;
1281
1933
                }
1282
1934
            }
1283
1935
        }
1284
1936
 
1285
1937
        uri = &u->headers_in.x_accel_redirect->value;
1286
 
        args.len = 0;
1287
 
        args.data = NULL;
1288
 
        flags = 0;
 
1938
        ngx_str_null(&args);
 
1939
        flags = NGX_HTTP_LOG_UNSAFE;
1289
1940
 
1290
1941
        if (ngx_http_parse_unsafe_uri(r, uri, &args, &flags) != NGX_OK) {
1291
1942
            ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND);
1292
 
            return;
1293
 
        }
1294
 
 
1295
 
        if (flags & NGX_HTTP_ZERO_IN_URI) {
1296
 
            r->zero_in_uri = 1;
 
1943
            return NGX_DONE;
1297
1944
        }
1298
1945
 
1299
1946
        if (r->method != NGX_HTTP_HEAD) {
1301
1948
        }
1302
1949
 
1303
1950
        ngx_http_internal_redirect(r, uri, &args);
1304
 
        return;
 
1951
        ngx_http_finalize_request(r, NGX_DONE);
 
1952
        return NGX_DONE;
1305
1953
    }
1306
1954
 
1307
1955
    part = &u->headers_in.headers.part;
1332
1980
            if (hh->copy_handler(r, &h[i], hh->conf) != NGX_OK) {
1333
1981
                ngx_http_upstream_finalize_request(r, u,
1334
1982
                                               NGX_HTTP_INTERNAL_SERVER_ERROR);
1335
 
                return;
 
1983
                return NGX_DONE;
1336
1984
            }
1337
1985
 
1338
1986
            continue;
1341
1989
        if (ngx_http_upstream_copy_header_line(r, &h[i], 0) != NGX_OK) {
1342
1990
            ngx_http_upstream_finalize_request(r, u,
1343
1991
                                               NGX_HTTP_INTERNAL_SERVER_ERROR);
1344
 
            return;
 
1992
            return NGX_DONE;
1345
1993
        }
1346
1994
    }
1347
1995
 
1356
2004
    r->headers_out.status = u->headers_in.status_n;
1357
2005
    r->headers_out.status_line = u->headers_in.status_line;
1358
2006
 
1359
 
    u->headers_in.content_length_n = r->headers_out.content_length_n;
1360
 
 
1361
 
    if (r->headers_out.content_length_n != -1) {
1362
 
        u->length = (size_t) r->headers_out.content_length_n;
1363
 
 
1364
 
    } else {
1365
 
        u->length = NGX_MAX_SIZE_T_VALUE;
1366
 
    }
1367
 
 
1368
 
    if (!r->subrequest_in_memory) {
1369
 
        ngx_http_upstream_send_response(r, u);
1370
 
        return;
1371
 
    }
1372
 
 
1373
 
    /* subrequest content in memory */
1374
 
 
1375
 
    if (u->input_filter == NULL) {
1376
 
        u->input_filter_init = ngx_http_upstream_non_buffered_filter_init;
1377
 
        u->input_filter = ngx_http_upstream_non_buffered_filter;
1378
 
        u->input_filter_ctx = r;
1379
 
    }
1380
 
 
1381
 
    if (u->input_filter_init(u->input_filter_ctx) == NGX_ERROR) {
1382
 
        ngx_http_upstream_finalize_request(r, u,
1383
 
                                           NGX_HTTP_INTERNAL_SERVER_ERROR);
1384
 
        return;
1385
 
    }
1386
 
 
1387
 
    if (u->buffer.last - u->buffer.pos >= (ssize_t) u->length) {
1388
 
        if (u->input_filter(u->input_filter_ctx, 0) == NGX_ERROR) {
1389
 
            ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
1390
 
            return;
1391
 
        }
1392
 
 
1393
 
        ngx_http_upstream_finalize_request(r, u, 0);
1394
 
        return;
1395
 
    }
1396
 
 
1397
 
    rev->handler = ngx_http_upstream_process_body_in_memory;
1398
 
 
1399
 
    ngx_http_upstream_process_body_in_memory(rev);
1400
 
}
1401
 
 
1402
 
 
1403
 
static ngx_int_t
1404
 
ngx_http_upstream_test_connect(ngx_connection_t *c)
1405
 
{
1406
 
    int        err;
1407
 
    socklen_t  len;
1408
 
 
1409
 
#if (NGX_HAVE_KQUEUE)
1410
 
 
1411
 
    if (ngx_event_flags & NGX_USE_KQUEUE_EVENT)  {
1412
 
        if (c->write->pending_eof) {
1413
 
            c->log->action = "connecting to upstream";
1414
 
            (void) ngx_connection_error(c, c->write->kq_errno,
1415
 
                                    "kevent() reported that connect() failed");
1416
 
            return NGX_ERROR;
1417
 
        }
1418
 
 
1419
 
    } else
1420
 
#endif
1421
 
    {
1422
 
        err = 0;
1423
 
        len = sizeof(int);
1424
 
 
1425
 
        /*
1426
 
         * BSDs and Linux return 0 and set a pending error in err
1427
 
         * Solaris returns -1 and sets errno
1428
 
         */
1429
 
 
1430
 
        if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, (void *) &err, &len)
1431
 
            == -1)
1432
 
        {
1433
 
            err = ngx_errno;
1434
 
        }
1435
 
 
1436
 
        if (err) {
1437
 
            c->log->action = "connecting to upstream";
1438
 
            (void) ngx_connection_error(c, err, "connect() failed");
1439
 
            return NGX_ERROR;
1440
 
        }
1441
 
    }
 
2007
    r->headers_out.content_length_n = u->headers_in.content_length_n;
 
2008
 
 
2009
    u->length = u->headers_in.content_length_n;
1442
2010
 
1443
2011
    return NGX_OK;
1444
2012
}
1445
2013
 
1446
2014
 
1447
2015
static void
1448
 
ngx_http_upstream_process_body_in_memory(ngx_event_t *rev)
 
2016
ngx_http_upstream_process_body_in_memory(ngx_http_request_t *r,
 
2017
    ngx_http_upstream_t *u)
1449
2018
{
1450
 
    size_t                size;
1451
 
    ssize_t               n;
1452
 
    ngx_buf_t            *b;
1453
 
    ngx_connection_t     *c;
1454
 
    ngx_http_request_t   *r;
1455
 
    ngx_http_upstream_t  *u;
 
2019
    size_t             size;
 
2020
    ssize_t            n;
 
2021
    ngx_buf_t         *b;
 
2022
    ngx_event_t       *rev;
 
2023
    ngx_connection_t  *c;
1456
2024
 
1457
 
    c = rev->data;
1458
 
    r = c->data;
1459
 
    u = r->upstream;
 
2025
    c = u->peer.connection;
 
2026
    rev = c->read;
1460
2027
 
1461
2028
    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
1462
2029
                   "http upstream process body on memory");
1475
2042
 
1476
2043
        if (size == 0) {
1477
2044
            ngx_log_error(NGX_LOG_ALERT, c->log, 0,
1478
 
                          "upstream buffer is too small to read repsonse");
 
2045
                          "upstream buffer is too small to read response");
1479
2046
            ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
1480
2047
            return;
1481
2048
        }
1491
2058
            return;
1492
2059
        }
1493
2060
 
 
2061
        u->state->response_length += n;
 
2062
 
1494
2063
        if (u->input_filter(u->input_filter_ctx, n) == NGX_ERROR) {
1495
2064
            ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
1496
2065
            return;
1501
2070
        }
1502
2071
    }
1503
2072
 
1504
 
    if (ngx_handle_read_event(rev, 0) == NGX_ERROR) {
 
2073
    if (u->length == 0) {
 
2074
        ngx_http_upstream_finalize_request(r, u, 0);
 
2075
        return;
 
2076
    }
 
2077
 
 
2078
    if (ngx_handle_read_event(rev, 0) != NGX_OK) {
1505
2079
        ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
1506
2080
        return;
1507
2081
    }
1519
2093
ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
1520
2094
{
1521
2095
    int                        tcp_nodelay;
1522
 
    ssize_t                    size;
 
2096
    ssize_t                    n;
1523
2097
    ngx_int_t                  rc;
1524
2098
    ngx_event_pipe_t          *p;
1525
2099
    ngx_connection_t          *c;
1526
 
    ngx_pool_cleanup_t        *cl;
1527
 
    ngx_pool_cleanup_file_t   *clf;
1528
2100
    ngx_http_core_loc_conf_t  *clcf;
1529
2101
 
1530
2102
    rc = ngx_http_send_header(r);
1531
2103
 
1532
 
    if (rc == NGX_ERROR || rc > NGX_OK || r->post_action || r->header_only) {
 
2104
    if (rc == NGX_ERROR || rc > NGX_OK || r->post_action) {
1533
2105
        ngx_http_upstream_finalize_request(r, u, rc);
1534
2106
        return;
1535
2107
    }
1536
2108
 
 
2109
    if (u->upgrade) {
 
2110
        ngx_http_upstream_upgrade(r, u);
 
2111
        return;
 
2112
    }
 
2113
 
 
2114
    c = r->connection;
 
2115
 
 
2116
    if (r->header_only) {
 
2117
 
 
2118
        if (u->cacheable || u->store) {
 
2119
 
 
2120
            if (ngx_shutdown_socket(c->fd, NGX_WRITE_SHUTDOWN) == -1) {
 
2121
                ngx_connection_error(c, ngx_socket_errno,
 
2122
                                     ngx_shutdown_socket_n " failed");
 
2123
            }
 
2124
 
 
2125
            r->read_event_handler = ngx_http_request_empty_handler;
 
2126
            r->write_event_handler = ngx_http_request_empty_handler;
 
2127
            c->error = 1;
 
2128
 
 
2129
        } else {
 
2130
            ngx_http_upstream_finalize_request(r, u, rc);
 
2131
            return;
 
2132
        }
 
2133
    }
 
2134
 
1537
2135
    u->header_sent = 1;
1538
2136
 
1539
2137
    if (r->request_body && r->request_body->temp_file) {
1540
 
        for (cl = r->pool->cleanup; cl; cl = cl->next) {
1541
 
            if (cl->handler == ngx_pool_cleanup_file) {
1542
 
                clf = cl->data;
1543
 
 
1544
 
                if (clf->fd == r->request_body->temp_file->file.fd) {
1545
 
                    cl->handler(clf);
1546
 
                    cl->handler = NULL;
1547
 
                    r->request_body->temp_file->file.fd = NGX_INVALID_FILE;
1548
 
                    break;
1549
 
                }
1550
 
            }
1551
 
        }
 
2138
        ngx_pool_run_cleanup_file(r->pool, r->request_body->temp_file->file.fd);
 
2139
        r->request_body->temp_file->file.fd = NGX_INVALID_FILE;
1552
2140
    }
1553
2141
 
1554
 
    c = r->connection;
1555
 
 
1556
2142
    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1557
2143
 
1558
2144
    if (!u->buffering) {
1563
2149
            u->input_filter_ctx = r;
1564
2150
        }
1565
2151
 
1566
 
        u->peer.connection->read->handler =
1567
 
                                   ngx_http_upstream_process_non_buffered_body;
 
2152
        u->read_event_handler = ngx_http_upstream_process_non_buffered_upstream;
1568
2153
        r->write_event_handler =
1569
2154
                             ngx_http_upstream_process_non_buffered_downstream;
1570
2155
 
1592
2177
            c->tcp_nodelay = NGX_TCP_NODELAY_SET;
1593
2178
        }
1594
2179
 
1595
 
        size = u->buffer.last - u->buffer.pos;
 
2180
        n = u->buffer.last - u->buffer.pos;
1596
2181
 
1597
 
        if (size) {
 
2182
        if (n) {
1598
2183
            u->buffer.last = u->buffer.pos;
1599
2184
 
1600
 
            if (u->input_filter(u->input_filter_ctx, size) == NGX_ERROR) {
 
2185
            u->state->response_length += n;
 
2186
 
 
2187
            if (u->input_filter(u->input_filter_ctx, n) == NGX_ERROR) {
1601
2188
                ngx_http_upstream_finalize_request(r, u, 0);
1602
2189
                return;
1603
2190
            }
1604
2191
 
1605
 
            ngx_http_upstream_process_non_buffered_body(c->write);
 
2192
            ngx_http_upstream_process_non_buffered_downstream(r);
1606
2193
 
1607
2194
        } else {
1608
2195
            u->buffer.pos = u->buffer.start;
1613
2200
                return;
1614
2201
            }
1615
2202
 
1616
 
            if (u->peer.connection->read->ready) {
1617
 
                ngx_http_upstream_process_non_buffered_body(
1618
 
                                                     u->peer.connection->read);
 
2203
            if (u->peer.connection->read->ready || u->length == 0) {
 
2204
                ngx_http_upstream_process_non_buffered_upstream(r, u);
1619
2205
            }
1620
2206
        }
1621
2207
 
1624
2210
 
1625
2211
    /* TODO: preallocate event_pipe bufs, look "Content-Length" */
1626
2212
 
1627
 
#if 0
1628
 
 
1629
 
    if (u->cache && u->cache->ctx.file.fd != NGX_INVALID_FILE) {
1630
 
        if (ngx_close_file(u->cache->ctx.file.fd) == NGX_FILE_ERROR) {
1631
 
            ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
1632
 
                          ngx_close_file_n " \"%s\" failed",
1633
 
                          u->cache->ctx.file.name.data);
 
2213
#if (NGX_HTTP_CACHE)
 
2214
 
 
2215
    if (r->cache && r->cache->file.fd != NGX_INVALID_FILE) {
 
2216
        ngx_pool_run_cleanup_file(r->pool, r->cache->file.fd);
 
2217
        r->cache->file.fd = NGX_INVALID_FILE;
 
2218
    }
 
2219
 
 
2220
    switch (ngx_http_test_predicates(r, u->conf->no_cache)) {
 
2221
 
 
2222
    case NGX_ERROR:
 
2223
        ngx_http_upstream_finalize_request(r, u, 0);
 
2224
        return;
 
2225
 
 
2226
    case NGX_DECLINED:
 
2227
        u->cacheable = 0;
 
2228
        break;
 
2229
 
 
2230
    default: /* NGX_OK */
 
2231
 
 
2232
        if (u->cache_status == NGX_HTTP_CACHE_BYPASS) {
 
2233
 
 
2234
            r->cache->min_uses = u->conf->cache_min_uses;
 
2235
            r->cache->body_start = u->conf->buffer_size;
 
2236
            r->cache->file_cache = u->conf->cache->data;
 
2237
 
 
2238
            if (ngx_http_file_cache_create(r) != NGX_OK) {
 
2239
                ngx_http_upstream_finalize_request(r, u, 0);
 
2240
                return;
 
2241
            }
1634
2242
        }
 
2243
 
 
2244
        break;
1635
2245
    }
1636
2246
 
1637
2247
    if (u->cacheable) {
1638
 
        header = (ngx_http_cache_header_t *) u->buffer->start;
1639
 
 
1640
 
        header->expires = u->cache->ctx.expires;
1641
 
        header->last_modified = u->cache->ctx.last_modified;
1642
 
        header->date = u->cache->ctx.date;
1643
 
        header->length = r->headers_out.content_length_n;
1644
 
        u->cache->ctx.length = r->headers_out.content_length_n;
1645
 
 
1646
 
        header->key_len = u->cache->ctx.key0.len;
1647
 
        ngx_memcpy(&header->key, u->cache->ctx.key0.data, header->key_len);
1648
 
        header->key[header->key_len] = LF;
 
2248
        time_t  now, valid;
 
2249
 
 
2250
        now = ngx_time();
 
2251
 
 
2252
        valid = r->cache->valid_sec;
 
2253
 
 
2254
        if (valid == 0) {
 
2255
            valid = ngx_http_file_cache_valid(u->conf->cache_valid,
 
2256
                                              u->headers_in.status_n);
 
2257
            if (valid) {
 
2258
                r->cache->valid_sec = now + valid;
 
2259
            }
 
2260
        }
 
2261
 
 
2262
        if (valid) {
 
2263
            r->cache->last_modified = r->headers_out.last_modified_time;
 
2264
            r->cache->date = now;
 
2265
            r->cache->body_start = (u_short) (u->buffer.pos - u->buffer.start);
 
2266
 
 
2267
            ngx_http_file_cache_set_header(r, u->buffer.start);
 
2268
 
 
2269
        } else {
 
2270
            u->cacheable = 0;
 
2271
            r->headers_out.last_modified_time = -1;
 
2272
        }
 
2273
    }
 
2274
 
 
2275
    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
 
2276
                   "http cacheable: %d", u->cacheable);
 
2277
 
 
2278
    if (u->cacheable == 0 && r->cache) {
 
2279
        ngx_http_file_cache_free(r->cache, u->pipe->temp_file);
1649
2280
    }
1650
2281
 
1651
2282
#endif
1675
2306
    p->temp_file->path = u->conf->temp_path;
1676
2307
    p->temp_file->pool = r->pool;
1677
2308
 
1678
 
    if (u->cacheable || u->store) {
 
2309
    if (p->cacheable) {
1679
2310
        p->temp_file->persistent = 1;
1680
2311
 
1681
2312
    } else {
1707
2338
            return;
1708
2339
        }
1709
2340
 
 
2341
        p->buf_to_file->start = u->buffer.start;
1710
2342
        p->buf_to_file->pos = u->buffer.start;
1711
2343
        p->buf_to_file->last = u->buffer.pos;
1712
2344
        p->buf_to_file->temporary = 1;
1713
2345
    }
1714
2346
 
1715
2347
    if (ngx_event_flags & NGX_USE_AIO_EVENT) {
1716
 
        /* the posted aio operation may currupt a shadow buffer */
 
2348
        /* the posted aio operation may corrupt a shadow buffer */
1717
2349
        p->single_buf = 1;
1718
2350
    }
1719
2351
 
1745
2377
    p->send_timeout = clcf->send_timeout;
1746
2378
    p->send_lowat = clcf->send_lowat;
1747
2379
 
1748
 
    u->peer.connection->read->handler = ngx_http_upstream_process_body;
 
2380
    p->length = -1;
 
2381
 
 
2382
    if (u->input_filter_init
 
2383
        && u->input_filter_init(p->input_ctx) != NGX_OK)
 
2384
    {
 
2385
        ngx_http_upstream_finalize_request(r, u, 0);
 
2386
        return;
 
2387
    }
 
2388
 
 
2389
    u->read_event_handler = ngx_http_upstream_process_upstream;
1749
2390
    r->write_event_handler = ngx_http_upstream_process_downstream;
1750
2391
 
1751
 
    ngx_http_upstream_process_body(u->peer.connection->read);
 
2392
    ngx_http_upstream_process_upstream(r, u);
 
2393
}
 
2394
 
 
2395
 
 
2396
static void
 
2397
ngx_http_upstream_upgrade(ngx_http_request_t *r, ngx_http_upstream_t *u)
 
2398
{
 
2399
    int                        tcp_nodelay;
 
2400
    ngx_connection_t          *c;
 
2401
    ngx_http_core_loc_conf_t  *clcf;
 
2402
 
 
2403
    c = r->connection;
 
2404
    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
 
2405
 
 
2406
    /* TODO: prevent upgrade if not requested or not possible */
 
2407
 
 
2408
    r->keepalive = 0;
 
2409
    c->log->action = "proxying upgraded connection";
 
2410
 
 
2411
    u->read_event_handler = ngx_http_upstream_upgraded_read_upstream;
 
2412
    u->write_event_handler = ngx_http_upstream_upgraded_write_upstream;
 
2413
    r->read_event_handler = ngx_http_upstream_upgraded_read_downstream;
 
2414
    r->write_event_handler = ngx_http_upstream_upgraded_write_downstream;
 
2415
 
 
2416
    if (clcf->tcp_nodelay) {
 
2417
        tcp_nodelay = 1;
 
2418
 
 
2419
        if (c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) {
 
2420
            ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay");
 
2421
 
 
2422
            if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY,
 
2423
                           (const void *) &tcp_nodelay, sizeof(int)) == -1)
 
2424
            {
 
2425
                ngx_connection_error(c, ngx_socket_errno,
 
2426
                                     "setsockopt(TCP_NODELAY) failed");
 
2427
                ngx_http_upstream_finalize_request(r, u, 0);
 
2428
                return;
 
2429
            }
 
2430
 
 
2431
            c->tcp_nodelay = NGX_TCP_NODELAY_SET;
 
2432
        }
 
2433
 
 
2434
        if (u->peer.connection->tcp_nodelay == NGX_TCP_NODELAY_UNSET) {
 
2435
            ngx_log_debug0(NGX_LOG_DEBUG_HTTP, u->peer.connection->log, 0,
 
2436
                           "tcp_nodelay");
 
2437
 
 
2438
            if (setsockopt(u->peer.connection->fd, IPPROTO_TCP, TCP_NODELAY,
 
2439
                           (const void *) &tcp_nodelay, sizeof(int)) == -1)
 
2440
            {
 
2441
                ngx_connection_error(u->peer.connection, ngx_socket_errno,
 
2442
                                     "setsockopt(TCP_NODELAY) failed");
 
2443
                ngx_http_upstream_finalize_request(r, u, 0);
 
2444
                return;
 
2445
            }
 
2446
 
 
2447
            u->peer.connection->tcp_nodelay = NGX_TCP_NODELAY_SET;
 
2448
        }
 
2449
    }
 
2450
 
 
2451
    if (ngx_http_send_special(r, NGX_HTTP_FLUSH) == NGX_ERROR) {
 
2452
        ngx_http_upstream_finalize_request(r, u, 0);
 
2453
        return;
 
2454
    }
 
2455
 
 
2456
    if (u->peer.connection->read->ready
 
2457
        || u->buffer.pos != u->buffer.last)
 
2458
    {
 
2459
        ngx_http_upstream_process_upgraded(r, 1, 1);
 
2460
    }
 
2461
 
 
2462
    if (c->read->ready
 
2463
        || r->header_in->pos != r->header_in->last)
 
2464
    {
 
2465
        ngx_http_upstream_process_upgraded(r, 0, 1);
 
2466
    }
 
2467
}
 
2468
 
 
2469
 
 
2470
static void
 
2471
ngx_http_upstream_upgraded_read_downstream(ngx_http_request_t *r)
 
2472
{
 
2473
    ngx_http_upstream_process_upgraded(r, 0, 0);
 
2474
}
 
2475
 
 
2476
 
 
2477
static void
 
2478
ngx_http_upstream_upgraded_write_downstream(ngx_http_request_t *r)
 
2479
{
 
2480
    ngx_http_upstream_process_upgraded(r, 1, 1);
 
2481
}
 
2482
 
 
2483
 
 
2484
static void
 
2485
ngx_http_upstream_upgraded_read_upstream(ngx_http_request_t *r,
 
2486
    ngx_http_upstream_t *u)
 
2487
{
 
2488
    ngx_http_upstream_process_upgraded(r, 1, 0);
 
2489
}
 
2490
 
 
2491
 
 
2492
static void
 
2493
ngx_http_upstream_upgraded_write_upstream(ngx_http_request_t *r,
 
2494
    ngx_http_upstream_t *u)
 
2495
{
 
2496
    ngx_http_upstream_process_upgraded(r, 0, 1);
 
2497
}
 
2498
 
 
2499
 
 
2500
static void
 
2501
ngx_http_upstream_process_upgraded(ngx_http_request_t *r,
 
2502
    ngx_uint_t from_upstream, ngx_uint_t do_write)
 
2503
{
 
2504
    size_t                     size;
 
2505
    ssize_t                    n;
 
2506
    ngx_buf_t                 *b;
 
2507
    ngx_connection_t          *c, *downstream, *upstream, *dst, *src;
 
2508
    ngx_http_upstream_t       *u;
 
2509
    ngx_http_core_loc_conf_t  *clcf;
 
2510
 
 
2511
    c = r->connection;
 
2512
    u = r->upstream;
 
2513
 
 
2514
    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
 
2515
                   "http upstream process upgraded, fu:%ui", from_upstream);
 
2516
 
 
2517
    downstream = c;
 
2518
    upstream = u->peer.connection;
 
2519
 
 
2520
    if (downstream->write->timedout) {
 
2521
        c->timedout = 1;
 
2522
        ngx_connection_error(c, NGX_ETIMEDOUT, "client timed out");
 
2523
        ngx_http_upstream_finalize_request(r, u, NGX_HTTP_REQUEST_TIME_OUT);
 
2524
        return;
 
2525
    }
 
2526
 
 
2527
    if (upstream->read->timedout || upstream->write->timedout) {
 
2528
        ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out");
 
2529
        ngx_http_upstream_finalize_request(r, u, 0);
 
2530
        return;
 
2531
    }
 
2532
 
 
2533
    if (from_upstream) {
 
2534
        src = upstream;
 
2535
        dst = downstream;
 
2536
        b = &u->buffer;
 
2537
 
 
2538
    } else {
 
2539
        src = downstream;
 
2540
        dst = upstream;
 
2541
        b = &u->from_client;
 
2542
 
 
2543
        if (r->header_in->last > r->header_in->pos) {
 
2544
            b = r->header_in;
 
2545
            b->end = b->last;
 
2546
            do_write = 1;
 
2547
        }
 
2548
 
 
2549
        if (b->start == NULL) {
 
2550
            b->start = ngx_palloc(r->pool, u->conf->buffer_size);
 
2551
            if (b->start == NULL) {
 
2552
                ngx_http_upstream_finalize_request(r, u, 0);
 
2553
                return;
 
2554
            }
 
2555
 
 
2556
            b->pos = b->start;
 
2557
            b->last = b->start;
 
2558
            b->end = b->start + u->conf->buffer_size;
 
2559
            b->temporary = 1;
 
2560
            b->tag = u->output.tag;
 
2561
        }
 
2562
    }
 
2563
 
 
2564
    for ( ;; ) {
 
2565
 
 
2566
        if (do_write) {
 
2567
 
 
2568
            size = b->last - b->pos;
 
2569
 
 
2570
            if (size && dst->write->ready) {
 
2571
 
 
2572
                n = dst->send(dst, b->pos, size);
 
2573
 
 
2574
                if (n == NGX_ERROR) {
 
2575
                    ngx_http_upstream_finalize_request(r, u, 0);
 
2576
                    return;
 
2577
                }
 
2578
 
 
2579
                if (n > 0) {
 
2580
                    b->pos += n;
 
2581
 
 
2582
                    if (b->pos == b->last) {
 
2583
                        b->pos = b->start;
 
2584
                        b->last = b->start;
 
2585
                    }
 
2586
                }
 
2587
            }
 
2588
        }
 
2589
 
 
2590
        size = b->end - b->last;
 
2591
 
 
2592
        if (size && src->read->ready) {
 
2593
 
 
2594
            n = src->recv(src, b->last, size);
 
2595
 
 
2596
            if (n == NGX_AGAIN || n == 0) {
 
2597
                break;
 
2598
            }
 
2599
 
 
2600
            if (n > 0) {
 
2601
                do_write = 1;
 
2602
                b->last += n;
 
2603
 
 
2604
                continue;
 
2605
            }
 
2606
 
 
2607
            if (n == NGX_ERROR) {
 
2608
                src->read->eof = 1;
 
2609
            }
 
2610
        }
 
2611
 
 
2612
        break;
 
2613
    }
 
2614
 
 
2615
    if ((upstream->read->eof && u->buffer.pos == u->buffer.last)
 
2616
        || (downstream->read->eof && u->from_client.pos == u->from_client.last)
 
2617
        || (downstream->read->eof && upstream->read->eof))
 
2618
    {
 
2619
        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
 
2620
                       "http upstream upgraded done");
 
2621
        ngx_http_upstream_finalize_request(r, u, 0);
 
2622
        return;
 
2623
    }
 
2624
 
 
2625
    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
 
2626
 
 
2627
    if (ngx_handle_write_event(upstream->write, u->conf->send_lowat)
 
2628
        != NGX_OK)
 
2629
    {
 
2630
        ngx_http_upstream_finalize_request(r, u, 0);
 
2631
        return;
 
2632
    }
 
2633
 
 
2634
    if (upstream->write->active && !upstream->write->ready) {
 
2635
        ngx_add_timer(upstream->write, u->conf->send_timeout);
 
2636
 
 
2637
    } else if (upstream->write->timer_set) {
 
2638
        ngx_del_timer(upstream->write);
 
2639
    }
 
2640
 
 
2641
    if (ngx_handle_read_event(upstream->read, 0) != NGX_OK) {
 
2642
        ngx_http_upstream_finalize_request(r, u, 0);
 
2643
        return;
 
2644
    }
 
2645
 
 
2646
    if (upstream->read->active && !upstream->read->ready) {
 
2647
        ngx_add_timer(upstream->read, u->conf->read_timeout);
 
2648
 
 
2649
    } else if (upstream->read->timer_set) {
 
2650
        ngx_del_timer(upstream->read);
 
2651
    }
 
2652
 
 
2653
    if (ngx_handle_write_event(downstream->write, clcf->send_lowat)
 
2654
        != NGX_OK)
 
2655
    {
 
2656
        ngx_http_upstream_finalize_request(r, u, 0);
 
2657
        return;
 
2658
    }
 
2659
 
 
2660
    if (ngx_handle_read_event(downstream->read, 0) != NGX_OK) {
 
2661
        ngx_http_upstream_finalize_request(r, u, 0);
 
2662
        return;
 
2663
    }
 
2664
 
 
2665
    if (downstream->write->active && !downstream->write->ready) {
 
2666
        ngx_add_timer(downstream->write, clcf->send_timeout);
 
2667
 
 
2668
    } else if (downstream->write->timer_set) {
 
2669
        ngx_del_timer(downstream->write);
 
2670
    }
1752
2671
}
1753
2672
 
1754
2673
 
1755
2674
static void
1756
2675
ngx_http_upstream_process_non_buffered_downstream(ngx_http_request_t *r)
1757
2676
{
1758
 
    ngx_http_upstream_process_non_buffered_body(r->connection->write);
1759
 
}
1760
 
 
1761
 
 
1762
 
static void
1763
 
ngx_http_upstream_process_non_buffered_body(ngx_event_t *ev)
 
2677
    ngx_event_t          *wev;
 
2678
    ngx_connection_t     *c;
 
2679
    ngx_http_upstream_t  *u;
 
2680
 
 
2681
    c = r->connection;
 
2682
    u = r->upstream;
 
2683
    wev = c->write;
 
2684
 
 
2685
    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
 
2686
                   "http upstream process non buffered downstream");
 
2687
 
 
2688
    c->log->action = "sending to client";
 
2689
 
 
2690
    if (wev->timedout) {
 
2691
        c->timedout = 1;
 
2692
        ngx_connection_error(c, NGX_ETIMEDOUT, "client timed out");
 
2693
        ngx_http_upstream_finalize_request(r, u, NGX_HTTP_REQUEST_TIME_OUT);
 
2694
        return;
 
2695
    }
 
2696
 
 
2697
    ngx_http_upstream_process_non_buffered_request(r, 1);
 
2698
}
 
2699
 
 
2700
 
 
2701
static void
 
2702
ngx_http_upstream_process_non_buffered_upstream(ngx_http_request_t *r,
 
2703
    ngx_http_upstream_t *u)
 
2704
{
 
2705
    ngx_connection_t  *c;
 
2706
 
 
2707
    c = u->peer.connection;
 
2708
 
 
2709
    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
 
2710
                   "http upstream process non buffered upstream");
 
2711
 
 
2712
    c->log->action = "reading upstream";
 
2713
 
 
2714
    if (c->read->timedout) {
 
2715
        ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out");
 
2716
        ngx_http_upstream_finalize_request(r, u, 0);
 
2717
        return;
 
2718
    }
 
2719
 
 
2720
    ngx_http_upstream_process_non_buffered_request(r, 0);
 
2721
}
 
2722
 
 
2723
 
 
2724
static void
 
2725
ngx_http_upstream_process_non_buffered_request(ngx_http_request_t *r,
 
2726
    ngx_uint_t do_write)
1764
2727
{
1765
2728
    size_t                     size;
1766
2729
    ssize_t                    n;
1767
2730
    ngx_buf_t                 *b;
1768
2731
    ngx_int_t                  rc;
1769
 
    ngx_uint_t                 do_write;
1770
 
    ngx_connection_t          *c, *downstream, *upstream;
1771
 
    ngx_http_request_t        *r;
 
2732
    ngx_connection_t          *downstream, *upstream;
1772
2733
    ngx_http_upstream_t       *u;
1773
2734
    ngx_http_core_loc_conf_t  *clcf;
1774
2735
 
1775
 
    c = ev->data;
1776
 
    r = c->data;
1777
2736
    u = r->upstream;
1778
 
 
1779
 
    if (ev->write) {
1780
 
        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
1781
 
                       "http upstream process non buffered downstream");
1782
 
        c->log->action = "sending to client";
1783
 
 
1784
 
    } else {
1785
 
        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
1786
 
                       "http upstream process non buffered upstream");
1787
 
        c->log->action = "reading upstream";
1788
 
    }
1789
 
 
1790
 
    if (ev->timedout) {
1791
 
        if (ev->write) {
1792
 
            c->timedout = 1;
1793
 
            ngx_connection_error(c, NGX_ETIMEDOUT, "client timed out");
1794
 
 
1795
 
        } else {
1796
 
            ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out");
1797
 
        }
1798
 
 
1799
 
        ngx_http_upstream_finalize_request(r, u, 0);
1800
 
        return;
1801
 
    }
1802
 
 
1803
2737
    downstream = r->connection;
1804
2738
    upstream = u->peer.connection;
1805
2739
 
1806
2740
    b = &u->buffer;
1807
2741
 
1808
 
    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1809
 
 
1810
 
    do_write = ev->write || u->length == 0;
 
2742
    do_write = do_write || u->length == 0;
1811
2743
 
1812
2744
    for ( ;; ) {
1813
2745
 
1816
2748
            if (u->out_bufs || u->busy_bufs) {
1817
2749
                rc = ngx_http_output_filter(r, u->out_bufs);
1818
2750
 
1819
 
                if (downstream->destroyed) {
1820
 
                    return;
1821
 
                }
1822
 
 
1823
2751
                if (rc == NGX_ERROR) {
1824
2752
                    ngx_http_upstream_finalize_request(r, u, 0);
1825
2753
                    return;
1826
2754
                }
1827
2755
 
1828
 
                ngx_chain_update_chains(&u->free_bufs, &u->busy_bufs,
 
2756
                ngx_chain_update_chains(r->pool, &u->free_bufs, &u->busy_bufs,
1829
2757
                                        &u->out_bufs, u->output.tag);
1830
2758
            }
1831
2759
 
1846
2774
 
1847
2775
        size = b->end - b->last;
1848
2776
 
1849
 
        if (size > u->length) {
1850
 
            size = u->length;
1851
 
        }
1852
 
 
1853
2777
        if (size && upstream->read->ready) {
1854
2778
 
1855
2779
            n = upstream->recv(upstream, b->last, size);
1859
2783
            }
1860
2784
 
1861
2785
            if (n > 0) {
 
2786
                u->state->response_length += n;
 
2787
 
1862
2788
                if (u->input_filter(u->input_filter_ctx, n) == NGX_ERROR) {
1863
2789
                    ngx_http_upstream_finalize_request(r, u, 0);
1864
2790
                    return;
1873
2799
        break;
1874
2800
    }
1875
2801
 
 
2802
    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
 
2803
 
1876
2804
    if (downstream->data == r) {
1877
2805
        if (ngx_handle_write_event(downstream->write, clcf->send_lowat)
1878
 
            == NGX_ERROR)
 
2806
            != NGX_OK)
1879
2807
        {
1880
2808
            ngx_http_upstream_finalize_request(r, u, 0);
1881
2809
            return;
1889
2817
        ngx_del_timer(downstream->write);
1890
2818
    }
1891
2819
 
1892
 
    if (ngx_handle_read_event(upstream->read, 0) == NGX_ERROR) {
 
2820
    if (ngx_handle_read_event(upstream->read, 0) != NGX_OK) {
1893
2821
        ngx_http_upstream_finalize_request(r, u, 0);
1894
2822
        return;
1895
2823
    }
1942
2870
    cl->buf->last = b->last;
1943
2871
    cl->buf->tag = u->output.tag;
1944
2872
 
1945
 
    if (u->length == NGX_MAX_SIZE_T_VALUE) {
 
2873
    if (u->length == -1) {
1946
2874
        return NGX_OK;
1947
2875
    }
1948
2876
 
1955
2883
static void
1956
2884
ngx_http_upstream_process_downstream(ngx_http_request_t *r)
1957
2885
{
1958
 
    ngx_http_upstream_process_body(r->connection->write);
1959
 
}
1960
 
 
1961
 
 
1962
 
static void
1963
 
ngx_http_upstream_process_body(ngx_event_t *ev)
1964
 
{
1965
 
    ngx_temp_file_t      *tf;
 
2886
    ngx_event_t          *wev;
 
2887
    ngx_connection_t     *c;
1966
2888
    ngx_event_pipe_t     *p;
1967
 
    ngx_connection_t     *c, *downstream;
1968
 
    ngx_http_log_ctx_t   *ctx;
1969
 
    ngx_http_request_t   *r;
1970
2889
    ngx_http_upstream_t  *u;
1971
2890
 
1972
 
    c = ev->data;
1973
 
    r = c->data;
 
2891
    c = r->connection;
1974
2892
    u = r->upstream;
1975
 
    downstream = r->connection;
1976
 
 
1977
 
    if (ev->write) {
1978
 
        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
1979
 
                       "http upstream process downstream");
1980
 
        c->log->action = "sending to client";
1981
 
 
1982
 
    } else {
1983
 
        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
1984
 
                       "http upstream process upstream");
1985
 
        c->log->action = "reading upstream";
1986
 
 
1987
 
        ctx = c->log->data;
1988
 
        ctx->current_request = r;
1989
 
    }
1990
 
 
1991
2893
    p = u->pipe;
1992
 
 
1993
 
    if (ev->timedout) {
1994
 
        if (ev->write) {
1995
 
            if (ev->delayed) {
1996
 
 
1997
 
                ev->timedout = 0;
1998
 
                ev->delayed = 0;
1999
 
 
2000
 
                if (!ev->ready) {
2001
 
                    ngx_add_timer(ev, p->send_timeout);
2002
 
 
2003
 
                    if (ngx_handle_write_event(ev, p->send_lowat) == NGX_ERROR)
2004
 
                    {
2005
 
                        ngx_http_upstream_finalize_request(r, u, 0);
2006
 
                        return;
2007
 
                    }
2008
 
 
2009
 
                    return;
2010
 
                }
2011
 
 
2012
 
                if (ngx_event_pipe(p, ev->write) == NGX_ABORT) {
2013
 
 
2014
 
                    if (downstream->destroyed) {
2015
 
                        return;
2016
 
                    }
2017
 
 
 
2894
    wev = c->write;
 
2895
 
 
2896
    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
 
2897
                   "http upstream process downstream");
 
2898
 
 
2899
    c->log->action = "sending to client";
 
2900
 
 
2901
    if (wev->timedout) {
 
2902
 
 
2903
        if (wev->delayed) {
 
2904
 
 
2905
            wev->timedout = 0;
 
2906
            wev->delayed = 0;
 
2907
 
 
2908
            if (!wev->ready) {
 
2909
                ngx_add_timer(wev, p->send_timeout);
 
2910
 
 
2911
                if (ngx_handle_write_event(wev, p->send_lowat) != NGX_OK) {
2018
2912
                    ngx_http_upstream_finalize_request(r, u, 0);
2019
 
                    return;
2020
2913
                }
2021
2914
 
2022
 
            } else {
2023
 
                p->downstream_error = 1;
2024
 
                c->timedout = 1;
2025
 
                ngx_connection_error(c, NGX_ETIMEDOUT, "client timed out");
 
2915
                return;
 
2916
            }
 
2917
 
 
2918
            if (ngx_event_pipe(p, wev->write) == NGX_ABORT) {
 
2919
                ngx_http_upstream_finalize_request(r, u, 0);
 
2920
                return;
2026
2921
            }
2027
2922
 
2028
2923
        } else {
2029
 
            p->upstream_error = 1;
2030
 
            ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out");
 
2924
            p->downstream_error = 1;
 
2925
            c->timedout = 1;
 
2926
            ngx_connection_error(c, NGX_ETIMEDOUT, "client timed out");
2031
2927
        }
2032
2928
 
2033
2929
    } else {
2034
 
        if (ev->write && ev->delayed) {
 
2930
 
 
2931
        if (wev->delayed) {
 
2932
 
2035
2933
            ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
2036
2934
                           "http downstream delayed");
2037
2935
 
2038
 
            if (ngx_handle_write_event(ev, p->send_lowat) == NGX_ERROR) {
2039
 
                return;
2040
 
            }
2041
 
 
2042
 
            return;
2043
 
        }
2044
 
 
2045
 
        if (ngx_event_pipe(p, ev->write) == NGX_ABORT) {
2046
 
 
2047
 
            if (downstream->destroyed) {
2048
 
                return;
2049
 
            }
2050
 
 
2051
 
            ngx_http_upstream_finalize_request(r, u, 0);
2052
 
            return;
2053
 
        }
2054
 
    }
 
2936
            if (ngx_handle_write_event(wev, p->send_lowat) != NGX_OK) {
 
2937
                ngx_http_upstream_finalize_request(r, u, 0);
 
2938
            }
 
2939
 
 
2940
            return;
 
2941
        }
 
2942
 
 
2943
        if (ngx_event_pipe(p, 1) == NGX_ABORT) {
 
2944
            ngx_http_upstream_finalize_request(r, u, 0);
 
2945
            return;
 
2946
        }
 
2947
    }
 
2948
 
 
2949
    ngx_http_upstream_process_request(r);
 
2950
}
 
2951
 
 
2952
 
 
2953
static void
 
2954
ngx_http_upstream_process_upstream(ngx_http_request_t *r,
 
2955
    ngx_http_upstream_t *u)
 
2956
{
 
2957
    ngx_connection_t  *c;
 
2958
 
 
2959
    c = u->peer.connection;
 
2960
 
 
2961
    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
 
2962
                   "http upstream process upstream");
 
2963
 
 
2964
    c->log->action = "reading upstream";
 
2965
 
 
2966
    if (c->read->timedout) {
 
2967
        u->pipe->upstream_error = 1;
 
2968
        ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out");
 
2969
 
 
2970
    } else {
 
2971
        if (ngx_event_pipe(u->pipe, 0) == NGX_ABORT) {
 
2972
            ngx_http_upstream_finalize_request(r, u, 0);
 
2973
            return;
 
2974
        }
 
2975
    }
 
2976
 
 
2977
    ngx_http_upstream_process_request(r);
 
2978
}
 
2979
 
 
2980
 
 
2981
static void
 
2982
ngx_http_upstream_process_request(ngx_http_request_t *r)
 
2983
{
 
2984
    ngx_temp_file_t      *tf;
 
2985
    ngx_event_pipe_t     *p;
 
2986
    ngx_http_upstream_t  *u;
 
2987
 
 
2988
    u = r->upstream;
 
2989
    p = u->pipe;
2055
2990
 
2056
2991
    if (u->peer.connection) {
2057
2992
 
2058
2993
        if (u->store) {
2059
2994
 
2060
 
            tf = u->pipe->temp_file;
2061
 
 
2062
 
            if (p->upstream_eof
2063
 
                && u->headers_in.status_n == NGX_HTTP_OK
2064
 
                && (u->headers_in.content_length_n == -1
2065
 
                    || (u->headers_in.content_length_n == tf->offset)))
2066
 
            {
2067
 
                ngx_http_upstream_store(r, u);
2068
 
 
2069
 
            } else if ((p->upstream_error
2070
 
                        || (p->upstream_eof
2071
 
                            && u->headers_in.status_n != NGX_HTTP_OK))
2072
 
                       && tf->file.fd != NGX_INVALID_FILE)
2073
 
            {
2074
 
                if (ngx_delete_file(tf->file.name.data) == NGX_FILE_ERROR) {
2075
 
 
2076
 
                    ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
2077
 
                                  ngx_delete_file_n " \"%s\" failed",
2078
 
                                  u->pipe->temp_file->file.name.data);
 
2995
            if (p->upstream_eof || p->upstream_done) {
 
2996
 
 
2997
                tf = u->pipe->temp_file;
 
2998
 
 
2999
                if (u->headers_in.status_n == NGX_HTTP_OK
 
3000
                    && (u->headers_in.content_length_n == -1
 
3001
                        || (u->headers_in.content_length_n == tf->offset)))
 
3002
                {
 
3003
                    ngx_http_upstream_store(r, u);
 
3004
                    u->store = 0;
2079
3005
                }
2080
3006
            }
2081
3007
        }
2082
3008
 
2083
 
#if (NGX_HTTP_FILE_CACHE)
2084
 
 
2085
 
        if (p->upstream_done && u->cacheable) {
2086
 
            if (ngx_http_cache_update(r) == NGX_ERROR) {
2087
 
                ngx_http_busy_unlock(u->conf->busy_lock, &u->busy_lock);
2088
 
                ngx_http_upstream_finalize_request(r, u, 0);
2089
 
                return;
2090
 
            }
2091
 
 
2092
 
        } else if (p->upstream_eof && u->cacheable) {
2093
 
 
2094
 
            /* TODO: check length & update cache */
2095
 
 
2096
 
            if (ngx_http_cache_update(r) == NGX_ERROR) {
2097
 
                ngx_http_busy_unlock(u->conf->busy_lock, &u->busy_lock);
2098
 
                ngx_http_upstream_finalize_request(r, u, 0);
2099
 
                return;
 
3009
#if (NGX_HTTP_CACHE)
 
3010
 
 
3011
        if (u->cacheable) {
 
3012
 
 
3013
            if (p->upstream_done) {
 
3014
                ngx_http_file_cache_update(r, u->pipe->temp_file);
 
3015
 
 
3016
            } else if (p->upstream_eof) {
 
3017
 
 
3018
                tf = u->pipe->temp_file;
 
3019
 
 
3020
                if (u->headers_in.content_length_n == -1
 
3021
                    || u->headers_in.content_length_n
 
3022
                       == tf->offset - (off_t) r->cache->body_start)
 
3023
                {
 
3024
                    ngx_http_file_cache_update(r, tf);
 
3025
 
 
3026
                } else {
 
3027
                    ngx_http_file_cache_free(r->cache, tf);
 
3028
                }
 
3029
 
 
3030
            } else if (p->upstream_error) {
 
3031
                ngx_http_file_cache_free(r->cache, u->pipe->temp_file);
2100
3032
            }
2101
3033
        }
2102
3034
 
2103
3035
#endif
2104
3036
 
2105
3037
        if (p->upstream_done || p->upstream_eof || p->upstream_error) {
2106
 
            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
 
3038
            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2107
3039
                           "http upstream exit: %p", p->out);
2108
3040
#if 0
2109
3041
            ngx_http_busy_unlock(u->conf->busy_lock, &u->busy_lock);
2114
3046
    }
2115
3047
 
2116
3048
    if (p->downstream_error) {
2117
 
        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
 
3049
        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2118
3050
                       "http upstream downstream error");
2119
3051
 
2120
 
        if (!u->cacheable && u->peer.connection) {
 
3052
        if (!u->cacheable && !u->store && u->peer.connection) {
2121
3053
            ngx_http_upstream_finalize_request(r, u, 0);
2122
3054
        }
2123
3055
    }
2161
3093
    }
2162
3094
 
2163
3095
    ext.access = u->conf->store_access;
 
3096
    ext.path_access = u->conf->store_access;
2164
3097
    ext.time = -1;
2165
3098
    ext.create_path = 1;
2166
3099
    ext.delete_file = 1;
2190
3123
        }
2191
3124
    }
2192
3125
 
 
3126
    path.len--;
 
3127
 
2193
3128
    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2194
3129
                   "upstream stores \"%s\" to \"%s\"",
2195
3130
                   tf->file.name.data, path.data);
2199
3134
 
2200
3135
 
2201
3136
static void
2202
 
ngx_http_upstream_dummy_handler(ngx_event_t *wev)
 
3137
ngx_http_upstream_dummy_handler(ngx_http_request_t *r, ngx_http_upstream_t *u)
2203
3138
{
2204
 
    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0,
 
3139
    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2205
3140
                   "http upstream dummy handler");
2206
3141
}
2207
3142
 
2219
3154
    ngx_http_busy_unlock(u->conf->busy_lock, &u->busy_lock);
2220
3155
#endif
2221
3156
 
2222
 
    if (ft_type == NGX_HTTP_UPSTREAM_FT_HTTP_404) {
2223
 
        state = NGX_PEER_NEXT;
2224
 
    } else {
2225
 
        state = NGX_PEER_FAILED;
2226
 
    }
2227
 
 
2228
 
    if (ft_type != NGX_HTTP_UPSTREAM_FT_NOLIVE) {
 
3157
    if (u->peer.sockaddr) {
 
3158
 
 
3159
        if (ft_type == NGX_HTTP_UPSTREAM_FT_HTTP_404) {
 
3160
            state = NGX_PEER_NEXT;
 
3161
        } else {
 
3162
            state = NGX_PEER_FAILED;
 
3163
        }
 
3164
 
2229
3165
        u->peer.free(&u->peer, u->peer.data, state);
 
3166
        u->peer.sockaddr = NULL;
2230
3167
    }
2231
3168
 
2232
3169
    if (ft_type == NGX_HTTP_UPSTREAM_FT_TIMEOUT) {
2237
3174
    if (u->peer.cached && ft_type == NGX_HTTP_UPSTREAM_FT_ERROR) {
2238
3175
        status = 0;
2239
3176
 
 
3177
        /* TODO: inform balancer instead */
 
3178
 
 
3179
        u->peer.tries++;
 
3180
 
2240
3181
    } else {
2241
3182
        switch(ft_type) {
2242
3183
 
2275
3216
 
2276
3217
#if (NGX_HTTP_CACHE)
2277
3218
 
2278
 
            if (u->stale && (u->conf->use_stale & ft_type)) {
2279
 
                ngx_http_upstream_finalize_request(r, u,
2280
 
                                             ngx_http_send_cached_response(r));
 
3219
            if (u->cache_status == NGX_HTTP_CACHE_EXPIRED
 
3220
                && (u->conf->cache_use_stale & ft_type))
 
3221
            {
 
3222
                ngx_int_t  rc;
 
3223
 
 
3224
                rc = u->reinit_request(r);
 
3225
 
 
3226
                if (rc == NGX_OK) {
 
3227
                    u->cache_status = NGX_HTTP_CACHE_STALE;
 
3228
                    rc = ngx_http_upstream_cache_send(r, u);
 
3229
                }
 
3230
 
 
3231
                ngx_http_upstream_finalize_request(r, u, rc);
2281
3232
                return;
2282
3233
            }
2283
 
 
2284
3234
#endif
2285
3235
 
2286
3236
            ngx_http_upstream_finalize_request(r, u, status);
2302
3252
        }
2303
3253
#endif
2304
3254
 
 
3255
        if (u->peer.connection->pool) {
 
3256
            ngx_destroy_pool(u->peer.connection->pool);
 
3257
        }
 
3258
 
2305
3259
        ngx_close_connection(u->peer.connection);
 
3260
        u->peer.connection = NULL;
2306
3261
    }
2307
3262
 
2308
3263
#if 0
2321
3276
{
2322
3277
    ngx_http_request_t *r = data;
2323
3278
 
2324
 
    ngx_http_upstream_t  *u;
2325
 
 
2326
3279
    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2327
3280
                   "cleanup http upstream request: \"%V\"", &r->uri);
2328
3281
 
2329
 
    u = r->upstream;
2330
 
 
2331
 
    if (u->resolved && u->resolved->ctx) {
2332
 
        ngx_resolve_name_done(u->resolved->ctx);
2333
 
    }
2334
 
 
2335
 
    ngx_http_upstream_finalize_request(r, u, NGX_DONE);
 
3282
    ngx_http_upstream_finalize_request(r, r->upstream, NGX_DONE);
2336
3283
}
2337
3284
 
2338
3285
 
2345
3292
    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2346
3293
                   "finalize http upstream request: %i", rc);
2347
3294
 
2348
 
    *u->cleanup = NULL;
 
3295
    if (u->cleanup) {
 
3296
        *u->cleanup = NULL;
 
3297
        u->cleanup = NULL;
 
3298
    }
 
3299
 
 
3300
    if (u->resolved && u->resolved->ctx) {
 
3301
        ngx_resolve_name_done(u->resolved->ctx);
 
3302
        u->resolved->ctx = NULL;
 
3303
    }
2349
3304
 
2350
3305
    if (u->state && u->state->response_sec) {
2351
3306
        tp = ngx_timeofday();
2352
3307
        u->state->response_sec = tp->sec - u->state->response_sec;
2353
3308
        u->state->response_msec = tp->msec - u->state->response_msec;
 
3309
 
 
3310
        if (u->pipe && u->pipe->read_length) {
 
3311
            u->state->response_length = u->pipe->read_length;
 
3312
        }
2354
3313
    }
2355
3314
 
2356
3315
    u->finalize_request(r, rc);
2357
3316
 
2358
 
    if (u->peer.free) {
 
3317
    if (u->peer.free && u->peer.sockaddr) {
2359
3318
        u->peer.free(&u->peer, u->peer.data, 0);
 
3319
        u->peer.sockaddr = NULL;
2360
3320
    }
2361
3321
 
2362
3322
    if (u->peer.connection) {
2383
3343
                       "close http upstream connection: %d",
2384
3344
                       u->peer.connection->fd);
2385
3345
 
 
3346
        if (u->peer.connection->pool) {
 
3347
            ngx_destroy_pool(u->peer.connection->pool);
 
3348
        }
 
3349
 
2386
3350
        ngx_close_connection(u->peer.connection);
2387
3351
    }
2388
3352
 
2389
3353
    u->peer.connection = NULL;
2390
3354
 
2391
 
    if (u->header_sent && (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE))
2392
 
    {
2393
 
        rc = 0;
2394
 
    }
2395
 
 
2396
3355
    if (u->pipe && u->pipe->temp_file) {
2397
3356
        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2398
3357
                       "http upstream temp fd: %d",
2399
3358
                       u->pipe->temp_file->file.fd);
2400
3359
    }
2401
3360
 
2402
 
#if 0
2403
 
    if (u->cache) {
2404
 
        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2405
 
                       "http upstream cache fd: %d",
2406
 
                       u->cache->ctx.file.fd);
2407
 
    }
 
3361
    if (u->store && u->pipe && u->pipe->temp_file
 
3362
        && u->pipe->temp_file->file.fd != NGX_INVALID_FILE)
 
3363
    {
 
3364
        if (ngx_delete_file(u->pipe->temp_file->file.name.data)
 
3365
            == NGX_FILE_ERROR)
 
3366
        {
 
3367
            ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
 
3368
                          ngx_delete_file_n " \"%s\" failed",
 
3369
                          u->pipe->temp_file->file.name.data);
 
3370
        }
 
3371
    }
 
3372
 
 
3373
#if (NGX_HTTP_CACHE)
 
3374
 
 
3375
    if (r->cache) {
 
3376
 
 
3377
        if (u->cacheable) {
 
3378
 
 
3379
            if (rc == NGX_HTTP_BAD_GATEWAY || rc == NGX_HTTP_GATEWAY_TIME_OUT) {
 
3380
                time_t  valid;
 
3381
 
 
3382
                valid = ngx_http_file_cache_valid(u->conf->cache_valid, rc);
 
3383
 
 
3384
                if (valid) {
 
3385
                    r->cache->valid_sec = ngx_time() + valid;
 
3386
                    r->cache->error = rc;
 
3387
                }
 
3388
            }
 
3389
        }
 
3390
 
 
3391
        ngx_http_file_cache_free(r->cache, u->pipe->temp_file);
 
3392
    }
 
3393
 
2408
3394
#endif
2409
3395
 
 
3396
    if (u->header_sent
 
3397
        && rc != NGX_HTTP_REQUEST_TIME_OUT
 
3398
        && (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE))
 
3399
    {
 
3400
        rc = 0;
 
3401
    }
 
3402
 
2410
3403
    if (rc == NGX_DECLINED) {
2411
3404
        return;
2412
3405
    }
2413
3406
 
2414
3407
    r->connection->log->action = "sending to client";
2415
3408
 
2416
 
    if (rc == 0) {
2417
 
        if (r == r->main) {
2418
 
            if (!r->post_action) {
2419
 
                rc = ngx_http_send_special(r, NGX_HTTP_LAST);
2420
 
            }
2421
 
 
2422
 
        } else {
2423
 
            if (r->out) {
2424
 
                rc = NGX_AGAIN;
2425
 
            }
2426
 
        }
 
3409
    if (rc == 0
 
3410
        && !r->header_only
 
3411
#if (NGX_HTTP_CACHE)
 
3412
        && !r->cached
 
3413
#endif
 
3414
       )
 
3415
    {
 
3416
        rc = ngx_http_send_special(r, NGX_HTTP_LAST);
2427
3417
    }
2428
3418
 
2429
3419
    ngx_http_finalize_request(r, rc);
2447
3437
 
2448
3438
 
2449
3439
static ngx_int_t
2450
 
ngx_http_upstream_process_multi_header_lines(ngx_http_request_t *r,
2451
 
    ngx_table_elt_t *h, ngx_uint_t offset)
2452
 
{
2453
 
    ngx_array_t       *pa;
2454
 
    ngx_table_elt_t  **ph;
2455
 
 
2456
 
    pa = (ngx_array_t *) ((char *) &r->upstream->headers_in + offset);
 
3440
ngx_http_upstream_ignore_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
 
3441
    ngx_uint_t offset)
 
3442
{
 
3443
    return NGX_OK;
 
3444
}
 
3445
 
 
3446
 
 
3447
static ngx_int_t
 
3448
ngx_http_upstream_process_content_length(ngx_http_request_t *r,
 
3449
    ngx_table_elt_t *h, ngx_uint_t offset)
 
3450
{
 
3451
    ngx_http_upstream_t  *u;
 
3452
 
 
3453
    u = r->upstream;
 
3454
 
 
3455
    u->headers_in.content_length = h;
 
3456
    u->headers_in.content_length_n = ngx_atoof(h->value.data, h->value.len);
 
3457
 
 
3458
    return NGX_OK;
 
3459
}
 
3460
 
 
3461
 
 
3462
static ngx_int_t
 
3463
ngx_http_upstream_process_set_cookie(ngx_http_request_t *r, ngx_table_elt_t *h,
 
3464
    ngx_uint_t offset)
 
3465
{
 
3466
#if (NGX_HTTP_CACHE)
 
3467
    ngx_http_upstream_t  *u;
 
3468
 
 
3469
    u = r->upstream;
 
3470
 
 
3471
    if (!(u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_SET_COOKIE)) {
 
3472
        u->cacheable = 0;
 
3473
    }
 
3474
#endif
 
3475
 
 
3476
    return NGX_OK;
 
3477
}
 
3478
 
 
3479
 
 
3480
static ngx_int_t
 
3481
ngx_http_upstream_process_cache_control(ngx_http_request_t *r,
 
3482
    ngx_table_elt_t *h, ngx_uint_t offset)
 
3483
{
 
3484
    ngx_array_t          *pa;
 
3485
    ngx_table_elt_t     **ph;
 
3486
    ngx_http_upstream_t  *u;
 
3487
 
 
3488
    u = r->upstream;
 
3489
    pa = &u->headers_in.cache_control;
2457
3490
 
2458
3491
    if (pa->elts == NULL) {
2459
3492
       if (ngx_array_init(pa, r->pool, 2, sizeof(ngx_table_elt_t *)) != NGX_OK)
2469
3502
 
2470
3503
    *ph = h;
2471
3504
 
 
3505
#if (NGX_HTTP_CACHE)
 
3506
    {
 
3507
    u_char     *p, *last;
 
3508
    ngx_int_t   n;
 
3509
 
 
3510
    if (u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_CACHE_CONTROL) {
 
3511
        return NGX_OK;
 
3512
    }
 
3513
 
 
3514
    if (r->cache == NULL) {
 
3515
        return NGX_OK;
 
3516
    }
 
3517
 
 
3518
    if (r->cache->valid_sec != 0) {
 
3519
        return NGX_OK;
 
3520
    }
 
3521
 
 
3522
    p = h->value.data;
 
3523
    last = p + h->value.len;
 
3524
 
 
3525
    if (ngx_strlcasestrn(p, last, (u_char *) "no-cache", 8 - 1) != NULL
 
3526
        || ngx_strlcasestrn(p, last, (u_char *) "no-store", 8 - 1) != NULL
 
3527
        || ngx_strlcasestrn(p, last, (u_char *) "private", 7 - 1) != NULL)
 
3528
    {
 
3529
        u->cacheable = 0;
 
3530
        return NGX_OK;
 
3531
    }
 
3532
 
 
3533
    p = ngx_strlcasestrn(p, last, (u_char *) "max-age=", 8 - 1);
 
3534
 
 
3535
    if (p == NULL) {
 
3536
        return NGX_OK;
 
3537
    }
 
3538
 
 
3539
    n = 0;
 
3540
 
 
3541
    for (p += 8; p < last; p++) {
 
3542
        if (*p == ',' || *p == ';' || *p == ' ') {
 
3543
            break;
 
3544
        }
 
3545
 
 
3546
        if (*p >= '0' && *p <= '9') {
 
3547
            n = n * 10 + *p - '0';
 
3548
            continue;
 
3549
        }
 
3550
 
 
3551
        u->cacheable = 0;
 
3552
        return NGX_OK;
 
3553
    }
 
3554
 
 
3555
    if (n == 0) {
 
3556
        u->cacheable = 0;
 
3557
        return NGX_OK;
 
3558
    }
 
3559
 
 
3560
    r->cache->valid_sec = ngx_time() + n;
 
3561
    }
 
3562
#endif
 
3563
 
2472
3564
    return NGX_OK;
2473
3565
}
2474
3566
 
2475
3567
 
2476
3568
static ngx_int_t
2477
 
ngx_http_upstream_ignore_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
 
3569
ngx_http_upstream_process_expires(ngx_http_request_t *r, ngx_table_elt_t *h,
2478
3570
    ngx_uint_t offset)
2479
3571
{
 
3572
    ngx_http_upstream_t  *u;
 
3573
 
 
3574
    u = r->upstream;
 
3575
    u->headers_in.expires = h;
 
3576
 
 
3577
#if (NGX_HTTP_CACHE)
 
3578
    {
 
3579
    time_t  expires;
 
3580
 
 
3581
    if (u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_EXPIRES) {
 
3582
        return NGX_OK;
 
3583
    }
 
3584
 
 
3585
    if (r->cache == NULL) {
 
3586
        return NGX_OK;
 
3587
    }
 
3588
 
 
3589
    if (r->cache->valid_sec != 0) {
 
3590
        return NGX_OK;
 
3591
    }
 
3592
 
 
3593
    expires = ngx_http_parse_time(h->value.data, h->value.len);
 
3594
 
 
3595
    if (expires == NGX_ERROR || expires < ngx_time()) {
 
3596
        u->cacheable = 0;
 
3597
        return NGX_OK;
 
3598
    }
 
3599
 
 
3600
    r->cache->valid_sec = expires;
 
3601
    }
 
3602
#endif
 
3603
 
 
3604
    return NGX_OK;
 
3605
}
 
3606
 
 
3607
 
 
3608
static ngx_int_t
 
3609
ngx_http_upstream_process_accel_expires(ngx_http_request_t *r,
 
3610
    ngx_table_elt_t *h, ngx_uint_t offset)
 
3611
{
 
3612
    ngx_http_upstream_t  *u;
 
3613
 
 
3614
    u = r->upstream;
 
3615
    u->headers_in.x_accel_expires = h;
 
3616
 
 
3617
#if (NGX_HTTP_CACHE)
 
3618
    {
 
3619
    u_char     *p;
 
3620
    size_t      len;
 
3621
    ngx_int_t   n;
 
3622
 
 
3623
    if (u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_XA_EXPIRES) {
 
3624
        return NGX_OK;
 
3625
    }
 
3626
 
 
3627
    if (r->cache == NULL) {
 
3628
        return NGX_OK;
 
3629
    }
 
3630
 
 
3631
    len = h->value.len;
 
3632
    p = h->value.data;
 
3633
 
 
3634
    if (p[0] != '@') {
 
3635
        n = ngx_atoi(p, len);
 
3636
 
 
3637
        switch (n) {
 
3638
        case 0:
 
3639
            u->cacheable = 0;
 
3640
            /* fall through */
 
3641
 
 
3642
        case NGX_ERROR:
 
3643
            return NGX_OK;
 
3644
 
 
3645
        default:
 
3646
            r->cache->valid_sec = ngx_time() + n;
 
3647
            return NGX_OK;
 
3648
        }
 
3649
    }
 
3650
 
 
3651
    p++;
 
3652
    len--;
 
3653
 
 
3654
    n = ngx_atoi(p, len);
 
3655
 
 
3656
    if (n != NGX_ERROR) {
 
3657
        r->cache->valid_sec = n;
 
3658
    }
 
3659
    }
 
3660
#endif
 
3661
 
2480
3662
    return NGX_OK;
2481
3663
}
2482
3664
 
2485
3667
ngx_http_upstream_process_limit_rate(ngx_http_request_t *r, ngx_table_elt_t *h,
2486
3668
    ngx_uint_t offset)
2487
3669
{
2488
 
    ngx_int_t  n;
2489
 
 
2490
 
    r->upstream->headers_in.x_accel_limit_rate = h;
 
3670
    ngx_int_t             n;
 
3671
    ngx_http_upstream_t  *u;
 
3672
 
 
3673
    u = r->upstream;
 
3674
    u->headers_in.x_accel_limit_rate = h;
 
3675
 
 
3676
    if (u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_XA_LIMIT_RATE) {
 
3677
        return NGX_OK;
 
3678
    }
2491
3679
 
2492
3680
    n = ngx_atoi(h->value.data, h->value.len);
2493
3681
 
2503
3691
ngx_http_upstream_process_buffering(ngx_http_request_t *r, ngx_table_elt_t *h,
2504
3692
    ngx_uint_t offset)
2505
3693
{
2506
 
    u_char  c0, c1, c2;
2507
 
 
2508
 
    if (r->upstream->conf->change_buffering) {
 
3694
    u_char                c0, c1, c2;
 
3695
    ngx_http_upstream_t  *u;
 
3696
 
 
3697
    u = r->upstream;
 
3698
 
 
3699
    if (u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_XA_BUFFERING) {
 
3700
        return NGX_OK;
 
3701
    }
 
3702
 
 
3703
    if (u->conf->change_buffering) {
2509
3704
 
2510
3705
        if (h->value.len == 2) {
2511
3706
            c0 = ngx_tolower(h->value.data[0]);
2512
3707
            c1 = ngx_tolower(h->value.data[1]);
2513
3708
 
2514
3709
            if (c0 == 'n' && c1 == 'o') {
2515
 
                r->upstream->buffering = 0;
 
3710
                u->buffering = 0;
2516
3711
            }
2517
3712
 
2518
3713
        } else if (h->value.len == 3) {
2521
3716
            c2 = ngx_tolower(h->value.data[2]);
2522
3717
 
2523
3718
            if (c0 == 'y' && c1 == 'e' && c2 == 's') {
2524
 
                r->upstream->buffering = 1;
 
3719
                u->buffering = 1;
2525
3720
            }
2526
3721
        }
2527
3722
    }
2534
3729
ngx_http_upstream_process_charset(ngx_http_request_t *r, ngx_table_elt_t *h,
2535
3730
    ngx_uint_t offset)
2536
3731
{
 
3732
    if (r->upstream->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_XA_CHARSET) {
 
3733
        return NGX_OK;
 
3734
    }
 
3735
 
2537
3736
    r->headers_out.override_charset = &h->value;
2538
3737
 
2539
3738
    return NGX_OK;
2541
3740
 
2542
3741
 
2543
3742
static ngx_int_t
 
3743
ngx_http_upstream_process_connection(ngx_http_request_t *r, ngx_table_elt_t *h,
 
3744
    ngx_uint_t offset)
 
3745
{
 
3746
    r->upstream->headers_in.connection = h;
 
3747
 
 
3748
    if (ngx_strlcasestrn(h->value.data, h->value.data + h->value.len,
 
3749
                         (u_char *) "close", 5 - 1)
 
3750
        != NULL)
 
3751
    {
 
3752
        r->upstream->headers_in.connection_close = 1;
 
3753
    }
 
3754
 
 
3755
    return NGX_OK;
 
3756
}
 
3757
 
 
3758
 
 
3759
static ngx_int_t
 
3760
ngx_http_upstream_process_transfer_encoding(ngx_http_request_t *r,
 
3761
    ngx_table_elt_t *h, ngx_uint_t offset)
 
3762
{
 
3763
    r->upstream->headers_in.transfer_encoding = h;
 
3764
 
 
3765
    if (ngx_strlcasestrn(h->value.data, h->value.data + h->value.len,
 
3766
                         (u_char *) "chunked", 7 - 1)
 
3767
        != NULL)
 
3768
    {
 
3769
        r->upstream->headers_in.chunked = 1;
 
3770
    }
 
3771
 
 
3772
    return NGX_OK;
 
3773
}
 
3774
 
 
3775
 
 
3776
static ngx_int_t
2544
3777
ngx_http_upstream_copy_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
2545
3778
    ngx_uint_t offset)
2546
3779
{
2603
3836
 
2604
3837
    r->headers_out.content_type_len = h->value.len;
2605
3838
    r->headers_out.content_type = h->value;
 
3839
    r->headers_out.content_type_lowcase = NULL;
2606
3840
 
2607
3841
    for (p = h->value.data; *p; p++) {
2608
3842
 
2647
3881
 
2648
3882
 
2649
3883
static ngx_int_t
2650
 
ngx_http_upstream_copy_content_length(ngx_http_request_t *r, ngx_table_elt_t *h,
 
3884
ngx_http_upstream_copy_last_modified(ngx_http_request_t *r, ngx_table_elt_t *h,
2651
3885
    ngx_uint_t offset)
2652
3886
{
2653
3887
    ngx_table_elt_t  *ho;
2659
3893
 
2660
3894
    *ho = *h;
2661
3895
 
2662
 
    r->headers_out.content_length = ho;
2663
 
    r->headers_out.content_length_n = ngx_atoof(h->value.data, h->value.len);
 
3896
    r->headers_out.last_modified = ho;
 
3897
 
 
3898
#if (NGX_HTTP_CACHE)
 
3899
 
 
3900
    if (r->upstream->cacheable) {
 
3901
        r->headers_out.last_modified_time = ngx_http_parse_time(h->value.data,
 
3902
                                                                h->value.len);
 
3903
    }
 
3904
 
 
3905
#endif
2664
3906
 
2665
3907
    return NGX_OK;
2666
3908
}
2756
3998
}
2757
3999
 
2758
4000
 
 
4001
static ngx_int_t
 
4002
ngx_http_upstream_rewrite_set_cookie(ngx_http_request_t *r, ngx_table_elt_t *h,
 
4003
    ngx_uint_t offset)
 
4004
{
 
4005
    ngx_int_t         rc;
 
4006
    ngx_table_elt_t  *ho;
 
4007
 
 
4008
    ho = ngx_list_push(&r->headers_out.headers);
 
4009
    if (ho == NULL) {
 
4010
        return NGX_ERROR;
 
4011
    }
 
4012
 
 
4013
    *ho = *h;
 
4014
 
 
4015
    if (r->upstream->rewrite_cookie) {
 
4016
        rc = r->upstream->rewrite_cookie(r, ho);
 
4017
 
 
4018
        if (rc == NGX_DECLINED) {
 
4019
            return NGX_OK;
 
4020
        }
 
4021
 
 
4022
#if (NGX_DEBUG)
 
4023
        if (rc == NGX_OK) {
 
4024
            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
 
4025
                           "rewritten cookie: \"%V\"", &ho->value);
 
4026
        }
 
4027
#endif
 
4028
 
 
4029
        return rc;
 
4030
    }
 
4031
 
 
4032
    return NGX_OK;
 
4033
}
 
4034
 
 
4035
 
 
4036
static ngx_int_t
 
4037
ngx_http_upstream_copy_allow_ranges(ngx_http_request_t *r,
 
4038
    ngx_table_elt_t *h, ngx_uint_t offset)
 
4039
{
 
4040
    ngx_table_elt_t  *ho;
 
4041
 
 
4042
#if (NGX_HTTP_CACHE)
 
4043
 
 
4044
    if (r->cached) {
 
4045
        r->allow_ranges = 1;
 
4046
        return NGX_OK;
 
4047
 
 
4048
    }
 
4049
 
 
4050
#endif
 
4051
 
 
4052
    ho = ngx_list_push(&r->headers_out.headers);
 
4053
    if (ho == NULL) {
 
4054
        return NGX_ERROR;
 
4055
    }
 
4056
 
 
4057
    *ho = *h;
 
4058
 
 
4059
    r->headers_out.accept_ranges = ho;
 
4060
 
 
4061
    return NGX_OK;
 
4062
}
 
4063
 
 
4064
 
2759
4065
#if (NGX_HTTP_GZIP)
2760
4066
 
2761
4067
static ngx_int_t
2828
4134
        }
2829
4135
    }
2830
4136
 
2831
 
    p = ngx_palloc(r->pool, len);
 
4137
    p = ngx_pnalloc(r->pool, len);
2832
4138
    if (p == NULL) {
2833
4139
        return NGX_ERROR;
2834
4140
    }
2889
4195
 
2890
4196
    len = r->upstream_states->nelts * (3 + 2);
2891
4197
 
2892
 
    p = ngx_palloc(r->pool, len);
 
4198
    p = ngx_pnalloc(r->pool, len);
2893
4199
    if (p == NULL) {
2894
4200
        return NGX_ERROR;
2895
4201
    }
2955
4261
 
2956
4262
    len = r->upstream_states->nelts * (NGX_TIME_T_LEN + 4 + 2);
2957
4263
 
2958
 
    p = ngx_palloc(r->pool, len);
 
4264
    p = ngx_pnalloc(r->pool, len);
2959
4265
    if (p == NULL) {
2960
4266
        return NGX_ERROR;
2961
4267
    }
2969
4275
        if (state[i].status) {
2970
4276
            ms = (ngx_msec_int_t)
2971
4277
                     (state[i].response_sec * 1000 + state[i].response_msec);
2972
 
            ms = (ms >= 0) ? ms : 0;
 
4278
            ms = ngx_max(ms, 0);
2973
4279
            p = ngx_sprintf(p, "%d.%03d", ms / 1000, ms % 1000);
2974
4280
 
2975
4281
        } else {
3003
4309
}
3004
4310
 
3005
4311
 
 
4312
static ngx_int_t
 
4313
ngx_http_upstream_response_length_variable(ngx_http_request_t *r,
 
4314
    ngx_http_variable_value_t *v, uintptr_t data)
 
4315
{
 
4316
    u_char                     *p;
 
4317
    size_t                      len;
 
4318
    ngx_uint_t                  i;
 
4319
    ngx_http_upstream_state_t  *state;
 
4320
 
 
4321
    v->valid = 1;
 
4322
    v->no_cacheable = 0;
 
4323
    v->not_found = 0;
 
4324
 
 
4325
    if (r->upstream_states == NULL || r->upstream_states->nelts == 0) {
 
4326
        v->not_found = 1;
 
4327
        return NGX_OK;
 
4328
    }
 
4329
 
 
4330
    len = r->upstream_states->nelts * (NGX_OFF_T_LEN + 2);
 
4331
 
 
4332
    p = ngx_pnalloc(r->pool, len);
 
4333
    if (p == NULL) {
 
4334
        return NGX_ERROR;
 
4335
    }
 
4336
 
 
4337
    v->data = p;
 
4338
 
 
4339
    i = 0;
 
4340
    state = r->upstream_states->elts;
 
4341
 
 
4342
    for ( ;; ) {
 
4343
        p = ngx_sprintf(p, "%O", state[i].response_length);
 
4344
 
 
4345
        if (++i == r->upstream_states->nelts) {
 
4346
            break;
 
4347
        }
 
4348
 
 
4349
        if (state[i].peer) {
 
4350
            *p++ = ',';
 
4351
            *p++ = ' ';
 
4352
 
 
4353
        } else {
 
4354
            *p++ = ' ';
 
4355
            *p++ = ':';
 
4356
            *p++ = ' ';
 
4357
 
 
4358
            if (++i == r->upstream_states->nelts) {
 
4359
                break;
 
4360
            }
 
4361
 
 
4362
            continue;
 
4363
        }
 
4364
    }
 
4365
 
 
4366
    v->len = p - v->data;
 
4367
 
 
4368
    return NGX_OK;
 
4369
}
 
4370
 
 
4371
 
3006
4372
ngx_int_t
3007
4373
ngx_http_upstream_header_variable(ngx_http_request_t *r,
3008
4374
    ngx_http_variable_value_t *v, uintptr_t data)
3018
4384
}
3019
4385
 
3020
4386
 
 
4387
#if (NGX_HTTP_CACHE)
 
4388
 
 
4389
ngx_int_t
 
4390
ngx_http_upstream_cache_status(ngx_http_request_t *r,
 
4391
    ngx_http_variable_value_t *v, uintptr_t data)
 
4392
{
 
4393
    ngx_uint_t  n;
 
4394
 
 
4395
    if (r->upstream == NULL || r->upstream->cache_status == 0) {
 
4396
        v->not_found = 1;
 
4397
        return NGX_OK;
 
4398
    }
 
4399
 
 
4400
    n = r->upstream->cache_status - 1;
 
4401
 
 
4402
    v->valid = 1;
 
4403
    v->no_cacheable = 0;
 
4404
    v->not_found = 0;
 
4405
    v->len = ngx_http_cache_status[n].len;
 
4406
    v->data = ngx_http_cache_status[n].data;
 
4407
 
 
4408
    return NGX_OK;
 
4409
}
 
4410
 
 
4411
#endif
 
4412
 
 
4413
 
3021
4414
static char *
3022
4415
ngx_http_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
3023
4416
{
3036
4429
    value = cf->args->elts;
3037
4430
    u.host = value[1];
3038
4431
    u.no_resolve = 1;
 
4432
    u.no_port = 1;
3039
4433
 
3040
4434
    uscf = ngx_http_upstream_add(cf, &u, NGX_HTTP_UPSTREAM_CREATE
3041
4435
                                         |NGX_HTTP_UPSTREAM_WEIGHT
3216
4610
 
3217
4611
            fail_timeout = ngx_parse_time(&s, 1);
3218
4612
 
3219
 
            if (fail_timeout == NGX_ERROR) {
 
4613
            if (fail_timeout == (time_t) NGX_ERROR) {
3220
4614
                goto invalid;
3221
4615
            }
3222
4616
 
3306
4700
            return NULL;
3307
4701
        }
3308
4702
 
3309
 
        if ((uscfp[i]->flags & NGX_HTTP_UPSTREAM_CREATE) && u->port) {
 
4703
        if ((uscfp[i]->flags & NGX_HTTP_UPSTREAM_CREATE) && !u->no_port) {
3310
4704
            ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
3311
4705
                               "upstream \"%V\" may not have port %d",
3312
4706
                               &u->host, u->port);
3313
4707
            return NULL;
3314
4708
        }
3315
4709
 
3316
 
        if ((flags & NGX_HTTP_UPSTREAM_CREATE) && uscfp[i]->port) {
 
4710
        if ((flags & NGX_HTTP_UPSTREAM_CREATE) && !uscfp[i]->no_port) {
3317
4711
            ngx_log_error(NGX_LOG_WARN, cf->log, 0,
3318
4712
                          "upstream \"%V\" may not have port %d in %s:%ui",
3319
4713
                          &u->host, uscfp[i]->port,
3321
4715
            return NULL;
3322
4716
        }
3323
4717
 
3324
 
        if (uscfp[i]->port != u->port) {
 
4718
        if (uscfp[i]->port && u->port
 
4719
            && uscfp[i]->port != u->port)
 
4720
        {
3325
4721
            continue;
3326
4722
        }
3327
4723
 
3331
4727
            continue;
3332
4728
        }
3333
4729
 
 
4730
        if (flags & NGX_HTTP_UPSTREAM_CREATE) {
 
4731
            uscfp[i]->flags = flags;
 
4732
        }
 
4733
 
3334
4734
        return uscfp[i];
3335
4735
    }
3336
4736
 
3345
4745
    uscf->line = cf->conf_file->line;
3346
4746
    uscf->port = u->port;
3347
4747
    uscf->default_port = u->default_port;
 
4748
    uscf->no_port = u->no_port;
3348
4749
 
3349
4750
    if (u->naddrs == 1) {
3350
4751
        uscf->servers = ngx_array_create(cf->pool, 1,
3351
4752
                                         sizeof(ngx_http_upstream_server_t));
3352
4753
        if (uscf->servers == NULL) {
3353
 
            return NGX_CONF_ERROR;
 
4754
            return NULL;
3354
4755
        }
3355
4756
 
3356
4757
        us = ngx_array_push(uscf->servers);
3357
4758
        if (us == NULL) {
3358
 
            return NGX_CONF_ERROR;
 
4759
            return NULL;
3359
4760
        }
3360
4761
 
3361
4762
        ngx_memzero(us, sizeof(ngx_http_upstream_server_t));
3362
4763
 
3363
4764
        us->addrs = u->addrs;
3364
 
        us->naddrs = u->naddrs;
 
4765
        us->naddrs = 1;
3365
4766
    }
3366
4767
 
3367
4768
    uscfp = ngx_array_push(&umcf->upstreams);
3375
4776
}
3376
4777
 
3377
4778
 
 
4779
char *
 
4780
ngx_http_upstream_bind_set_slot(ngx_conf_t *cf, ngx_command_t *cmd,
 
4781
    void *conf)
 
4782
{
 
4783
    char  *p = conf;
 
4784
 
 
4785
    ngx_int_t                           rc;
 
4786
    ngx_str_t                          *value;
 
4787
    ngx_http_complex_value_t            cv;
 
4788
    ngx_http_upstream_local_t         **plocal, *local;
 
4789
    ngx_http_compile_complex_value_t    ccv;
 
4790
 
 
4791
    plocal = (ngx_http_upstream_local_t **) (p + cmd->offset);
 
4792
 
 
4793
    if (*plocal != NGX_CONF_UNSET_PTR) {
 
4794
        return "is duplicate";
 
4795
    }
 
4796
 
 
4797
    value = cf->args->elts;
 
4798
 
 
4799
    if (ngx_strcmp(value[1].data, "off") == 0) {
 
4800
        *plocal = NULL;
 
4801
        return NGX_CONF_OK;
 
4802
    }
 
4803
 
 
4804
    ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
 
4805
 
 
4806
    ccv.cf = cf;
 
4807
    ccv.value = &value[1];
 
4808
    ccv.complex_value = &cv;
 
4809
 
 
4810
    if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
 
4811
        return NGX_CONF_ERROR;
 
4812
    }
 
4813
 
 
4814
    local = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_local_t));
 
4815
    if (local == NULL) {
 
4816
        return NGX_CONF_ERROR;
 
4817
    }
 
4818
 
 
4819
    *plocal = local;
 
4820
 
 
4821
    if (cv.lengths) {
 
4822
        local->value = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t));
 
4823
        if (local->value == NULL) {
 
4824
            return NGX_CONF_ERROR;
 
4825
        }
 
4826
 
 
4827
        *local->value = cv;
 
4828
 
 
4829
        return NGX_CONF_OK;
 
4830
    }
 
4831
 
 
4832
    local->addr = ngx_palloc(cf->pool, sizeof(ngx_addr_t));
 
4833
    if (local->addr == NULL) {
 
4834
        return NGX_CONF_ERROR;
 
4835
    }
 
4836
 
 
4837
    rc = ngx_parse_addr(cf->pool, local->addr, value[1].data, value[1].len);
 
4838
 
 
4839
    switch (rc) {
 
4840
    case NGX_OK:
 
4841
        local->addr->name = value[1];
 
4842
        return NGX_CONF_OK;
 
4843
 
 
4844
    case NGX_DECLINED:
 
4845
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
 
4846
                           "invalid address \"%V\"", &value[1]);
 
4847
        /* fall through */
 
4848
 
 
4849
    default:
 
4850
        return NGX_CONF_ERROR;
 
4851
    }
 
4852
}
 
4853
 
 
4854
 
 
4855
static ngx_addr_t *
 
4856
ngx_http_upstream_get_local(ngx_http_request_t *r,
 
4857
    ngx_http_upstream_local_t *local)
 
4858
{
 
4859
    ngx_int_t    rc;
 
4860
    ngx_str_t    val;
 
4861
    ngx_addr_t  *addr;
 
4862
 
 
4863
    if (local == NULL) {
 
4864
        return NULL;
 
4865
    }
 
4866
 
 
4867
    if (local->value == NULL) {
 
4868
        return local->addr;
 
4869
    }
 
4870
 
 
4871
    if (ngx_http_complex_value(r, local->value, &val) != NGX_OK) {
 
4872
        return NULL;
 
4873
    }
 
4874
 
 
4875
    if (val.len == 0) {
 
4876
        return NULL;
 
4877
    }
 
4878
 
 
4879
    addr = ngx_palloc(r->pool, sizeof(ngx_addr_t));
 
4880
    if (addr == NULL) {
 
4881
        return NULL;
 
4882
    }
 
4883
 
 
4884
    rc = ngx_parse_addr(r->pool, addr, val.data, val.len);
 
4885
 
 
4886
    switch (rc) {
 
4887
    case NGX_OK:
 
4888
        addr->name = val;
 
4889
        return addr;
 
4890
 
 
4891
    case NGX_DECLINED:
 
4892
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
 
4893
                      "invalid local address \"%V\"", &val);
 
4894
        /* fall through */
 
4895
 
 
4896
    default:
 
4897
        return NULL;
 
4898
    }
 
4899
}
 
4900
 
 
4901
 
 
4902
char *
 
4903
ngx_http_upstream_param_set_slot(ngx_conf_t *cf, ngx_command_t *cmd,
 
4904
    void *conf)
 
4905
{
 
4906
    char  *p = conf;
 
4907
 
 
4908
    ngx_str_t                   *value;
 
4909
    ngx_array_t                **a;
 
4910
    ngx_http_upstream_param_t   *param;
 
4911
 
 
4912
    a = (ngx_array_t **) (p + cmd->offset);
 
4913
 
 
4914
    if (*a == NULL) {
 
4915
        *a = ngx_array_create(cf->pool, 4, sizeof(ngx_http_upstream_param_t));
 
4916
        if (*a == NULL) {
 
4917
            return NGX_CONF_ERROR;
 
4918
        }
 
4919
    }
 
4920
 
 
4921
    param = ngx_array_push(*a);
 
4922
    if (param == NULL) {
 
4923
        return NGX_CONF_ERROR;
 
4924
    }
 
4925
 
 
4926
    value = cf->args->elts;
 
4927
 
 
4928
    param->key = value[1];
 
4929
    param->value = value[2];
 
4930
    param->skip_empty = 0;
 
4931
 
 
4932
    if (cf->args->nelts == 4) {
 
4933
        if (ngx_strcmp(value[3].data, "if_not_empty") != 0) {
 
4934
            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
 
4935
                               "invalid parameter \"%V\"", &value[3]);
 
4936
            return NGX_CONF_ERROR;
 
4937
        }
 
4938
 
 
4939
        param->skip_empty = 1;
 
4940
    }
 
4941
 
 
4942
    return NGX_CONF_OK;
 
4943
}
 
4944
 
 
4945
 
3378
4946
ngx_int_t
3379
4947
ngx_http_upstream_hide_headers_hash(ngx_conf_t *cf,
3380
4948
    ngx_http_upstream_conf_t *conf, ngx_http_upstream_conf_t *prev,
3388
4956
    if (conf->hide_headers == NGX_CONF_UNSET_PTR
3389
4957
        && conf->pass_headers == NGX_CONF_UNSET_PTR)
3390
4958
    {
3391
 
        conf->hide_headers_hash = prev->hide_headers_hash;
3392
 
 
3393
 
        if (conf->hide_headers_hash.buckets) {
3394
 
            return NGX_OK;
3395
 
        }
3396
 
 
3397
4959
        conf->hide_headers = prev->hide_headers;
3398
4960
        conf->pass_headers = prev->pass_headers;
3399
4961
 
 
4962
        conf->hide_headers_hash = prev->hide_headers_hash;
 
4963
 
 
4964
        if (conf->hide_headers_hash.buckets
 
4965
#if (NGX_HTTP_CACHE)
 
4966
            && ((conf->cache == NULL) == (prev->cache == NULL))
 
4967
#endif
 
4968
           )
 
4969
        {
 
4970
            return NGX_OK;
 
4971
        }
 
4972
 
3400
4973
    } else {
3401
4974
        if (conf->hide_headers == NGX_CONF_UNSET_PTR) {
3402
4975
            conf->hide_headers = prev->hide_headers;
3496
5069
                       sizeof(ngx_http_upstream_srv_conf_t *))
3497
5070
        != NGX_OK)
3498
5071
    {
3499
 
        return NGX_CONF_ERROR;
 
5072
        return NULL;
3500
5073
    }
3501
5074
 
3502
5075
    return umcf;