Bug Summary

File:http/ngx_http_upstream.c
Location:line 3391, column 44
Description:Access to field 'temp_file' results in a dereference of a null pointer (loaded from field 'pipe')

Annotated Source Code

1
2/*
3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
5 */
6
7
8#include <ngx_config.h>
9#include <ngx_core.h>
10#include <ngx_http.h>
11
12
13#if (NGX_HTTP_CACHE1)
14static ngx_int_t ngx_http_upstream_cache(ngx_http_request_t *r,
15 ngx_http_upstream_t *u);
16static ngx_int_t ngx_http_upstream_cache_send(ngx_http_request_t *r,
17 ngx_http_upstream_t *u);
18static 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
22static void ngx_http_upstream_init_request(ngx_http_request_t *r);
23static void ngx_http_upstream_resolve_handler(ngx_resolver_ctx_t *ctx);
24static void ngx_http_upstream_rd_check_broken_connection(ngx_http_request_t *r);
25static void ngx_http_upstream_wr_check_broken_connection(ngx_http_request_t *r);
26static void ngx_http_upstream_check_broken_connection(ngx_http_request_t *r,
27 ngx_event_t *ev);
28static void ngx_http_upstream_connect(ngx_http_request_t *r,
29 ngx_http_upstream_t *u);
30static ngx_int_t ngx_http_upstream_reinit(ngx_http_request_t *r,
31 ngx_http_upstream_t *u);
32static void ngx_http_upstream_send_request(ngx_http_request_t *r,
33 ngx_http_upstream_t *u);
34static void ngx_http_upstream_send_request_handler(ngx_http_request_t *r,
35 ngx_http_upstream_t *u);
36static void ngx_http_upstream_process_header(ngx_http_request_t *r,
37 ngx_http_upstream_t *u);
38static ngx_int_t ngx_http_upstream_test_next(ngx_http_request_t *r,
39 ngx_http_upstream_t *u);
40static ngx_int_t ngx_http_upstream_intercept_errors(ngx_http_request_t *r,
41 ngx_http_upstream_t *u);
42static ngx_int_t ngx_http_upstream_test_connect(ngx_connection_t *c);
43static ngx_int_t ngx_http_upstream_process_headers(ngx_http_request_t *r,
44 ngx_http_upstream_t *u);
45static void ngx_http_upstream_process_body_in_memory(ngx_http_request_t *r,
46 ngx_http_upstream_t *u);
47static void ngx_http_upstream_send_response(ngx_http_request_t *r,
48 ngx_http_upstream_t *u);
49static void ngx_http_upstream_upgrade(ngx_http_request_t *r,
50 ngx_http_upstream_t *u);
51static void ngx_http_upstream_upgraded_read_downstream(ngx_http_request_t *r);
52static void ngx_http_upstream_upgraded_write_downstream(ngx_http_request_t *r);
53static void ngx_http_upstream_upgraded_read_upstream(ngx_http_request_t *r,
54 ngx_http_upstream_t *u);
55static void ngx_http_upstream_upgraded_write_upstream(ngx_http_request_t *r,
56 ngx_http_upstream_t *u);
57static void ngx_http_upstream_process_upgraded(ngx_http_request_t *r,
58 ngx_uint_t from_upstream, ngx_uint_t do_write);
59static void
60 ngx_http_upstream_process_non_buffered_downstream(ngx_http_request_t *r);
61static void
62 ngx_http_upstream_process_non_buffered_upstream(ngx_http_request_t *r,
63 ngx_http_upstream_t *u);
64static void
65 ngx_http_upstream_process_non_buffered_request(ngx_http_request_t *r,
66 ngx_uint_t do_write);
67static ngx_int_t ngx_http_upstream_non_buffered_filter_init(void *data);
68static ngx_int_t ngx_http_upstream_non_buffered_filter(void *data,
69 ssize_t bytes);
70static void ngx_http_upstream_process_downstream(ngx_http_request_t *r);
71static void ngx_http_upstream_process_upstream(ngx_http_request_t *r,
72 ngx_http_upstream_t *u);
73static void ngx_http_upstream_process_request(ngx_http_request_t *r);
74static void ngx_http_upstream_store(ngx_http_request_t *r,
75 ngx_http_upstream_t *u);
76static void ngx_http_upstream_dummy_handler(ngx_http_request_t *r,
77 ngx_http_upstream_t *u);
78static void ngx_http_upstream_next(ngx_http_request_t *r,
79 ngx_http_upstream_t *u, ngx_uint_t ft_type);
80static void ngx_http_upstream_cleanup(void *data);
81static void ngx_http_upstream_finalize_request(ngx_http_request_t *r,
82 ngx_http_upstream_t *u, ngx_int_t rc);
83
84static ngx_int_t ngx_http_upstream_process_header_line(ngx_http_request_t *r,
85 ngx_table_elt_t *h, ngx_uint_t offset);
86static ngx_int_t ngx_http_upstream_process_content_length(ngx_http_request_t *r,
87 ngx_table_elt_t *h, ngx_uint_t offset);
88static ngx_int_t ngx_http_upstream_process_set_cookie(ngx_http_request_t *r,
89 ngx_table_elt_t *h, ngx_uint_t offset);
90static ngx_int_t
91 ngx_http_upstream_process_cache_control(ngx_http_request_t *r,
92 ngx_table_elt_t *h, ngx_uint_t offset);
93static ngx_int_t ngx_http_upstream_ignore_header_line(ngx_http_request_t *r,
94 ngx_table_elt_t *h, ngx_uint_t offset);
95static ngx_int_t ngx_http_upstream_process_expires(ngx_http_request_t *r,
96 ngx_table_elt_t *h, ngx_uint_t offset);
97static ngx_int_t ngx_http_upstream_process_accel_expires(ngx_http_request_t *r,
98 ngx_table_elt_t *h, ngx_uint_t offset);
99static ngx_int_t ngx_http_upstream_process_limit_rate(ngx_http_request_t *r,
100 ngx_table_elt_t *h, ngx_uint_t offset);
101static ngx_int_t ngx_http_upstream_process_buffering(ngx_http_request_t *r,
102 ngx_table_elt_t *h, ngx_uint_t offset);
103static ngx_int_t ngx_http_upstream_process_charset(ngx_http_request_t *r,
104 ngx_table_elt_t *h, ngx_uint_t offset);
105static ngx_int_t ngx_http_upstream_process_connection(ngx_http_request_t *r,
106 ngx_table_elt_t *h, ngx_uint_t offset);
107static 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);
110static ngx_int_t ngx_http_upstream_copy_header_line(ngx_http_request_t *r,
111 ngx_table_elt_t *h, ngx_uint_t offset);
112static ngx_int_t
113 ngx_http_upstream_copy_multi_header_lines(ngx_http_request_t *r,
114 ngx_table_elt_t *h, ngx_uint_t offset);
115static ngx_int_t ngx_http_upstream_copy_content_type(ngx_http_request_t *r,
116 ngx_table_elt_t *h, ngx_uint_t offset);
117static ngx_int_t ngx_http_upstream_copy_last_modified(ngx_http_request_t *r,
118 ngx_table_elt_t *h, ngx_uint_t offset);
119static ngx_int_t ngx_http_upstream_rewrite_location(ngx_http_request_t *r,
120 ngx_table_elt_t *h, ngx_uint_t offset);
121static ngx_int_t ngx_http_upstream_rewrite_refresh(ngx_http_request_t *r,
122 ngx_table_elt_t *h, ngx_uint_t offset);
123static ngx_int_t ngx_http_upstream_rewrite_set_cookie(ngx_http_request_t *r,
124 ngx_table_elt_t *h, ngx_uint_t offset);
125static 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
128#if (NGX_HTTP_GZIP1)
129static ngx_int_t ngx_http_upstream_copy_content_encoding(ngx_http_request_t *r,
130 ngx_table_elt_t *h, ngx_uint_t offset);
131#endif
132
133static ngx_int_t ngx_http_upstream_add_variables(ngx_conf_t *cf);
134static ngx_int_t ngx_http_upstream_addr_variable(ngx_http_request_t *r,
135 ngx_http_variable_value_t *v, uintptr_t data);
136static ngx_int_t ngx_http_upstream_status_variable(ngx_http_request_t *r,
137 ngx_http_variable_value_t *v, uintptr_t data);
138static ngx_int_t ngx_http_upstream_response_time_variable(ngx_http_request_t *r,
139 ngx_http_variable_value_t *v, uintptr_t data);
140static ngx_int_t ngx_http_upstream_response_length_variable(
141 ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data);
142
143static char *ngx_http_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy);
144static char *ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd,
145 void *conf);
146
147static ngx_addr_t *ngx_http_upstream_get_local(ngx_http_request_t *r,
148 ngx_http_upstream_local_t *local);
149
150static void *ngx_http_upstream_create_main_conf(ngx_conf_t *cf);
151static char *ngx_http_upstream_init_main_conf(ngx_conf_t *cf, void *conf);
152
153#if (NGX_HTTP_SSL)
154static void ngx_http_upstream_ssl_init_connection(ngx_http_request_t *,
155 ngx_http_upstream_t *u, ngx_connection_t *c);
156static void ngx_http_upstream_ssl_handshake(ngx_connection_t *c);
157#endif
158
159
160ngx_http_upstream_header_t ngx_http_upstream_headers_in[] = {
161
162 { ngx_string("Status"){ sizeof("Status") - 1, (u_char *) "Status" },
163 ngx_http_upstream_process_header_line,
164 offsetof(ngx_http_upstream_headers_in_t, status)__builtin_offsetof(ngx_http_upstream_headers_in_t, status),
165 ngx_http_upstream_copy_header_line, 0, 0 },
166
167 { ngx_string("Content-Type"){ sizeof("Content-Type") - 1, (u_char *) "Content-Type" },
168 ngx_http_upstream_process_header_line,
169 offsetof(ngx_http_upstream_headers_in_t, content_type)__builtin_offsetof(ngx_http_upstream_headers_in_t, content_type
)
,
170 ngx_http_upstream_copy_content_type, 0, 1 },
171
172 { ngx_string("Content-Length"){ sizeof("Content-Length") - 1, (u_char *) "Content-Length" },
173 ngx_http_upstream_process_content_length,
174 offsetof(ngx_http_upstream_headers_in_t, content_length)__builtin_offsetof(ngx_http_upstream_headers_in_t, content_length
)
,
175 ngx_http_upstream_ignore_header_line, 0, 0 },
176
177 { ngx_string("Date"){ sizeof("Date") - 1, (u_char *) "Date" },
178 ngx_http_upstream_process_header_line,
179 offsetof(ngx_http_upstream_headers_in_t, date)__builtin_offsetof(ngx_http_upstream_headers_in_t, date),
180 ngx_http_upstream_copy_header_line,
181 offsetof(ngx_http_headers_out_t, date)__builtin_offsetof(ngx_http_headers_out_t, date), 0 },
182
183 { ngx_string("Last-Modified"){ sizeof("Last-Modified") - 1, (u_char *) "Last-Modified" },
184 ngx_http_upstream_process_header_line,
185 offsetof(ngx_http_upstream_headers_in_t, last_modified)__builtin_offsetof(ngx_http_upstream_headers_in_t, last_modified
)
,
186 ngx_http_upstream_copy_last_modified, 0, 0 },
187
188 { ngx_string("ETag"){ sizeof("ETag") - 1, (u_char *) "ETag" },
189 ngx_http_upstream_process_header_line,
190 offsetof(ngx_http_upstream_headers_in_t, etag)__builtin_offsetof(ngx_http_upstream_headers_in_t, etag),
191 ngx_http_upstream_copy_header_line,
192 offsetof(ngx_http_headers_out_t, etag)__builtin_offsetof(ngx_http_headers_out_t, etag), 0 },
193
194 { ngx_string("Server"){ sizeof("Server") - 1, (u_char *) "Server" },
195 ngx_http_upstream_process_header_line,
196 offsetof(ngx_http_upstream_headers_in_t, server)__builtin_offsetof(ngx_http_upstream_headers_in_t, server),
197 ngx_http_upstream_copy_header_line,
198 offsetof(ngx_http_headers_out_t, server)__builtin_offsetof(ngx_http_headers_out_t, server), 0 },
199
200 { ngx_string("WWW-Authenticate"){ sizeof("WWW-Authenticate") - 1, (u_char *) "WWW-Authenticate"
}
,
201 ngx_http_upstream_process_header_line,
202 offsetof(ngx_http_upstream_headers_in_t, www_authenticate)__builtin_offsetof(ngx_http_upstream_headers_in_t, www_authenticate
)
,
203 ngx_http_upstream_copy_header_line, 0, 0 },
204
205 { ngx_string("Location"){ sizeof("Location") - 1, (u_char *) "Location" },
206 ngx_http_upstream_process_header_line,
207 offsetof(ngx_http_upstream_headers_in_t, location)__builtin_offsetof(ngx_http_upstream_headers_in_t, location),
208 ngx_http_upstream_rewrite_location, 0, 0 },
209
210 { ngx_string("Refresh"){ sizeof("Refresh") - 1, (u_char *) "Refresh" },
211 ngx_http_upstream_ignore_header_line, 0,
212 ngx_http_upstream_rewrite_refresh, 0, 0 },
213
214 { ngx_string("Set-Cookie"){ sizeof("Set-Cookie") - 1, (u_char *) "Set-Cookie" },
215 ngx_http_upstream_process_set_cookie, 0,
216 ngx_http_upstream_rewrite_set_cookie, 0, 1 },
217
218 { ngx_string("Content-Disposition"){ sizeof("Content-Disposition") - 1, (u_char *) "Content-Disposition"
}
,
219 ngx_http_upstream_ignore_header_line, 0,
220 ngx_http_upstream_copy_header_line, 0, 1 },
221
222 { ngx_string("Cache-Control"){ sizeof("Cache-Control") - 1, (u_char *) "Cache-Control" },
223 ngx_http_upstream_process_cache_control, 0,
224 ngx_http_upstream_copy_multi_header_lines,
225 offsetof(ngx_http_headers_out_t, cache_control)__builtin_offsetof(ngx_http_headers_out_t, cache_control), 1 },
226
227 { ngx_string("Expires"){ sizeof("Expires") - 1, (u_char *) "Expires" },
228 ngx_http_upstream_process_expires, 0,
229 ngx_http_upstream_copy_header_line,
230 offsetof(ngx_http_headers_out_t, expires)__builtin_offsetof(ngx_http_headers_out_t, expires), 1 },
231
232 { ngx_string("Accept-Ranges"){ sizeof("Accept-Ranges") - 1, (u_char *) "Accept-Ranges" },
233 ngx_http_upstream_process_header_line,
234 offsetof(ngx_http_upstream_headers_in_t, accept_ranges)__builtin_offsetof(ngx_http_upstream_headers_in_t, accept_ranges
)
,
235 ngx_http_upstream_copy_allow_ranges,
236 offsetof(ngx_http_headers_out_t, accept_ranges)__builtin_offsetof(ngx_http_headers_out_t, accept_ranges), 1 },
237
238 { ngx_string("Connection"){ sizeof("Connection") - 1, (u_char *) "Connection" },
239 ngx_http_upstream_process_connection, 0,
240 ngx_http_upstream_ignore_header_line, 0, 0 },
241
242 { ngx_string("Keep-Alive"){ sizeof("Keep-Alive") - 1, (u_char *) "Keep-Alive" },
243 ngx_http_upstream_ignore_header_line, 0,
244 ngx_http_upstream_ignore_header_line, 0, 0 },
245
246 { ngx_string("X-Powered-By"){ sizeof("X-Powered-By") - 1, (u_char *) "X-Powered-By" },
247 ngx_http_upstream_ignore_header_line, 0,
248 ngx_http_upstream_copy_header_line, 0, 0 },
249
250 { ngx_string("X-Accel-Expires"){ sizeof("X-Accel-Expires") - 1, (u_char *) "X-Accel-Expires"
}
,
251 ngx_http_upstream_process_accel_expires, 0,
252 ngx_http_upstream_copy_header_line, 0, 0 },
253
254 { ngx_string("X-Accel-Redirect"){ sizeof("X-Accel-Redirect") - 1, (u_char *) "X-Accel-Redirect"
}
,
255 ngx_http_upstream_process_header_line,
256 offsetof(ngx_http_upstream_headers_in_t, x_accel_redirect)__builtin_offsetof(ngx_http_upstream_headers_in_t, x_accel_redirect
)
,
257 ngx_http_upstream_copy_header_line, 0, 0 },
258
259 { ngx_string("X-Accel-Limit-Rate"){ sizeof("X-Accel-Limit-Rate") - 1, (u_char *) "X-Accel-Limit-Rate"
}
,
260 ngx_http_upstream_process_limit_rate, 0,
261 ngx_http_upstream_copy_header_line, 0, 0 },
262
263 { ngx_string("X-Accel-Buffering"){ sizeof("X-Accel-Buffering") - 1, (u_char *) "X-Accel-Buffering"
}
,
264 ngx_http_upstream_process_buffering, 0,
265 ngx_http_upstream_copy_header_line, 0, 0 },
266
267 { ngx_string("X-Accel-Charset"){ sizeof("X-Accel-Charset") - 1, (u_char *) "X-Accel-Charset"
}
,
268 ngx_http_upstream_process_charset, 0,
269 ngx_http_upstream_copy_header_line, 0, 0 },
270
271 { ngx_string("Transfer-Encoding"){ sizeof("Transfer-Encoding") - 1, (u_char *) "Transfer-Encoding"
}
,
272 ngx_http_upstream_process_transfer_encoding, 0,
273 ngx_http_upstream_ignore_header_line, 0, 0 },
274
275#if (NGX_HTTP_GZIP1)
276 { ngx_string("Content-Encoding"){ sizeof("Content-Encoding") - 1, (u_char *) "Content-Encoding"
}
,
277 ngx_http_upstream_process_header_line,
278 offsetof(ngx_http_upstream_headers_in_t, content_encoding)__builtin_offsetof(ngx_http_upstream_headers_in_t, content_encoding
)
,
279 ngx_http_upstream_copy_content_encoding, 0, 0 },
280#endif
281
282 { ngx_null_string{ 0, ((void*)0) }, NULL((void*)0), 0, NULL((void*)0), 0, 0 }
283};
284
285
286static ngx_command_t ngx_http_upstream_commands[] = {
287
288 { ngx_string("upstream"){ sizeof("upstream") - 1, (u_char *) "upstream" },
289 NGX_HTTP_MAIN_CONF0x02000000|NGX_CONF_BLOCK0x00000100|NGX_CONF_TAKE10x00000002,
290 ngx_http_upstream,
291 0,
292 0,
293 NULL((void*)0) },
294
295 { ngx_string("server"){ sizeof("server") - 1, (u_char *) "server" },
296 NGX_HTTP_UPS_CONF0x10000000|NGX_CONF_1MORE0x00000800,
297 ngx_http_upstream_server,
298 NGX_HTTP_SRV_CONF_OFFSET__builtin_offsetof(ngx_http_conf_ctx_t, srv_conf),
299 0,
300 NULL((void*)0) },
301
302 ngx_null_command{ { 0, ((void*)0) }, 0, ((void*)0), 0, 0, ((void*)0) }
303};
304
305
306static ngx_http_module_t ngx_http_upstream_module_ctx = {
307 ngx_http_upstream_add_variables, /* preconfiguration */
308 NULL((void*)0), /* postconfiguration */
309
310 ngx_http_upstream_create_main_conf, /* create main configuration */
311 ngx_http_upstream_init_main_conf, /* init main configuration */
312
313 NULL((void*)0), /* create server configuration */
314 NULL((void*)0), /* merge server configuration */
315
316 NULL((void*)0), /* create location configuration */
317 NULL((void*)0) /* merge location configuration */
318};
319
320
321ngx_module_t ngx_http_upstream_module = {
322 NGX_MODULE_V10, 0, 0, 0, 0, 0, 1,
323 &ngx_http_upstream_module_ctx, /* module context */
324 ngx_http_upstream_commands, /* module directives */
325 NGX_HTTP_MODULE0x50545448, /* module type */
326 NULL((void*)0), /* init master */
327 NULL((void*)0), /* init module */
328 NULL((void*)0), /* init process */
329 NULL((void*)0), /* init thread */
330 NULL((void*)0), /* exit thread */
331 NULL((void*)0), /* exit process */
332 NULL((void*)0), /* exit master */
333 NGX_MODULE_V1_PADDING0, 0, 0, 0, 0, 0, 0, 0
334};
335
336
337static ngx_http_variable_t ngx_http_upstream_vars[] = {
338
339 { ngx_string("upstream_addr"){ sizeof("upstream_addr") - 1, (u_char *) "upstream_addr" }, NULL((void*)0),
340 ngx_http_upstream_addr_variable, 0,
341 NGX_HTTP_VAR_NOCACHEABLE2, 0 },
342
343 { ngx_string("upstream_status"){ sizeof("upstream_status") - 1, (u_char *) "upstream_status"
}
, NULL((void*)0),
344 ngx_http_upstream_status_variable, 0,
345 NGX_HTTP_VAR_NOCACHEABLE2, 0 },
346
347 { ngx_string("upstream_response_time"){ sizeof("upstream_response_time") - 1, (u_char *) "upstream_response_time"
}
, NULL((void*)0),
348 ngx_http_upstream_response_time_variable, 0,
349 NGX_HTTP_VAR_NOCACHEABLE2, 0 },
350
351 { ngx_string("upstream_response_length"){ sizeof("upstream_response_length") - 1, (u_char *) "upstream_response_length"
}
, NULL((void*)0),
352 ngx_http_upstream_response_length_variable, 0,
353 NGX_HTTP_VAR_NOCACHEABLE2, 0 },
354
355#if (NGX_HTTP_CACHE1)
356
357 { ngx_string("upstream_cache_status"){ sizeof("upstream_cache_status") - 1, (u_char *) "upstream_cache_status"
}
, NULL((void*)0),
358 ngx_http_upstream_cache_status, 0,
359 NGX_HTTP_VAR_NOCACHEABLE2, 0 },
360
361#endif
362
363 { ngx_null_string{ 0, ((void*)0) }, NULL((void*)0), NULL((void*)0), 0, 0, 0 }
364};
365
366
367static ngx_http_upstream_next_t ngx_http_upstream_next_errors[] = {
368 { 500, NGX_HTTP_UPSTREAM_FT_HTTP_5000x00000010 },
369 { 502, NGX_HTTP_UPSTREAM_FT_HTTP_5020x00000020 },
370 { 503, NGX_HTTP_UPSTREAM_FT_HTTP_5030x00000040 },
371 { 504, NGX_HTTP_UPSTREAM_FT_HTTP_5040x00000080 },
372 { 404, NGX_HTTP_UPSTREAM_FT_HTTP_4040x00000100 },
373 { 0, 0 }
374};
375
376
377ngx_conf_bitmask_t ngx_http_upstream_cache_method_mask[] = {
378 { ngx_string("GET"){ sizeof("GET") - 1, (u_char *) "GET" }, NGX_HTTP_GET0x0002},
379 { ngx_string("HEAD"){ sizeof("HEAD") - 1, (u_char *) "HEAD" }, NGX_HTTP_HEAD0x0004 },
380 { ngx_string("POST"){ sizeof("POST") - 1, (u_char *) "POST" }, NGX_HTTP_POST0x0008 },
381 { ngx_null_string{ 0, ((void*)0) }, 0 }
382};
383
384
385ngx_conf_bitmask_t ngx_http_upstream_ignore_headers_masks[] = {
386 { ngx_string("X-Accel-Redirect"){ sizeof("X-Accel-Redirect") - 1, (u_char *) "X-Accel-Redirect"
}
, NGX_HTTP_UPSTREAM_IGN_XA_REDIRECT0x00000002 },
387 { ngx_string("X-Accel-Expires"){ sizeof("X-Accel-Expires") - 1, (u_char *) "X-Accel-Expires"
}
, NGX_HTTP_UPSTREAM_IGN_XA_EXPIRES0x00000004 },
388 { ngx_string("X-Accel-Limit-Rate"){ sizeof("X-Accel-Limit-Rate") - 1, (u_char *) "X-Accel-Limit-Rate"
}
, NGX_HTTP_UPSTREAM_IGN_XA_LIMIT_RATE0x00000040 },
389 { ngx_string("X-Accel-Buffering"){ sizeof("X-Accel-Buffering") - 1, (u_char *) "X-Accel-Buffering"
}
, NGX_HTTP_UPSTREAM_IGN_XA_BUFFERING0x00000080 },
390 { ngx_string("X-Accel-Charset"){ sizeof("X-Accel-Charset") - 1, (u_char *) "X-Accel-Charset"
}
, NGX_HTTP_UPSTREAM_IGN_XA_CHARSET0x00000100 },
391 { ngx_string("Expires"){ sizeof("Expires") - 1, (u_char *) "Expires" }, NGX_HTTP_UPSTREAM_IGN_EXPIRES0x00000008 },
392 { ngx_string("Cache-Control"){ sizeof("Cache-Control") - 1, (u_char *) "Cache-Control" }, NGX_HTTP_UPSTREAM_IGN_CACHE_CONTROL0x00000010 },
393 { ngx_string("Set-Cookie"){ sizeof("Set-Cookie") - 1, (u_char *) "Set-Cookie" }, NGX_HTTP_UPSTREAM_IGN_SET_COOKIE0x00000020 },
394 { ngx_null_string{ 0, ((void*)0) }, 0 }
395};
396
397
398ngx_int_t
399ngx_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((void*)0)) {
412 return NGX_ERROR-1;
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_CACHE1)
424 r->cache = NULL((void*)0);
425#endif
426
427 u->headers_in.content_length_n = -1;
428
429 return NGX_OK0;
430}
431
432
433void
434ngx_http_upstream_init(ngx_http_request_t *r)
435{
436 ngx_connection_t *c;
437
438 c = r->connection;
439
440 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
441 "http init upstream, client timer: %d", c->read->timer_set);
442
443#if (NGX_HTTP_SPDY)
444 if (r->spdy_stream) {
445 ngx_http_upstream_init_request(r);
446 return;
447 }
448#endif
449
450 if (c->read->timer_set) {
451 ngx_del_timerngx_event_del_timer(c->read);
452 }
453
454 if (ngx_event_flags & NGX_USE_CLEAR_EVENT0x00000004) {
455
456 if (!c->write->active) {
457 if (ngx_add_eventngx_event_actions.add(c->write, NGX_WRITE_EVENT(-2), NGX_CLEAR_EVENT0x0020)
458 == NGX_ERROR-1)
459 {
460 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR500);
461 return;
462 }
463 }
464 }
465
466 ngx_http_upstream_init_request(r);
467}
468
469
470static void
471ngx_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_CACHE1)
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-3) {
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-4) {
503 return;
504 }
505
506 if (rc != NGX_DECLINED-5) {
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
521 if (r->request_body) {
522 u->request_bufs = r->request_body->bufs;
523 }
524
525 if (u->create_request(r) != NGX_OK0) {
526 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR500);
527 return;
528 }
529
530 u->peer.local = ngx_http_upstream_get_local(r, u->conf->local);
531
532 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module)(r)->loc_conf[ngx_http_core_module.ctx_index];
533
534 u->output.alignment = clcf->directio_alignment;
535 u->output.pool = r->pool;
536 u->output.bufs.num = 1;
537 u->output.bufs.size = clcf->client_body_buffer_size;
538 u->output.output_filter = ngx_chain_writer;
539 u->output.filter_ctx = &u->writer;
540
541 u->writer.pool = r->pool;
542
543 if (r->upstream_states == NULL((void*)0)) {
544
545 r->upstream_states = ngx_array_create(r->pool, 1,
546 sizeof(ngx_http_upstream_state_t));
547 if (r->upstream_states == NULL((void*)0)) {
548 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR500);
549 return;
550 }
551
552 } else {
553
554 u->state = ngx_array_push(r->upstream_states);
555 if (u->state == NULL((void*)0)) {
556 ngx_http_upstream_finalize_request(r, u,
557 NGX_HTTP_INTERNAL_SERVER_ERROR500);
558 return;
559 }
560
561 ngx_memzero(u->state, sizeof(ngx_http_upstream_state_t))(void) ((__builtin_object_size (u->state, 0) != (size_t) -
1) ? __builtin___memset_chk (u->state, 0, sizeof(ngx_http_upstream_state_t
), __builtin_object_size (u->state, 0)) : __inline_memset_chk
(u->state, 0, sizeof(ngx_http_upstream_state_t)))
;
562 }
563
564 cln = ngx_http_cleanup_add(r, 0);
565 if (cln == NULL((void*)0)) {
566 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR500);
567 return;
568 }
569
570 cln->handler = ngx_http_upstream_cleanup;
571 cln->data = r;
572 u->cleanup = &cln->handler;
573
574 if (u->resolved == NULL((void*)0)) {
575
576 uscf = u->conf->upstream;
577
578 } else {
579
580 if (u->resolved->sockaddr) {
581
582 if (ngx_http_upstream_create_round_robin_peer(r, u->resolved)
583 != NGX_OK0)
584 {
585 ngx_http_upstream_finalize_request(r, u,
586 NGX_HTTP_INTERNAL_SERVER_ERROR500);
587 return;
588 }
589
590 ngx_http_upstream_connect(r, u);
591
592 return;
593 }
594
595 host = &u->resolved->host;
596
597 umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module)(r)->main_conf[ngx_http_upstream_module.ctx_index];
598
599 uscfp = umcf->upstreams.elts;
600
601 for (i = 0; i < umcf->upstreams.nelts; i++) {
602
603 uscf = uscfp[i];
604
605 if (uscf->host.len == host->len
606 && ((uscf->port == 0 && u->resolved->no_port)
607 || uscf->port == u->resolved->port)
608 && ngx_memcmp(uscf->host.data, host->data, host->len)memcmp((const char *) uscf->host.data, (const char *) host
->data, host->len)
== 0)
609 {
610 goto found;
611 }
612 }
613
614 if (u->resolved->port == 0) {
615 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,if ((r->connection->log)->log_level >= 4) ngx_log_error_core
(4, r->connection->log, 0, "no port in upstream \"%V\""
, host)
616 "no port in upstream \"%V\"", host)if ((r->connection->log)->log_level >= 4) ngx_log_error_core
(4, r->connection->log, 0, "no port in upstream \"%V\""
, host)
;
617 ngx_http_upstream_finalize_request(r, u,
618 NGX_HTTP_INTERNAL_SERVER_ERROR500);
619 return;
620 }
621
622 temp.name = *host;
623
624 ctx = ngx_resolve_start(clcf->resolver, &temp);
625 if (ctx == NULL((void*)0)) {
626 ngx_http_upstream_finalize_request(r, u,
627 NGX_HTTP_INTERNAL_SERVER_ERROR500);
628 return;
629 }
630
631 if (ctx == NGX_NO_RESOLVER(void *) -1) {
632 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,if ((r->connection->log)->log_level >= 4) ngx_log_error_core
(4, r->connection->log, 0, "no resolver defined to resolve %V"
, host)
633 "no resolver defined to resolve %V", host)if ((r->connection->log)->log_level >= 4) ngx_log_error_core
(4, r->connection->log, 0, "no resolver defined to resolve %V"
, host)
;
634
635 ngx_http_upstream_finalize_request(r, u, NGX_HTTP_BAD_GATEWAY502);
636 return;
637 }
638
639 ctx->name = *host;
640 ctx->type = NGX_RESOLVE_A1;
641 ctx->handler = ngx_http_upstream_resolve_handler;
642 ctx->data = r;
643 ctx->timeout = clcf->resolver_timeout;
644
645 u->resolved->ctx = ctx;
646
647 if (ngx_resolve_name(ctx) != NGX_OK0) {
648 u->resolved->ctx = NULL((void*)0);
649 ngx_http_upstream_finalize_request(r, u,
650 NGX_HTTP_INTERNAL_SERVER_ERROR500);
651 return;
652 }
653
654 return;
655 }
656
657found:
658
659 if (uscf == NULL((void*)0)) {
660 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,if ((r->connection->log)->log_level >= 2) ngx_log_error_core
(2, r->connection->log, 0, "no upstream configuration")
661 "no upstream configuration")if ((r->connection->log)->log_level >= 2) ngx_log_error_core
(2, r->connection->log, 0, "no upstream configuration")
;
662 ngx_http_upstream_finalize_request(r, u,
663 NGX_HTTP_INTERNAL_SERVER_ERROR500);
664 return;
665 }
666
667 if (uscf->peer.init(r, uscf) != NGX_OK0) {
668 ngx_http_upstream_finalize_request(r, u,
669 NGX_HTTP_INTERNAL_SERVER_ERROR500);
670 return;
671 }
672
673 ngx_http_upstream_connect(r, u);
674}
675
676
677#if (NGX_HTTP_CACHE1)
678
679static ngx_int_t
680ngx_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((void*)0)) {
688
689 if (!(r->method & u->conf->cache_methods)) {
690 return NGX_DECLINED-5;
691 }
692
693 if (r->method & NGX_HTTP_HEAD0x0004) {
694 u->method = ngx_http_core_get_method;
695 }
696
697 if (ngx_http_file_cache_new(r) != NGX_OK0) {
698 return NGX_ERROR-1;
699 }
700
701 if (u->create_key(r) != NGX_OK0) {
702 return NGX_ERROR-1;
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,if ((r->connection->log)->log_level >= 4) ngx_log_error_core
(4, r->connection->log, 0, "%V_buffer_size %uz is not enough for cache key, "
"it should increased at least to %uz", &u->conf->module
, u->conf->buffer_size, (((r->cache->header_start
+ 256) + (1024 - 1)) & ~(1024 - 1)))
711 "%V_buffer_size %uz is not enough for cache key, "if ((r->connection->log)->log_level >= 4) ngx_log_error_core
(4, r->connection->log, 0, "%V_buffer_size %uz is not enough for cache key, "
"it should increased at least to %uz", &u->conf->module
, u->conf->buffer_size, (((r->cache->header_start
+ 256) + (1024 - 1)) & ~(1024 - 1)))
712 "it should increased at least to %uz",if ((r->connection->log)->log_level >= 4) ngx_log_error_core
(4, r->connection->log, 0, "%V_buffer_size %uz is not enough for cache key, "
"it should increased at least to %uz", &u->conf->module
, u->conf->buffer_size, (((r->cache->header_start
+ 256) + (1024 - 1)) & ~(1024 - 1)))
713 &u->conf->module, u->conf->buffer_size,if ((r->connection->log)->log_level >= 4) ngx_log_error_core
(4, r->connection->log, 0, "%V_buffer_size %uz is not enough for cache key, "
"it should increased at least to %uz", &u->conf->module
, u->conf->buffer_size, (((r->cache->header_start
+ 256) + (1024 - 1)) & ~(1024 - 1)))
714 ngx_align(r->cache->header_start + 256, 1024))if ((r->connection->log)->log_level >= 4) ngx_log_error_core
(4, r->connection->log, 0, "%V_buffer_size %uz is not enough for cache key, "
"it should increased at least to %uz", &u->conf->module
, u->conf->buffer_size, (((r->cache->header_start
+ 256) + (1024 - 1)) & ~(1024 - 1)))
;
715
716 r->cache = NULL((void*)0);
717 return NGX_DECLINED-5;
718 }
719
720 u->cacheable = 1;
721
722 switch (ngx_http_test_predicates(r, u->conf->cache_bypass)) {
723
724 case NGX_ERROR-1:
725 return NGX_ERROR-1;
726
727 case NGX_DECLINED-5:
728 u->cache_status = NGX_HTTP_CACHE_BYPASS2;
729 return NGX_DECLINED-5;
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_MISS1;
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_UPDATING5:
755
756 if (u->conf->cache_use_stale & NGX_HTTP_UPSTREAM_FT_UPDATING0x00000200) {
757 u->cache_status = rc;
758 rc = NGX_OK0;
759
760 } else {
761 rc = NGX_HTTP_CACHE_STALE4;
762 }
763
764 break;
765
766 case NGX_OK0:
767 u->cache_status = NGX_HTTP_CACHE_HIT6;
768 }
769
770 switch (rc) {
771
772 case NGX_OK0:
773
774 rc = ngx_http_upstream_cache_send(r, u);
775
776 if (rc != NGX_HTTP_UPSTREAM_INVALID_HEADER40) {
777 return rc;
778 }
779
780 break;
781
782 case NGX_HTTP_CACHE_STALE4:
783
784 c->valid_sec = 0;
785 u->buffer.start = NULL((void*)0);
786 u->cache_status = NGX_HTTP_CACHE_EXPIRED3;
787
788 break;
789
790 case NGX_DECLINED-5:
791
792 if ((size_t) (u->buffer.end - u->buffer.start) < u->conf->buffer_size) {
793 u->buffer.start = NULL((void*)0);
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_SCARCE7:
803
804 u->cacheable = 0;
805
806 break;
807
808 case NGX_AGAIN-2:
809
810 return NGX_BUSY-3;
811
812 case NGX_ERROR-1:
813
814 return NGX_ERROR-1;
815
816 default:
817
818 /* cached NGX_HTTP_BAD_GATEWAY, NGX_HTTP_GATEWAY_TIME_OUT, etc. */
819
820 u->cache_status = NGX_HTTP_CACHE_HIT6;
821
822 return rc;
823 }
824
825 r->cached = 0;
826
827 return NGX_DECLINED-5;
828}
829
830
831static ngx_int_t
832ngx_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_99;
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))(void) ((__builtin_object_size (&u->headers_in, 0) != (
size_t) -1) ? __builtin___memset_chk (&u->headers_in, 0
, sizeof(ngx_http_upstream_headers_in_t), __builtin_object_size
(&u->headers_in, 0)) : __inline_memset_chk (&u->
headers_in, 0, 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_OK0)
856 {
857 return NGX_ERROR-1;
858 }
859
860 rc = u->process_header(r);
861
862 if (rc == NGX_OK0) {
863
864 if (ngx_http_upstream_process_headers(r, u) != NGX_OK0) {
865 return NGX_DONE-4;
866 }
867
868 return ngx_http_cache_send(r);
869 }
870
871 if (rc == NGX_ERROR-1) {
872 return NGX_ERROR-1;
873 }
874
875 /* rc == NGX_HTTP_UPSTREAM_INVALID_HEADER */
876
877 /* TODO: delete file */
878
879 return rc;
880}
881
882#endif
883
884
885static void
886ngx_http_upstream_resolve_handler(ngx_resolver_ctx_t *ctx)
887{
888 ngx_connection_t *c;
889 ngx_http_request_t *r;
890 ngx_http_upstream_t *u;
891 ngx_http_upstream_resolved_t *ur;
892
893 r = ctx->data;
894 c = r->connection;
895
896 u = r->upstream;
897 ur = u->resolved;
898
899 if (ctx->state) {
900 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,if ((r->connection->log)->log_level >= 4) ngx_log_error_core
(4, r->connection->log, 0, "%V could not be resolved (%i: %s)"
, &ctx->name, ctx->state, ngx_resolver_strerror(ctx
->state))
901 "%V could not be resolved (%i: %s)",if ((r->connection->log)->log_level >= 4) ngx_log_error_core
(4, r->connection->log, 0, "%V could not be resolved (%i: %s)"
, &ctx->name, ctx->state, ngx_resolver_strerror(ctx
->state))
902 &ctx->name, ctx->state,if ((r->connection->log)->log_level >= 4) ngx_log_error_core
(4, r->connection->log, 0, "%V could not be resolved (%i: %s)"
, &ctx->name, ctx->state, ngx_resolver_strerror(ctx
->state))
903 ngx_resolver_strerror(ctx->state))if ((r->connection->log)->log_level >= 4) ngx_log_error_core
(4, r->connection->log, 0, "%V could not be resolved (%i: %s)"
, &ctx->name, ctx->state, ngx_resolver_strerror(ctx
->state))
;
904
905 ngx_http_upstream_finalize_request(r, u, NGX_HTTP_BAD_GATEWAY502);
906 goto failed;
907 }
908
909 ur->naddrs = ctx->naddrs;
910 ur->addrs = ctx->addrs;
911
912#if (NGX_DEBUG)
913 {
914 in_addr_t addr;
915 ngx_uint_t i;
916
917 for (i = 0; i < ctx->naddrs; i++) {
918 addr = ntohl(ur->addrs[i])(__builtin_constant_p(ur->addrs[i]) ? ((__uint32_t)((((__uint32_t
)(ur->addrs[i]) & 0xff000000) >> 24) | (((__uint32_t
)(ur->addrs[i]) & 0x00ff0000) >> 8) | (((__uint32_t
)(ur->addrs[i]) & 0x0000ff00) << 8) | (((__uint32_t
)(ur->addrs[i]) & 0x000000ff) << 24))) : _OSSwapInt32
(ur->addrs[i]))
;
919
920 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
921 "name was resolved to %ud.%ud.%ud.%ud",
922 (addr >> 24) & 0xff, (addr >> 16) & 0xff,
923 (addr >> 8) & 0xff, addr & 0xff);
924 }
925 }
926#endif
927
928 if (ngx_http_upstream_create_round_robin_peer(r, ur) != NGX_OK0) {
929 ngx_http_upstream_finalize_request(r, u,
930 NGX_HTTP_INTERNAL_SERVER_ERROR500);
931 goto failed;
932 }
933
934 ngx_resolve_name_done(ctx);
935 ur->ctx = NULL((void*)0);
936
937 ngx_http_upstream_connect(r, u);
938
939failed:
940
941 ngx_http_run_posted_requests(c);
942}
943
944
945static void
946ngx_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);
973}
974
975
976static void
977ngx_http_upstream_rd_check_broken_connection(ngx_http_request_t *r)
978{
979 ngx_http_upstream_check_broken_connection(r, r->connection->read);
980}
981
982
983static void
984ngx_http_upstream_wr_check_broken_connection(ngx_http_request_t *r)
985{
986 ngx_http_upstream_check_broken_connection(r, r->connection->write);
987}
988
989
990static void
991ngx_http_upstream_check_broken_connection(ngx_http_request_t *r,
992 ngx_event_t *ev)
993{
994 int n;
995 char buf[1];
996 ngx_err_t err;
997 ngx_int_t event;
998 ngx_connection_t *c;
999 ngx_http_upstream_t *u;
1000
1001 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, ev->log, 0,
1002 "http upstream check client, write event:%d, \"%V\"",
1003 ev->write, &r->uri);
1004
1005 c = r->connection;
1006 u = r->upstream;
1007
1008 if (c->error) {
1009 if ((ngx_event_flags & NGX_USE_LEVEL_EVENT0x00000001) && ev->active) {
1010
1011 event = ev->write ? NGX_WRITE_EVENT(-2) : NGX_READ_EVENT(-1);
1012
1013 if (ngx_del_eventngx_event_actions.del(ev, event, 0) != NGX_OK0) {
1014 ngx_http_upstream_finalize_request(r, u,
1015 NGX_HTTP_INTERNAL_SERVER_ERROR500);
1016 return;
1017 }
1018 }
1019
1020 if (!u->cacheable) {
1021 ngx_http_upstream_finalize_request(r, u,
1022 NGX_HTTP_CLIENT_CLOSED_REQUEST499);
1023 }
1024
1025 return;
1026 }
1027
1028#if (NGX_HTTP_SPDY)
1029 if (r->spdy_stream) {
1030 return;
1031 }
1032#endif
1033
1034#if (NGX_HAVE_KQUEUE1)
1035
1036 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT0x00000008) {
1037
1038 if (!ev->pending_eof) {
1039 return;
1040 }
1041
1042 ev->eof = 1;
1043 c->error = 1;
1044
1045 if (ev->kq_errno) {
1046 ev->error = 1;
1047 }
1048
1049 if (!u->cacheable && u->peer.connection) {
1050 ngx_log_error(NGX_LOG_INFO, ev->log, ev->kq_errno,if ((ev->log)->log_level >= 7) ngx_log_error_core(7,
ev->log, ev->kq_errno, "kevent() reported that client prematurely closed "
"connection, so upstream connection is closed too")
1051 "kevent() reported that client prematurely closed "if ((ev->log)->log_level >= 7) ngx_log_error_core(7,
ev->log, ev->kq_errno, "kevent() reported that client prematurely closed "
"connection, so upstream connection is closed too")
1052 "connection, so upstream connection is closed too")if ((ev->log)->log_level >= 7) ngx_log_error_core(7,
ev->log, ev->kq_errno, "kevent() reported that client prematurely closed "
"connection, so upstream connection is closed too")
;
1053 ngx_http_upstream_finalize_request(r, u,
1054 NGX_HTTP_CLIENT_CLOSED_REQUEST499);
1055 return;
1056 }
1057
1058 ngx_log_error(NGX_LOG_INFO, ev->log, ev->kq_errno,if ((ev->log)->log_level >= 7) ngx_log_error_core(7,
ev->log, ev->kq_errno, "kevent() reported that client prematurely closed "
"connection")
1059 "kevent() reported that client prematurely closed "if ((ev->log)->log_level >= 7) ngx_log_error_core(7,
ev->log, ev->kq_errno, "kevent() reported that client prematurely closed "
"connection")
1060 "connection")if ((ev->log)->log_level >= 7) ngx_log_error_core(7,
ev->log, ev->kq_errno, "kevent() reported that client prematurely closed "
"connection")
;
1061
1062 if (u->peer.connection == NULL((void*)0)) {
1063 ngx_http_upstream_finalize_request(r, u,
1064 NGX_HTTP_CLIENT_CLOSED_REQUEST499);
1065 }
1066
1067 return;
1068 }
1069
1070#endif
1071
1072 n = recv(c->fd, buf, 1, MSG_PEEK0x2);
1073
1074 err = ngx_socket_errno(*__error());
1075
1076 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ev->log, err,
1077 "http upstream recv(): %d", n);
1078
1079 if (ev->write && (n >= 0 || err == NGX_EAGAIN35)) {
1080 return;
1081 }
1082
1083 if ((ngx_event_flags & NGX_USE_LEVEL_EVENT0x00000001) && ev->active) {
1084
1085 event = ev->write ? NGX_WRITE_EVENT(-2) : NGX_READ_EVENT(-1);
1086
1087 if (ngx_del_eventngx_event_actions.del(ev, event, 0) != NGX_OK0) {
1088 ngx_http_upstream_finalize_request(r, u,
1089 NGX_HTTP_INTERNAL_SERVER_ERROR500);
1090 return;
1091 }
1092 }
1093
1094 if (n > 0) {
1095 return;
1096 }
1097
1098 if (n == -1) {
1099 if (err == NGX_EAGAIN35) {
1100 return;
1101 }
1102
1103 ev->error = 1;
1104
1105 } else { /* n == 0 */
1106 err = 0;
1107 }
1108
1109 ev->eof = 1;
1110 c->error = 1;
1111
1112 if (!u->cacheable && u->peer.connection) {
1113 ngx_log_error(NGX_LOG_INFO, ev->log, err,if ((ev->log)->log_level >= 7) ngx_log_error_core(7,
ev->log, err, "client prematurely closed connection, " "so upstream connection is closed too"
)
1114 "client prematurely closed connection, "if ((ev->log)->log_level >= 7) ngx_log_error_core(7,
ev->log, err, "client prematurely closed connection, " "so upstream connection is closed too"
)
1115 "so upstream connection is closed too")if ((ev->log)->log_level >= 7) ngx_log_error_core(7,
ev->log, err, "client prematurely closed connection, " "so upstream connection is closed too"
)
;
1116 ngx_http_upstream_finalize_request(r, u,
1117 NGX_HTTP_CLIENT_CLOSED_REQUEST499);
1118 return;
1119 }
1120
1121 ngx_log_error(NGX_LOG_INFO, ev->log, err,if ((ev->log)->log_level >= 7) ngx_log_error_core(7,
ev->log, err, "client prematurely closed connection")
1122 "client prematurely closed connection")if ((ev->log)->log_level >= 7) ngx_log_error_core(7,
ev->log, err, "client prematurely closed connection")
;
1123
1124 if (u->peer.connection == NULL((void*)0)) {
1125 ngx_http_upstream_finalize_request(r, u,
1126 NGX_HTTP_CLIENT_CLOSED_REQUEST499);
1127 }
1128}
1129
1130
1131static void
1132ngx_http_upstream_connect(ngx_http_request_t *r, ngx_http_upstream_t *u)
1133{
1134 ngx_int_t rc;
1135 ngx_time_t *tp;
1136 ngx_connection_t *c;
1137
1138 r->connection->log->action = "connecting to upstream";
1139
1140 if (u->state && u->state->response_sec) {
1141 tp = ngx_timeofday()(ngx_time_t *) ngx_cached_time;
1142 u->state->response_sec = tp->sec - u->state->response_sec;
1143 u->state->response_msec = tp->msec - u->state->response_msec;
1144 }
1145
1146 u->state = ngx_array_push(r->upstream_states);
1147 if (u->state == NULL((void*)0)) {
1148 ngx_http_upstream_finalize_request(r, u,
1149 NGX_HTTP_INTERNAL_SERVER_ERROR500);
1150 return;
1151 }
1152
1153 ngx_memzero(u->state, sizeof(ngx_http_upstream_state_t))(void) ((__builtin_object_size (u->state, 0) != (size_t) -
1) ? __builtin___memset_chk (u->state, 0, sizeof(ngx_http_upstream_state_t
), __builtin_object_size (u->state, 0)) : __inline_memset_chk
(u->state, 0, sizeof(ngx_http_upstream_state_t)))
;
1154
1155 tp = ngx_timeofday()(ngx_time_t *) ngx_cached_time;
1156 u->state->response_sec = tp->sec;
1157 u->state->response_msec = tp->msec;
1158
1159 rc = ngx_event_connect_peer(&u->peer);
1160
1161 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1162 "http upstream connect: %i", rc);
1163
1164 if (rc == NGX_ERROR-1) {
1165 ngx_http_upstream_finalize_request(r, u,
1166 NGX_HTTP_INTERNAL_SERVER_ERROR500);
1167 return;
1168 }
1169
1170 u->state->peer = u->peer.name;
1171
1172 if (rc == NGX_BUSY-3) {
1173 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "no live upstreams")if ((r->connection->log)->log_level >= 4) ngx_log_error_core
(4, r->connection->log, 0, "no live upstreams")
;
1174 ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_NOLIVE0x40000000);
1175 return;
1176 }
1177
1178 if (rc == NGX_DECLINED-5) {
1179 ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR0x00000002);
1180 return;
1181 }
1182
1183 /* rc == NGX_OK || rc == NGX_AGAIN */
1184
1185 c = u->peer.connection;
1186
1187 c->data = r;
1188
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;
1194
1195 c->sendfile &= r->connection->sendfile;
1196 u->output.sendfile = c->sendfile;
1197
1198 if (c->pool == NULL((void*)0)) {
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((void*)0)) {
1204 ngx_http_upstream_finalize_request(r, u,
1205 NGX_HTTP_INTERNAL_SERVER_ERROR500);
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;
1214
1215 /* init or reinit the ngx_output_chain() and ngx_chain_writer() contexts */
1216
1217 u->writer.out = NULL((void*)0);
1218 u->writer.last = &u->writer.out;
1219 u->writer.connection = c;
1220 u->writer.limit = 0;
1221
1222 if (u->request_sent) {
1223 if (ngx_http_upstream_reinit(r, u) != NGX_OK0) {
1224 ngx_http_upstream_finalize_request(r, u,
1225 NGX_HTTP_INTERNAL_SERVER_ERROR500);
1226 return;
1227 }
1228 }
1229
1230 if (r->request_body
1231 && r->request_body->buf
1232 && r->request_body->temp_file
1233 && r == r->main)
1234 {
1235 /*
1236 * the r->request_body->buf can be reused for one request only,
1237 * the subrequests should allocate their own temporary bufs
1238 */
1239
1240 u->output.free = ngx_alloc_chain_link(r->pool);
1241 if (u->output.free == NULL((void*)0)) {
1242 ngx_http_upstream_finalize_request(r, u,
1243 NGX_HTTP_INTERNAL_SERVER_ERROR500);
1244 return;
1245 }
1246
1247 u->output.free->buf = r->request_body->buf;
1248 u->output.free->next = NULL((void*)0);
1249 u->output.allocated = 1;
1250
1251 r->request_body->buf->pos = r->request_body->buf->start;
1252 r->request_body->buf->last = r->request_body->buf->start;
1253 r->request_body->buf->tag = u->output.tag;
1254 }
1255
1256 u->request_sent = 0;
1257
1258 if (rc == NGX_AGAIN-2) {
1259 ngx_add_timerngx_event_add_timer(c->write, u->conf->connect_timeout);
1260 return;
1261 }
1262
1263#if (NGX_HTTP_SSL)
1264
1265 if (u->ssl && c->ssl == NULL((void*)0)) {
1266 ngx_http_upstream_ssl_init_connection(r, u, c);
1267 return;
1268 }
1269
1270#endif
1271
1272 ngx_http_upstream_send_request(r, u);
1273}
1274
1275
1276#if (NGX_HTTP_SSL)
1277
1278static void
1279ngx_http_upstream_ssl_init_connection(ngx_http_request_t *r,
1280 ngx_http_upstream_t *u, ngx_connection_t *c)
1281{
1282 ngx_int_t rc;
1283
1284 if (ngx_ssl_create_connection(u->conf->ssl, c,
1285 NGX_SSL_BUFFER|NGX_SSL_CLIENT)
1286 != NGX_OK0)
1287 {
1288 ngx_http_upstream_finalize_request(r, u,
1289 NGX_HTTP_INTERNAL_SERVER_ERROR500);
1290 return;
1291 }
1292
1293 c->sendfile = 0;
1294 u->output.sendfile = 0;
1295
1296 if (u->conf->ssl_session_reuse) {
1297 if (u->peer.set_session(&u->peer, u->peer.data) != NGX_OK0) {
1298 ngx_http_upstream_finalize_request(r, u,
1299 NGX_HTTP_INTERNAL_SERVER_ERROR500);
1300 return;
1301 }
1302 }
1303
1304 r->connection->log->action = "SSL handshaking to upstream";
1305
1306 rc = ngx_ssl_handshake(c);
1307
1308 if (rc == NGX_AGAIN-2) {
1309 c->ssl->handler = ngx_http_upstream_ssl_handshake;
1310 return;
1311 }
1312
1313 ngx_http_upstream_ssl_handshake(c);
1314}
1315
1316
1317static void
1318ngx_http_upstream_ssl_handshake(ngx_connection_t *c)
1319{
1320 ngx_http_request_t *r;
1321 ngx_http_upstream_t *u;
1322
1323 r = c->data;
1324 u = r->upstream;
1325
1326 if (c->ssl->handshaked) {
1327
1328 if (u->conf->ssl_session_reuse) {
1329 u->peer.save_session(&u->peer, u->peer.data);
1330 }
1331
1332 c->write->handler = ngx_http_upstream_handler;
1333 c->read->handler = ngx_http_upstream_handler;
1334
1335 ngx_http_upstream_send_request(r, u);
1336
1337 return;
1338 }
1339
1340 ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR0x00000002);
1341
1342}
1343
1344#endif
1345
1346
1347static ngx_int_t
1348ngx_http_upstream_reinit(ngx_http_request_t *r, ngx_http_upstream_t *u)
1349{
1350 ngx_chain_t *cl;
1351
1352 if (u->reinit_request(r) != NGX_OK0) {
1353 return NGX_ERROR-1;
1354 }
1355
1356 u->keepalive = 0;
1357 u->upgrade = 0;
1358
1359 ngx_memzero(&u->headers_in, sizeof(ngx_http_upstream_headers_in_t))(void) ((__builtin_object_size (&u->headers_in, 0) != (
size_t) -1) ? __builtin___memset_chk (&u->headers_in, 0
, sizeof(ngx_http_upstream_headers_in_t), __builtin_object_size
(&u->headers_in, 0)) : __inline_memset_chk (&u->
headers_in, 0, sizeof(ngx_http_upstream_headers_in_t)))
;
1360 u->headers_in.content_length_n = -1;
1361
1362 if (ngx_list_init(&u->headers_in.headers, r->pool, 8,
1363 sizeof(ngx_table_elt_t))
1364 != NGX_OK0)
1365 {
1366 return NGX_ERROR-1;
1367 }
1368
1369 /* reinit the request chain */
1370
1371 for (cl = u->request_bufs; cl; cl = cl->next) {
1372 cl->buf->pos = cl->buf->start;
1373 cl->buf->file_pos = 0;
1374 }
1375
1376 /* reinit the subrequest's ngx_output_chain() context */
1377
1378 if (r->request_body && r->request_body->temp_file
1379 && r != r->main && u->output.buf)
1380 {
1381 u->output.free = ngx_alloc_chain_link(r->pool);
1382 if (u->output.free == NULL((void*)0)) {
1383 return NGX_ERROR-1;
1384 }
1385
1386 u->output.free->buf = u->output.buf;
1387 u->output.free->next = NULL((void*)0);
1388
1389 u->output.buf->pos = u->output.buf->start;
1390 u->output.buf->last = u->output.buf->start;
1391 }
1392
1393 u->output.buf = NULL((void*)0);
1394 u->output.in = NULL((void*)0);
1395 u->output.busy = NULL((void*)0);
1396
1397 /* reinit u->buffer */
1398
1399 u->buffer.pos = u->buffer.start;
1400
1401#if (NGX_HTTP_CACHE1)
1402
1403 if (r->cache) {
1404 u->buffer.pos += r->cache->header_start;
1405 }
1406
1407#endif
1408
1409 u->buffer.last = u->buffer.pos;
1410
1411 return NGX_OK0;
1412}
1413
1414
1415static void
1416ngx_http_upstream_send_request(ngx_http_request_t *r, ngx_http_upstream_t *u)
1417{
1418 ngx_int_t rc;
1419 ngx_connection_t *c;
1420
1421 c = u->peer.connection;
1422
1423 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
1424 "http upstream send request");
1425
1426 if (!u->request_sent && ngx_http_upstream_test_connect(c) != NGX_OK0) {
1427 ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR0x00000002);
1428 return;
1429 }
1430
1431 c->log->action = "sending request to upstream";
1432
1433 rc = ngx_output_chain(&u->output, u->request_sent ? NULL((void*)0) : u->request_bufs);
1434
1435 u->request_sent = 1;
1436
1437 if (rc == NGX_ERROR-1) {
1438 ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR0x00000002);
1439 return;
1440 }
1441
1442 if (c->write->timer_set) {
1443 ngx_del_timerngx_event_del_timer(c->write);
1444 }
1445
1446 if (rc == NGX_AGAIN-2) {
1447 ngx_add_timerngx_event_add_timer(c->write, u->conf->send_timeout);
1448
1449 if (ngx_handle_write_event(c->write, u->conf->send_lowat) != NGX_OK0) {
1450 ngx_http_upstream_finalize_request(r, u,
1451 NGX_HTTP_INTERNAL_SERVER_ERROR500);
1452 return;
1453 }
1454
1455 return;
1456 }
1457
1458 /* rc == NGX_OK */
1459
1460 if (c->tcp_nopush == NGX_TCP_NOPUSH_SET) {
1461 if (ngx_tcp_push(c->fd) == NGX_ERROR-1) {
1462 ngx_log_error(NGX_LOG_CRIT, c->log, ngx_socket_errno,if ((c->log)->log_level >= 3) ngx_log_error_core(3, c
->log, (*__error()), "setsockopt(!TCP_NOPUSH)" " failed")
1463 ngx_tcp_push_n " failed")if ((c->log)->log_level >= 3) ngx_log_error_core(3, c
->log, (*__error()), "setsockopt(!TCP_NOPUSH)" " failed")
;
1464 ngx_http_upstream_finalize_request(r, u,
1465 NGX_HTTP_INTERNAL_SERVER_ERROR500);
1466 return;
1467 }
1468
1469 c->tcp_nopush = NGX_TCP_NOPUSH_UNSET;
1470 }
1471
1472 ngx_add_timerngx_event_add_timer(c->read, u->conf->read_timeout);
1473
1474#if 1
1475 if (c->read->ready) {
1476
1477 /* post aio operation */
1478
1479 /*
1480 * TODO comment
1481 * although we can post aio operation just in the end
1482 * of ngx_http_upstream_connect() CHECK IT !!!
1483 * it's better to do here because we postpone header buffer allocation
1484 */
1485
1486 ngx_http_upstream_process_header(r, u);
1487 return;
1488 }
1489#endif
1490
1491 u->write_event_handler = ngx_http_upstream_dummy_handler;
1492
1493 if (ngx_handle_write_event(c->write, 0) != NGX_OK0) {
1494 ngx_http_upstream_finalize_request(r, u,
1495 NGX_HTTP_INTERNAL_SERVER_ERROR500);
1496 return;
1497 }
1498}
1499
1500
1501static void
1502ngx_http_upstream_send_request_handler(ngx_http_request_t *r,
1503 ngx_http_upstream_t *u)
1504{
1505 ngx_connection_t *c;
1506
1507 c = u->peer.connection;
1508
1509 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1510 "http upstream send request handler");
1511
1512 if (c->write->timedout) {
1513 ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_TIMEOUT0x00000004);
1514 return;
1515 }
1516
1517#if (NGX_HTTP_SSL)
1518
1519 if (u->ssl && c->ssl == NULL((void*)0)) {
1520 ngx_http_upstream_ssl_init_connection(r, u, c);
1521 return;
1522 }
1523
1524#endif
1525
1526 if (u->header_sent) {
1527 u->write_event_handler = ngx_http_upstream_dummy_handler;
1528
1529 (void) ngx_handle_write_event(c->write, 0);
1530
1531 return;
1532 }
1533
1534 ngx_http_upstream_send_request(r, u);
1535}
1536
1537
1538static void
1539ngx_http_upstream_process_header(ngx_http_request_t *r, ngx_http_upstream_t *u)
1540{
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,
1548 "http upstream process header");
1549
1550 c->log->action = "reading response header from upstream";
1551
1552 if (c->read->timedout) {
1553 ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_TIMEOUT0x00000004);
1554 return;
1555 }
1556
1557 if (!u->request_sent && ngx_http_upstream_test_connect(c) != NGX_OK0) {
1558 ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR0x00000002);
1559 return;
1560 }
1561
1562 if (u->buffer.start == NULL((void*)0)) {
1563 u->buffer.start = ngx_palloc(r->pool, u->conf->buffer_size);
1564 if (u->buffer.start == NULL((void*)0)) {
1565 ngx_http_upstream_finalize_request(r, u,
1566 NGX_HTTP_INTERNAL_SERVER_ERROR500);
1567 return;
1568 }
1569
1570 u->buffer.pos = u->buffer.start;
1571 u->buffer.last = u->buffer.start;
1572 u->buffer.end = u->buffer.start + u->conf->buffer_size;
1573 u->buffer.temporary = 1;
1574
1575 u->buffer.tag = u->output.tag;
1576
1577 if (ngx_list_init(&u->headers_in.headers, r->pool, 8,
1578 sizeof(ngx_table_elt_t))
1579 != NGX_OK0)
1580 {
1581 ngx_http_upstream_finalize_request(r, u,
1582 NGX_HTTP_INTERNAL_SERVER_ERROR500);
1583 return;
1584 }
1585
1586#if (NGX_HTTP_CACHE1)
1587
1588 if (r->cache) {
1589 u->buffer.pos += r->cache->header_start;
1590 u->buffer.last = u->buffer.pos;
1591 }
1592#endif
1593 }
1594
1595 for ( ;; ) {
1596
1597 n = c->recv(c, u->buffer.last, u->buffer.end - u->buffer.last);
1598
1599 if (n == NGX_AGAIN-2) {
1600#if 0
1601 ngx_add_timerngx_event_add_timer(rev, u->read_timeout);
1602#endif
1603
1604 if (ngx_handle_read_event(c->read, 0) != NGX_OK0) {
1605 ngx_http_upstream_finalize_request(r, u,
1606 NGX_HTTP_INTERNAL_SERVER_ERROR500);
1607 return;
1608 }
1609
1610 return;
1611 }
1612
1613 if (n == 0) {
1614 ngx_log_error(NGX_LOG_ERR, c->log, 0,if ((c->log)->log_level >= 4) ngx_log_error_core(4, c
->log, 0, "upstream prematurely closed connection")
1615 "upstream prematurely closed connection")if ((c->log)->log_level >= 4) ngx_log_error_core(4, c
->log, 0, "upstream prematurely closed connection")
;
1616 }
1617
1618 if (n == NGX_ERROR-1 || n == 0) {
1619 ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR0x00000002);
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-2) {
1634
1635 if (u->buffer.last == u->buffer.end) {
1636 ngx_log_error(NGX_LOG_ERR, c->log, 0,if ((c->log)->log_level >= 4) ngx_log_error_core(4, c
->log, 0, "upstream sent too big header")
1637 "upstream sent too big header")if ((c->log)->log_level >= 4) ngx_log_error_core(4, c
->log, 0, "upstream sent too big header")
;
1638
1639 ngx_http_upstream_next(r, u,
1640 NGX_HTTP_UPSTREAM_FT_INVALID_HEADER0x00000008);
1641 return;
1642 }
1643
1644 continue;
1645 }
1646
1647 break;
1648 }
1649
1650 if (rc == NGX_HTTP_UPSTREAM_INVALID_HEADER40) {
1651 ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_INVALID_HEADER0x00000008);
1652 return;
1653 }
1654
1655 if (rc == NGX_ERROR-1) {
1656 ngx_http_upstream_finalize_request(r, u,
1657 NGX_HTTP_INTERNAL_SERVER_ERROR500);
1658 return;
1659 }
1660
1661 /* rc == NGX_OK */
1662
1663 if (u->headers_in.status_n > NGX_HTTP_SPECIAL_RESPONSE300) {
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_OK0) {
1670 return;
1671 }
1672
1673 if (ngx_http_upstream_intercept_errors(r, u) == NGX_OK0) {
1674 return;
1675 }
1676 }
1677
1678 if (ngx_http_upstream_process_headers(r, u) != NGX_OK0) {
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((void*)0)) {
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-1) {
1696 ngx_http_upstream_finalize_request(r, u,
1697 NGX_HTTP_INTERNAL_SERVER_ERROR500);
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-1) {
1709 ngx_http_upstream_finalize_request(r, u, NGX_ERROR-1);
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
1725static ngx_int_t
1726ngx_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_OK0;
1742 }
1743
1744#if (NGX_HTTP_CACHE1)
1745
1746 if (u->cache_status == NGX_HTTP_CACHE_EXPIRED3
1747 && (u->conf->cache_use_stale & un->mask))
1748 {
1749 ngx_int_t rc;
1750
1751 rc = u->reinit_request(r);
1752
1753 if (rc == NGX_OK0) {
1754 u->cache_status = NGX_HTTP_CACHE_STALE4;
1755 rc = ngx_http_upstream_cache_send(r, u);
1756 }
1757
1758 ngx_http_upstream_finalize_request(r, u, rc);
1759 return NGX_OK0;
1760 }
1761
1762#endif
1763 }
1764
1765 return NGX_DECLINED-5;
1766}
1767
1768
1769static ngx_int_t
1770ngx_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_FOUND404 && u->conf->intercept_404) {
1782 ngx_http_upstream_finalize_request(r, u, NGX_HTTP_NOT_FOUND404);
1783 return NGX_OK0;
1784 }
1785
1786 if (!u->conf->intercept_errors) {
1787 return NGX_DECLINED-5;
1788 }
1789
1790 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module)(r)->loc_conf[ngx_http_core_module.ctx_index];
1791
1792 if (clcf->error_pages == NULL((void*)0)) {
1793 return NGX_DECLINED-5;
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_UNAUTHORIZED401
1802 && u->headers_in.www_authenticate)
1803 {
1804 h = ngx_list_push(&r->headers_out.headers);
1805
1806 if (h == NULL((void*)0)) {
1807 ngx_http_upstream_finalize_request(r, u,
1808 NGX_HTTP_INTERNAL_SERVER_ERROR500);
1809 return NGX_OK0;
1810 }
1811
1812 *h = *u->headers_in.www_authenticate;
1813
1814 r->headers_out.www_authenticate = h;
1815 }
1816
1817#if (NGX_HTTP_CACHE1)
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()ngx_cached_time->sec + 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_OK0;
1835 }
1836 }
1837
1838 return NGX_DECLINED-5;
1839}
1840
1841
1842static ngx_int_t
1843ngx_http_upstream_test_connect(ngx_connection_t *c)
1844{
1845 int err;
1846 socklen_t len;
1847
1848#if (NGX_HAVE_KQUEUE1)
1849
1850 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT0x00000008) {
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-1;
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_SOCKET0xffff, SO_ERROR0x1007, (void *) &err, &len)
1877 == -1)
1878 {
1879 err = ngx_errno(*__error());
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-1;
1886 }
1887 }
1888
1889 return NGX_OK0;
1890}
1891
1892
1893static ngx_int_t
1894ngx_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;
1902
1903 umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module)(r)->main_conf[ngx_http_upstream_module.ctx_index];
1904
1905 if (u->headers_in.x_accel_redirect
1906 && !(u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_XA_REDIRECT0x00000002))
1907 {
1908 ngx_http_upstream_finalize_request(r, u, NGX_DECLINED-5);
1909
1910 part = &u->headers_in.headers.part;
1911 h = part->elts;
1912
1913 for (i = 0; /* void */; i++) {
1914
1915 if (i >= part->nelts) {
1916 if (part->next == NULL((void*)0)) {
1917 break;
1918 }
1919
1920 part = part->next;
1921 h = part->elts;
1922 i = 0;
1923 }
1924
1925 hh = ngx_hash_find(&umcf->headers_in_hash, h[i].hash,
1926 h[i].lowcase_key, h[i].key.len);
1927
1928 if (hh && hh->redirect) {
1929 if (hh->copy_handler(r, &h[i], hh->conf) != NGX_OK0) {
1930 ngx_http_finalize_request(r,
1931 NGX_HTTP_INTERNAL_SERVER_ERROR500);
1932 return NGX_DONE-4;
1933 }
1934 }
1935 }
1936
1937 uri = &u->headers_in.x_accel_redirect->value;
1938 ngx_str_null(&args)(&args)->len = 0; (&args)->data = ((void*)0);
1939 flags = NGX_HTTP_LOG_UNSAFE8;
1940
1941 if (ngx_http_parse_unsafe_uri(r, uri, &args, &flags) != NGX_OK0) {
1942 ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND404);
1943 return NGX_DONE-4;
1944 }
1945
1946 if (r->method != NGX_HTTP_HEAD0x0004) {
1947 r->method = NGX_HTTP_GET0x0002;
1948 }
1949
1950 ngx_http_internal_redirect(r, uri, &args);
1951 ngx_http_finalize_request(r, NGX_DONE-4);
1952 return NGX_DONE-4;
1953 }
1954
1955 part = &u->headers_in.headers.part;
1956 h = part->elts;
1957
1958 for (i = 0; /* void */; i++) {
1959
1960 if (i >= part->nelts) {
1961 if (part->next == NULL((void*)0)) {
1962 break;
1963 }
1964
1965 part = part->next;
1966 h = part->elts;
1967 i = 0;
1968 }
1969
1970 if (ngx_hash_find(&u->conf->hide_headers_hash, h[i].hash,
1971 h[i].lowcase_key, h[i].key.len))
1972 {
1973 continue;
1974 }
1975
1976 hh = ngx_hash_find(&umcf->headers_in_hash, h[i].hash,
1977 h[i].lowcase_key, h[i].key.len);
1978
1979 if (hh) {
1980 if (hh->copy_handler(r, &h[i], hh->conf) != NGX_OK0) {
1981 ngx_http_upstream_finalize_request(r, u,
1982 NGX_HTTP_INTERNAL_SERVER_ERROR500);
1983 return NGX_DONE-4;
1984 }
1985
1986 continue;
1987 }
1988
1989 if (ngx_http_upstream_copy_header_line(r, &h[i], 0) != NGX_OK0) {
1990 ngx_http_upstream_finalize_request(r, u,
1991 NGX_HTTP_INTERNAL_SERVER_ERROR500);
1992 return NGX_DONE-4;
1993 }
1994 }
1995
1996 if (r->headers_out.server && r->headers_out.server->value.data == NULL((void*)0)) {
1997 r->headers_out.server->hash = 0;
1998 }
1999
2000 if (r->headers_out.date && r->headers_out.date->value.data == NULL((void*)0)) {
2001 r->headers_out.date->hash = 0;
2002 }
2003
2004 r->headers_out.status = u->headers_in.status_n;
2005 r->headers_out.status_line = u->headers_in.status_line;
2006
2007 r->headers_out.content_length_n = u->headers_in.content_length_n;
2008
2009 u->length = u->headers_in.content_length_n;
2010
2011 return NGX_OK0;
2012}
2013
2014
2015static void
2016ngx_http_upstream_process_body_in_memory(ngx_http_request_t *r,
2017 ngx_http_upstream_t *u)
2018{
2019 size_t size;
2020 ssize_t n;
2021 ngx_buf_t *b;
2022 ngx_event_t *rev;
2023 ngx_connection_t *c;
2024
2025 c = u->peer.connection;
2026 rev = c->read;
2027
2028 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
2029 "http upstream process body on memory");
2030
2031 if (rev->timedout) {
2032 ngx_connection_error(c, NGX_ETIMEDOUT60, "upstream timed out");
2033 ngx_http_upstream_finalize_request(r, u, NGX_ETIMEDOUT60);
2034 return;
2035 }
2036
2037 b = &u->buffer;
2038
2039 for ( ;; ) {
2040
2041 size = b->end - b->last;
2042
2043 if (size == 0) {
2044 ngx_log_error(NGX_LOG_ALERT, c->log, 0,if ((c->log)->log_level >= 2) ngx_log_error_core(2, c
->log, 0, "upstream buffer is too small to read response")
2045 "upstream buffer is too small to read response")if ((c->log)->log_level >= 2) ngx_log_error_core(2, c
->log, 0, "upstream buffer is too small to read response")
;
2046 ngx_http_upstream_finalize_request(r, u, NGX_ERROR-1);
2047 return;
2048 }
2049
2050 n = c->recv(c, b->last, size);
2051
2052 if (n == NGX_AGAIN-2) {
2053 break;
2054 }
2055
2056 if (n == 0 || n == NGX_ERROR-1) {
2057 ngx_http_upstream_finalize_request(r, u, n);
2058 return;
2059 }
2060
2061 u->state->response_length += n;
2062
2063 if (u->input_filter(u->input_filter_ctx, n) == NGX_ERROR-1) {
2064 ngx_http_upstream_finalize_request(r, u, NGX_ERROR-1);
2065 return;
2066 }
2067
2068 if (!rev->ready) {
2069 break;
2070 }
2071 }
2072
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_OK0) {
2079 ngx_http_upstream_finalize_request(r, u, NGX_ERROR-1);
2080 return;
2081 }
2082
2083 if (rev->active) {
2084 ngx_add_timerngx_event_add_timer(rev, u->conf->read_timeout);
2085
2086 } else if (rev->timer_set) {
2087 ngx_del_timerngx_event_del_timer(rev);
2088 }
2089}
2090
2091
2092static void
2093ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
2094{
2095 int tcp_nodelay;
2096 ssize_t n;
2097 ngx_int_t rc;
2098 ngx_event_pipe_t *p;
2099 ngx_connection_t *c;
2100 ngx_http_core_loc_conf_t *clcf;
2101
2102 rc = ngx_http_send_header(r);
2103
2104 if (rc == NGX_ERROR-1 || rc > NGX_OK0 || r->post_action) {
2105 ngx_http_upstream_finalize_request(r, u, rc);
2106 return;
2107 }
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_socketshutdown(c->fd, NGX_WRITE_SHUTDOWN1) == -1) {
2121 ngx_connection_error(c, ngx_socket_errno(*__error()),
2122 ngx_shutdown_socket_n"shutdown()" " 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
2135 u->header_sent = 1;
2136
2137 if (r->request_body && r->request_body->temp_file) {
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-1;
2140 }
2141
2142 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module)(r)->loc_conf[ngx_http_core_module.ctx_index];
2143
2144 if (!u->buffering) {
2145
2146 if (u->input_filter == NULL((void*)0)) {
2147 u->input_filter_init = ngx_http_upstream_non_buffered_filter_init;
2148 u->input_filter = ngx_http_upstream_non_buffered_filter;
2149 u->input_filter_ctx = r;
2150 }
2151
2152 u->read_event_handler = ngx_http_upstream_process_non_buffered_upstream;
2153 r->write_event_handler =
2154 ngx_http_upstream_process_non_buffered_downstream;
2155
2156 r->limit_rate = 0;
2157
2158 if (u->input_filter_init(u->input_filter_ctx) == NGX_ERROR-1) {
2159 ngx_http_upstream_finalize_request(r, u, 0);
2160 return;
2161 }
2162
2163 if (clcf->tcp_nodelay && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) {
2164 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay");
2165
2166 tcp_nodelay = 1;
2167
2168 if (setsockopt(c->fd, IPPROTO_TCP6, TCP_NODELAY0x01,
2169 (const void *) &tcp_nodelay, sizeof(int)) == -1)
2170 {
2171 ngx_connection_error(c, ngx_socket_errno(*__error()),
2172 "setsockopt(TCP_NODELAY) failed");
2173 ngx_http_upstream_finalize_request(r, u, 0);
2174 return;
2175 }
2176
2177 c->tcp_nodelay = NGX_TCP_NODELAY_SET;
2178 }
2179
2180 n = u->buffer.last - u->buffer.pos;
2181
2182 if (n) {
2183 u->buffer.last = u->buffer.pos;
2184
2185 u->state->response_length += n;
2186
2187 if (u->input_filter(u->input_filter_ctx, n) == NGX_ERROR-1) {
2188 ngx_http_upstream_finalize_request(r, u, 0);
2189 return;
2190 }
2191
2192 ngx_http_upstream_process_non_buffered_downstream(r);
2193
2194 } else {
2195 u->buffer.pos = u->buffer.start;
2196 u->buffer.last = u->buffer.start;
2197
2198 if (ngx_http_send_special(r, NGX_HTTP_FLUSH2) == NGX_ERROR-1) {
2199 ngx_http_upstream_finalize_request(r, u, 0);
2200 return;
2201 }
2202
2203 if (u->peer.connection->read->ready || u->length == 0) {
2204 ngx_http_upstream_process_non_buffered_upstream(r, u);
2205 }
2206 }
2207
2208 return;
2209 }
2210
2211 /* TODO: preallocate event_pipe bufs, look "Content-Length" */
2212
2213#if (NGX_HTTP_CACHE1)
2214
2215 if (r->cache && r->cache->file.fd != NGX_INVALID_FILE-1) {
2216 ngx_pool_run_cleanup_file(r->pool, r->cache->file.fd);
2217 r->cache->file.fd = NGX_INVALID_FILE-1;
2218 }
2219
2220 switch (ngx_http_test_predicates(r, u->conf->no_cache)) {
2221
2222 case NGX_ERROR-1:
2223 ngx_http_upstream_finalize_request(r, u, 0);
2224 return;
2225
2226 case NGX_DECLINED-5:
2227 u->cacheable = 0;
2228 break;
2229
2230 default: /* NGX_OK */
2231
2232 if (u->cache_status == NGX_HTTP_CACHE_BYPASS2) {
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_OK0) {
2239 ngx_http_upstream_finalize_request(r, u, 0);
2240 return;
2241 }
2242 }
2243
2244 break;
2245 }
2246
2247 if (u->cacheable) {
2248 time_t now, valid;
2249
2250 now = ngx_time()ngx_cached_time->sec;
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);
2280 }
2281
2282#endif
2283
2284 p = u->pipe;
2285
2286 p->output_filter = (ngx_event_pipe_output_filter_pt) ngx_http_output_filter;
2287 p->output_ctx = r;
2288 p->tag = u->output.tag;
2289 p->bufs = u->conf->bufs;
2290 p->busy_size = u->conf->busy_buffers_size;
2291 p->upstream = u->peer.connection;
2292 p->downstream = c;
2293 p->pool = r->pool;
2294 p->log = c->log;
2295
2296 p->cacheable = u->cacheable || u->store;
2297
2298 p->temp_file = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t));
2299 if (p->temp_file == NULL((void*)0)) {
2300 ngx_http_upstream_finalize_request(r, u, 0);
2301 return;
2302 }
2303
2304 p->temp_file->file.fd = NGX_INVALID_FILE-1;
2305 p->temp_file->file.log = c->log;
2306 p->temp_file->path = u->conf->temp_path;
2307 p->temp_file->pool = r->pool;
2308
2309 if (p->cacheable) {
2310 p->temp_file->persistent = 1;
2311
2312 } else {
2313 p->temp_file->log_level = NGX_LOG_WARN5;
2314 p->temp_file->warn = "an upstream response is buffered "
2315 "to a temporary file";
2316 }
2317
2318 p->max_temp_file_size = u->conf->max_temp_file_size;
2319 p->temp_file_write_size = u->conf->temp_file_write_size;
2320
2321 p->preread_bufs = ngx_alloc_chain_link(r->pool);
2322 if (p->preread_bufs == NULL((void*)0)) {
2323 ngx_http_upstream_finalize_request(r, u, 0);
2324 return;
2325 }
2326
2327 p->preread_bufs->buf = &u->buffer;
2328 p->preread_bufs->next = NULL((void*)0);
2329 u->buffer.recycled = 1;
2330
2331 p->preread_size = u->buffer.last - u->buffer.pos;
2332
2333 if (u->cacheable) {
2334
2335 p->buf_to_file = ngx_calloc_buf(r->pool)ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
2336 if (p->buf_to_file == NULL((void*)0)) {
2337 ngx_http_upstream_finalize_request(r, u, 0);
2338 return;
2339 }
2340
2341 p->buf_to_file->start = u->buffer.start;
2342 p->buf_to_file->pos = u->buffer.start;
2343 p->buf_to_file->last = u->buffer.pos;
2344 p->buf_to_file->temporary = 1;
2345 }
2346
2347 if (ngx_event_flags & NGX_USE_AIO_EVENT0x00000100) {
2348 /* the posted aio operation may corrupt a shadow buffer */
2349 p->single_buf = 1;
2350 }
2351
2352 /* TODO: p->free_bufs = 0 if use ngx_create_chain_of_bufs() */
2353 p->free_bufs = 1;
2354
2355 /*
2356 * event_pipe would do u->buffer.last += p->preread_size
2357 * as though these bytes were read
2358 */
2359 u->buffer.last = u->buffer.pos;
2360
2361 if (u->conf->cyclic_temp_file) {
2362
2363 /*
2364 * we need to disable the use of sendfile() if we use cyclic temp file
2365 * because the writing a new data may interfere with sendfile()
2366 * that uses the same kernel file pages (at least on FreeBSD)
2367 */
2368
2369 p->cyclic_temp_file = 1;
2370 c->sendfile = 0;
2371
2372 } else {
2373 p->cyclic_temp_file = 0;
2374 }
2375
2376 p->read_timeout = u->conf->read_timeout;
2377 p->send_timeout = clcf->send_timeout;
2378 p->send_lowat = clcf->send_lowat;
2379
2380 p->length = -1;
2381
2382 if (u->input_filter_init
2383 && u->input_filter_init(p->input_ctx) != NGX_OK0)
2384 {
2385 ngx_http_upstream_finalize_request(r, u, 0);
2386 return;
2387 }
2388
2389 u->read_event_handler = ngx_http_upstream_process_upstream;
2390 r->write_event_handler = ngx_http_upstream_process_downstream;
2391
2392 ngx_http_upstream_process_upstream(r, u);
2393}
2394
2395
2396static void
2397ngx_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)(r)->loc_conf[ngx_http_core_module.ctx_index];
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_TCP6, TCP_NODELAY0x01,
2423 (const void *) &tcp_nodelay, sizeof(int)) == -1)
2424 {
2425 ngx_connection_error(c, ngx_socket_errno(*__error()),
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_TCP6, TCP_NODELAY0x01,
2439 (const void *) &tcp_nodelay, sizeof(int)) == -1)
2440 {
2441 ngx_connection_error(u->peer.connection, ngx_socket_errno(*__error()),
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_FLUSH2) == NGX_ERROR-1) {
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
2470static void
2471ngx_http_upstream_upgraded_read_downstream(ngx_http_request_t *r)
2472{
2473 ngx_http_upstream_process_upgraded(r, 0, 0);
2474}
2475
2476
2477static void
2478ngx_http_upstream_upgraded_write_downstream(ngx_http_request_t *r)
2479{
2480 ngx_http_upstream_process_upgraded(r, 1, 1);
2481}
2482
2483
2484static void
2485ngx_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
2492static void
2493ngx_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
2500static void
2501ngx_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_ETIMEDOUT60, "client timed out");
2523 ngx_http_upstream_finalize_request(r, u, NGX_HTTP_REQUEST_TIME_OUT408);
2524 return;
2525 }
2526
2527 if (upstream->read->timedout || upstream->write->timedout) {
2528 ngx_connection_error(c, NGX_ETIMEDOUT60, "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((void*)0)) {
2550 b->start = ngx_palloc(r->pool, u->conf->buffer_size);
2551 if (b->start == NULL((void*)0)) {
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-1) {
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-2 || 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-1) {
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)(r)->loc_conf[ngx_http_core_module.ctx_index];
2626
2627 if (ngx_handle_write_event(upstream->write, u->conf->send_lowat)
2628 != NGX_OK0)
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_timerngx_event_add_timer(upstream->write, u->conf->send_timeout);
2636
2637 } else if (upstream->write->timer_set) {
2638 ngx_del_timerngx_event_del_timer(upstream->write);
2639 }
2640
2641 if (ngx_handle_read_event(upstream->read, 0) != NGX_OK0) {
2642 ngx_http_upstream_finalize_request(r, u, 0);
2643 return;
2644 }
2645
2646 if (upstream->read->active && !upstream->read->ready) {
2647 ngx_add_timerngx_event_add_timer(upstream->read, u->conf->read_timeout);
2648
2649 } else if (upstream->read->timer_set) {
2650 ngx_del_timerngx_event_del_timer(upstream->read);
2651 }
2652
2653 if (ngx_handle_write_event(downstream->write, clcf->send_lowat)
2654 != NGX_OK0)
2655 {
2656 ngx_http_upstream_finalize_request(r, u, 0);
2657 return;
2658 }
2659
2660 if (ngx_handle_read_event(downstream->read, 0) != NGX_OK0) {
2661 ngx_http_upstream_finalize_request(r, u, 0);
2662 return;
2663 }
2664
2665 if (downstream->write->active && !downstream->write->ready) {
2666 ngx_add_timerngx_event_add_timer(downstream->write, clcf->send_timeout);
2667
2668 } else if (downstream->write->timer_set) {
2669 ngx_del_timerngx_event_del_timer(downstream->write);
2670 }
2671}
2672
2673
2674static void
2675ngx_http_upstream_process_non_buffered_downstream(ngx_http_request_t *r)
2676{
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_ETIMEDOUT60, "client timed out");
2693 ngx_http_upstream_finalize_request(r, u, NGX_HTTP_REQUEST_TIME_OUT408);
2694 return;
2695 }
2696
2697 ngx_http_upstream_process_non_buffered_request(r, 1);
2698}
2699
2700
2701static void
2702ngx_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_ETIMEDOUT60, "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
2724static void
2725ngx_http_upstream_process_non_buffered_request(ngx_http_request_t *r,
2726 ngx_uint_t do_write)
2727{
2728 size_t size;
2729 ssize_t n;
2730 ngx_buf_t *b;
2731 ngx_int_t rc;
2732 ngx_connection_t *downstream, *upstream;
2733 ngx_http_upstream_t *u;
2734 ngx_http_core_loc_conf_t *clcf;
2735
2736 u = r->upstream;
2737 downstream = r->connection;
2738 upstream = u->peer.connection;
2739
2740 b = &u->buffer;
2741
2742 do_write = do_write || u->length == 0;
2743
2744 for ( ;; ) {
2745
2746 if (do_write) {
2747
2748 if (u->out_bufs || u->busy_bufs) {
2749 rc = ngx_http_output_filter(r, u->out_bufs);
2750
2751 if (rc == NGX_ERROR-1) {
2752 ngx_http_upstream_finalize_request(r, u, 0);
2753 return;
2754 }
2755
2756 ngx_chain_update_chains(r->pool, &u->free_bufs, &u->busy_bufs,
2757 &u->out_bufs, u->output.tag);
2758 }
2759
2760 if (u->busy_bufs == NULL((void*)0)) {
2761
2762 if (u->length == 0
2763 || upstream->read->eof
2764 || upstream->read->error)
2765 {
2766 ngx_http_upstream_finalize_request(r, u, 0);
2767 return;
2768 }
2769
2770 b->pos = b->start;
2771 b->last = b->start;
2772 }
2773 }
2774
2775 size = b->end - b->last;
2776
2777 if (size && upstream->read->ready) {
2778
2779 n = upstream->recv(upstream, b->last, size);
2780
2781 if (n == NGX_AGAIN-2) {
2782 break;
2783 }
2784
2785 if (n > 0) {
2786 u->state->response_length += n;
2787
2788 if (u->input_filter(u->input_filter_ctx, n) == NGX_ERROR-1) {
2789 ngx_http_upstream_finalize_request(r, u, 0);
2790 return;
2791 }
2792 }
2793
2794 do_write = 1;
2795
2796 continue;
2797 }
2798
2799 break;
2800 }
2801
2802 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module)(r)->loc_conf[ngx_http_core_module.ctx_index];
2803
2804 if (downstream->data == r) {
2805 if (ngx_handle_write_event(downstream->write, clcf->send_lowat)
2806 != NGX_OK0)
2807 {
2808 ngx_http_upstream_finalize_request(r, u, 0);
2809 return;
2810 }
2811 }
2812
2813 if (downstream->write->active && !downstream->write->ready) {
2814 ngx_add_timerngx_event_add_timer(downstream->write, clcf->send_timeout);
2815
2816 } else if (downstream->write->timer_set) {
2817 ngx_del_timerngx_event_del_timer(downstream->write);
2818 }
2819
2820 if (ngx_handle_read_event(upstream->read, 0) != NGX_OK0) {
2821 ngx_http_upstream_finalize_request(r, u, 0);
2822 return;
2823 }
2824
2825 if (upstream->read->active && !upstream->read->ready) {
2826 ngx_add_timerngx_event_add_timer(upstream->read, u->conf->read_timeout);
2827
2828 } else if (upstream->read->timer_set) {
2829 ngx_del_timerngx_event_del_timer(upstream->read);
2830 }
2831}
2832
2833
2834static ngx_int_t
2835ngx_http_upstream_non_buffered_filter_init(void *data)
2836{
2837 return NGX_OK0;
2838}
2839
2840
2841static ngx_int_t
2842ngx_http_upstream_non_buffered_filter(void *data, ssize_t bytes)
2843{
2844 ngx_http_request_t *r = data;
2845
2846 ngx_buf_t *b;
2847 ngx_chain_t *cl, **ll;
2848 ngx_http_upstream_t *u;
2849
2850 u = r->upstream;
2851
2852 for (cl = u->out_bufs, ll = &u->out_bufs; cl; cl = cl->next) {
2853 ll = &cl->next;
2854 }
2855
2856 cl = ngx_chain_get_free_buf(r->pool, &u->free_bufs);
2857 if (cl == NULL((void*)0)) {
2858 return NGX_ERROR-1;
2859 }
2860
2861 *ll = cl;
2862
2863 cl->buf->flush = 1;
2864 cl->buf->memory = 1;
2865
2866 b = &u->buffer;
2867
2868 cl->buf->pos = b->last;
2869 b->last += bytes;
2870 cl->buf->last = b->last;
2871 cl->buf->tag = u->output.tag;
2872
2873 if (u->length == -1) {
2874 return NGX_OK0;
2875 }
2876
2877 u->length -= bytes;
2878
2879 return NGX_OK0;
2880}
2881
2882
2883static void
2884ngx_http_upstream_process_downstream(ngx_http_request_t *r)
2885{
2886 ngx_event_t *wev;
2887 ngx_connection_t *c;
2888 ngx_event_pipe_t *p;
2889 ngx_http_upstream_t *u;
2890
2891 c = r->connection;
2892 u = r->upstream;
2893 p = u->pipe;
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_timerngx_event_add_timer(wev, p->send_timeout);
2910
2911 if (ngx_handle_write_event(wev, p->send_lowat) != NGX_OK0) {
2912 ngx_http_upstream_finalize_request(r, u, 0);
2913 }
2914
2915 return;
2916 }
2917
2918 if (ngx_event_pipe(p, wev->write) == NGX_ABORT-6) {
2919 ngx_http_upstream_finalize_request(r, u, 0);
2920 return;
2921 }
2922
2923 } else {
2924 p->downstream_error = 1;
2925 c->timedout = 1;
2926 ngx_connection_error(c, NGX_ETIMEDOUT60, "client timed out");
2927 }
2928
2929 } else {
2930
2931 if (wev->delayed) {
2932
2933 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
2934 "http downstream delayed");
2935
2936 if (ngx_handle_write_event(wev, p->send_lowat) != NGX_OK0) {
2937 ngx_http_upstream_finalize_request(r, u, 0);
2938 }
2939
2940 return;
2941 }
2942
2943 if (ngx_event_pipe(p, 1) == NGX_ABORT-6) {
2944 ngx_http_upstream_finalize_request(r, u, 0);
2945 return;
2946 }
2947 }
2948
2949 ngx_http_upstream_process_request(r);
2950}
2951
2952
2953static void
2954ngx_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_ETIMEDOUT60, "upstream timed out");
2969
2970 } else {
2971 if (ngx_event_pipe(u->pipe, 0) == NGX_ABORT-6) {
2972 ngx_http_upstream_finalize_request(r, u, 0);
2973 return;
2974 }
2975 }
2976
2977 ngx_http_upstream_process_request(r);
2978}
2979
2980
2981static void
2982ngx_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;
2990
2991 if (u->peer.connection) {
2992
2993 if (u->store) {
2994
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_OK200
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;
3005 }
3006 }
3007 }
3008
3009#if (NGX_HTTP_CACHE1)
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);
3032 }
3033 }
3034
3035#endif
3036
3037 if (p->upstream_done || p->upstream_eof || p->upstream_error) {
3038 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
3039 "http upstream exit: %p", p->out);
3040#if 0
3041 ngx_http_busy_unlock(u->conf->busy_lock, &u->busy_lock);
3042#endif
3043 ngx_http_upstream_finalize_request(r, u, 0);
3044 return;
3045 }
3046 }
3047
3048 if (p->downstream_error) {
3049 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
3050 "http upstream downstream error");
3051
3052 if (!u->cacheable && !u->store && u->peer.connection) {
3053 ngx_http_upstream_finalize_request(r, u, 0);
3054 }
3055 }
3056}
3057
3058
3059static void
3060ngx_http_upstream_store(ngx_http_request_t *r, ngx_http_upstream_t *u)
3061{
3062 size_t root;
3063 time_t lm;
3064 ngx_str_t path;
3065 ngx_temp_file_t *tf;
3066 ngx_ext_rename_file_t ext;
3067
3068 tf = u->pipe->temp_file;
3069
3070 if (tf->file.fd == NGX_INVALID_FILE-1) {
3071
3072 /* create file for empty 200 response */
3073
3074 tf = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t));
3075 if (tf == NULL((void*)0)) {
3076 return;
3077 }
3078
3079 tf->file.fd = NGX_INVALID_FILE-1;
3080 tf->file.log = r->connection->log;
3081 tf->path = u->conf->temp_path;
3082 tf->pool = r->pool;
3083 tf->persistent = 1;
3084
3085 if (ngx_create_temp_file(&tf->file, tf->path, tf->pool,
3086 tf->persistent, tf->clean, tf->access)
3087 != NGX_OK0)
3088 {
3089 return;
3090 }
3091
3092 u->pipe->temp_file = tf;
3093 }
3094
3095 ext.access = u->conf->store_access;
3096 ext.path_access = u->conf->store_access;
3097 ext.time = -1;
3098 ext.create_path = 1;
3099 ext.delete_file = 1;
3100 ext.log = r->connection->log;
3101
3102 if (u->headers_in.last_modified) {
3103
3104 lm = ngx_http_parse_time(u->headers_in.last_modified->value.data,
3105 u->headers_in.last_modified->value.len);
3106
3107 if (lm != NGX_ERROR-1) {
3108 ext.time = lm;
3109 ext.fd = tf->file.fd;
3110 }
3111 }
3112
3113 if (u->conf->store_lengths == NULL((void*)0)) {
3114
3115 ngx_http_map_uri_to_path(r, &path, &root, 0);
3116
3117 } else {
3118 if (ngx_http_script_run(r, &path, u->conf->store_lengths->elts, 0,
3119 u->conf->store_values->elts)
3120 == NULL((void*)0))
3121 {
3122 return;
3123 }
3124 }
3125
3126 path.len--;
3127
3128 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
3129 "upstream stores \"%s\" to \"%s\"",
3130 tf->file.name.data, path.data);
3131
3132 (void) ngx_ext_rename_file(&tf->file.name, &path, &ext);
3133}
3134
3135
3136static void
3137ngx_http_upstream_dummy_handler(ngx_http_request_t *r, ngx_http_upstream_t *u)
3138{
3139 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
3140 "http upstream dummy handler");
3141}
3142
3143
3144static void
3145ngx_http_upstream_next(ngx_http_request_t *r, ngx_http_upstream_t *u,
3146 ngx_uint_t ft_type)
3147{
3148 ngx_uint_t status, state;
3149
3150 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
3151 "http next upstream, %xi", ft_type);
3152
3153#if 0
3154 ngx_http_busy_unlock(u->conf->busy_lock, &u->busy_lock);
3155#endif
3156
3157 if (u->peer.sockaddr) {
3158
3159 if (ft_type == NGX_HTTP_UPSTREAM_FT_HTTP_4040x00000100) {
3160 state = NGX_PEER_NEXT2;
3161 } else {
3162 state = NGX_PEER_FAILED4;
3163 }
3164
3165 u->peer.free(&u->peer, u->peer.data, state);
3166 u->peer.sockaddr = NULL((void*)0);
3167 }
3168
3169 if (ft_type == NGX_HTTP_UPSTREAM_FT_TIMEOUT0x00000004) {
3170 ngx_log_error(NGX_LOG_ERR, r->connection->log, NGX_ETIMEDOUT,if ((r->connection->log)->log_level >= 4) ngx_log_error_core
(4, r->connection->log, 60, "upstream timed out")
3171 "upstream timed out")if ((r->connection->log)->log_level >= 4) ngx_log_error_core
(4, r->connection->log, 60, "upstream timed out")
;
3172 }
3173
3174 if (u->peer.cached && ft_type == NGX_HTTP_UPSTREAM_FT_ERROR0x00000002) {
3175 status = 0;
3176
3177 /* TODO: inform balancer instead */
3178
3179 u->peer.tries++;
3180
3181 } else {
3182 switch(ft_type) {
3183
3184 case NGX_HTTP_UPSTREAM_FT_TIMEOUT0x00000004:
3185 status = NGX_HTTP_GATEWAY_TIME_OUT504;
3186 break;
3187
3188 case NGX_HTTP_UPSTREAM_FT_HTTP_5000x00000010:
3189 status = NGX_HTTP_INTERNAL_SERVER_ERROR500;
3190 break;
3191
3192 case NGX_HTTP_UPSTREAM_FT_HTTP_4040x00000100:
3193 status = NGX_HTTP_NOT_FOUND404;
3194 break;
3195
3196 /*
3197 * NGX_HTTP_UPSTREAM_FT_BUSY_LOCK and NGX_HTTP_UPSTREAM_FT_MAX_WAITING
3198 * never reach here
3199 */
3200
3201 default:
3202 status = NGX_HTTP_BAD_GATEWAY502;
3203 }
3204 }
3205
3206 if (r->connection->error) {
3207 ngx_http_upstream_finalize_request(r, u,
3208 NGX_HTTP_CLIENT_CLOSED_REQUEST499);
3209 return;
3210 }
3211
3212 if (status) {
3213 u->state->status = status;
3214
3215 if (u->peer.tries == 0 || !(u->conf->next_upstream & ft_type)) {
3216
3217#if (NGX_HTTP_CACHE1)
3218
3219 if (u->cache_status == NGX_HTTP_CACHE_EXPIRED3
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_OK0) {
3227 u->cache_status = NGX_HTTP_CACHE_STALE4;
3228 rc = ngx_http_upstream_cache_send(r, u);
3229 }
3230
3231 ngx_http_upstream_finalize_request(r, u, rc);
3232 return;
3233 }
3234#endif
3235
3236 ngx_http_upstream_finalize_request(r, u, status);
3237 return;
3238 }
3239 }
3240
3241 if (u->peer.connection) {
3242 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
3243 "close http upstream connection: %d",
3244 u->peer.connection->fd);
3245#if (NGX_HTTP_SSL)
3246
3247 if (u->peer.connection->ssl) {
3248 u->peer.connection->ssl->no_wait_shutdown = 1;
3249 u->peer.connection->ssl->no_send_shutdown = 1;
3250
3251 (void) ngx_ssl_shutdown(u->peer.connection);
3252 }
3253#endif
3254
3255 if (u->peer.connection->pool) {
3256 ngx_destroy_pool(u->peer.connection->pool);
3257 }
3258
3259 ngx_close_connection(u->peer.connection);
3260 u->peer.connection = NULL((void*)0);
3261 }
3262
3263#if 0
3264 if (u->conf->busy_lock && !u->busy_locked) {
3265 ngx_http_upstream_busy_lock(p);
3266 return;
3267 }
3268#endif
3269
3270 ngx_http_upstream_connect(r, u);
3271}
3272
3273
3274static void
3275ngx_http_upstream_cleanup(void *data)
3276{
3277 ngx_http_request_t *r = data;
3278
3279 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
3280 "cleanup http upstream request: \"%V\"", &r->uri);
3281
3282 ngx_http_upstream_finalize_request(r, r->upstream, NGX_DONE-4);
3283}
3284
3285
3286static void
3287ngx_http_upstream_finalize_request(ngx_http_request_t *r,
3288 ngx_http_upstream_t *u, ngx_int_t rc)
3289{
3290 ngx_time_t *tp;
3291
3292 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
3293 "finalize http upstream request: %i", rc);
3294
3295 if (u->cleanup) {
1
Taking false branch
3296 *u->cleanup = NULL((void*)0);
3297 u->cleanup = NULL((void*)0);
3298 }
3299
3300 if (u->resolved && u->resolved->ctx) {
3301 ngx_resolve_name_done(u->resolved->ctx);
3302 u->resolved->ctx = NULL((void*)0);
3303 }
3304
3305 if (u->state && u->state->response_sec) {
3306 tp = ngx_timeofday()(ngx_time_t *) ngx_cached_time;
3307 u->state->response_sec = tp->sec - u->state->response_sec;
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 }
3313 }
3314
3315 u->finalize_request(r, rc);
3316
3317 if (u->peer.free && u->peer.sockaddr) {
3318 u->peer.free(&u->peer, u->peer.data, 0);
3319 u->peer.sockaddr = NULL((void*)0);
3320 }
3321
3322 if (u->peer.connection) {
2
Taking false branch
3323
3324#if (NGX_HTTP_SSL)
3325
3326 /* TODO: do not shutdown persistent connection */
3327
3328 if (u->peer.connection->ssl) {
3329
3330 /*
3331 * We send the "close notify" shutdown alert to the upstream only
3332 * and do not wait its "close notify" shutdown alert.
3333 * It is acceptable according to the TLS standard.
3334 */
3335
3336 u->peer.connection->ssl->no_wait_shutdown = 1;
3337
3338 (void) ngx_ssl_shutdown(u->peer.connection);
3339 }
3340#endif
3341
3342 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
3343 "close http upstream connection: %d",
3344 u->peer.connection->fd);
3345
3346 if (u->peer.connection->pool) {
3347 ngx_destroy_pool(u->peer.connection->pool);
3348 }
3349
3350 ngx_close_connection(u->peer.connection);
3351 }
3352
3353 u->peer.connection = NULL((void*)0);
3354
3355 if (u->pipe && u->pipe->temp_file) {
3
Assuming pointer value is null
3356 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
3357 "http upstream temp fd: %d",
3358 u->pipe->temp_file->file.fd);
3359 }
3360
3361 if (u->store && u->pipe && u->pipe->temp_file
3362 && u->pipe->temp_file->file.fd != NGX_INVALID_FILE-1)
3363 {
3364 if (ngx_delete_file(u->pipe->temp_file->file.name.data)unlink((const char *) u->pipe->temp_file->file.name.
data)
3365 == NGX_FILE_ERROR-1)
3366 {
3367 ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,if ((r->connection->log)->log_level >= 3) ngx_log_error_core
(3, r->connection->log, (*__error()), "unlink()" " \"%s\" failed"
, u->pipe->temp_file->file.name.data)
3368 ngx_delete_file_n " \"%s\" failed",if ((r->connection->log)->log_level >= 3) ngx_log_error_core
(3, r->connection->log, (*__error()), "unlink()" " \"%s\" failed"
, u->pipe->temp_file->file.name.data)
3369 u->pipe->temp_file->file.name.data)if ((r->connection->log)->log_level >= 3) ngx_log_error_core
(3, r->connection->log, (*__error()), "unlink()" " \"%s\" failed"
, u->pipe->temp_file->file.name.data)
;
3370 }
3371 }
3372
3373#if (NGX_HTTP_CACHE1)
3374
3375 if (r->cache) {
4
Taking true branch
3376
3377 if (u->cacheable) {
5
Taking false branch
3378
3379 if (rc == NGX_HTTP_BAD_GATEWAY502 || rc == NGX_HTTP_GATEWAY_TIME_OUT504) {
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()ngx_cached_time->sec + valid;
3386 r->cache->error = rc;
3387 }
3388 }
3389 }
3390
3391 ngx_http_file_cache_free(r->cache, u->pipe->temp_file);
6
Access to field 'temp_file' results in a dereference of a null pointer (loaded from field 'pipe')
3392 }
3393
3394#endif
3395
3396 if (u->header_sent
3397 && rc != NGX_HTTP_REQUEST_TIME_OUT408
3398 && (rc == NGX_ERROR-1 || rc >= NGX_HTTP_SPECIAL_RESPONSE300))
3399 {
3400 rc = 0;
3401 }
3402
3403 if (rc == NGX_DECLINED-5) {
3404 return;
3405 }
3406
3407 r->connection->log->action = "sending to client";
3408
3409 if (rc == 0
3410 && !r->header_only
3411#if (NGX_HTTP_CACHE1)
3412 && !r->cached
3413#endif
3414 )
3415 {
3416 rc = ngx_http_send_special(r, NGX_HTTP_LAST1);
3417 }
3418
3419 ngx_http_finalize_request(r, rc);
3420}
3421
3422
3423static ngx_int_t
3424ngx_http_upstream_process_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
3425 ngx_uint_t offset)
3426{
3427 ngx_table_elt_t **ph;
3428
3429 ph = (ngx_table_elt_t **) ((char *) &r->upstream->headers_in + offset);
3430
3431 if (*ph == NULL((void*)0)) {
3432 *ph = h;
3433 }
3434
3435 return NGX_OK0;
3436}
3437
3438
3439static ngx_int_t
3440ngx_http_upstream_ignore_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
3441 ngx_uint_t offset)
3442{
3443 return NGX_OK0;
3444}
3445
3446
3447static ngx_int_t
3448ngx_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_OK0;
3459}
3460
3461
3462static ngx_int_t
3463ngx_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_CACHE1)
3467 ngx_http_upstream_t *u;
3468
3469 u = r->upstream;
3470
3471 if (!(u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_SET_COOKIE0x00000020)) {
3472 u->cacheable = 0;
3473 }
3474#endif
3475
3476 return NGX_OK0;
3477}
3478
3479
3480static ngx_int_t
3481ngx_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;
3490
3491 if (pa->elts == NULL((void*)0)) {
3492 if (ngx_array_init(pa, r->pool, 2, sizeof(ngx_table_elt_t *)) != NGX_OK0)
3493 {
3494 return NGX_ERROR-1;
3495 }
3496 }
3497
3498 ph = ngx_array_push(pa);
3499 if (ph == NULL((void*)0)) {
3500 return NGX_ERROR-1;
3501 }
3502
3503 *ph = h;
3504
3505#if (NGX_HTTP_CACHE1)
3506 {
3507 u_char *p, *last;
3508 ngx_int_t n;
3509
3510 if (u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_CACHE_CONTROL0x00000010) {
3511 return NGX_OK0;
3512 }
3513
3514 if (r->cache == NULL((void*)0)) {
3515 return NGX_OK0;
3516 }
3517
3518 if (r->cache->valid_sec != 0) {
3519 return NGX_OK0;
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((void*)0)
3526 || ngx_strlcasestrn(p, last, (u_char *) "no-store", 8 - 1) != NULL((void*)0)
3527 || ngx_strlcasestrn(p, last, (u_char *) "private", 7 - 1) != NULL((void*)0))
3528 {
3529 u->cacheable = 0;
3530 return NGX_OK0;
3531 }
3532
3533 p = ngx_strlcasestrn(p, last, (u_char *) "max-age=", 8 - 1);
3534
3535 if (p == NULL((void*)0)) {
3536 return NGX_OK0;
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_OK0;
3553 }
3554
3555 if (n == 0) {
3556 u->cacheable = 0;
3557 return NGX_OK0;
3558 }
3559
3560 r->cache->valid_sec = ngx_time()ngx_cached_time->sec + n;
3561 }
3562#endif
3563
3564 return NGX_OK0;
3565}
3566
3567
3568static ngx_int_t
3569ngx_http_upstream_process_expires(ngx_http_request_t *r, ngx_table_elt_t *h,
3570 ngx_uint_t offset)
3571{
3572 ngx_http_upstream_t *u;
3573
3574 u = r->upstream;
3575 u->headers_in.expires = h;
3576
3577#if (NGX_HTTP_CACHE1)
3578 {
3579 time_t expires;
3580
3581 if (u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_EXPIRES0x00000008) {
3582 return NGX_OK0;
3583 }
3584
3585 if (r->cache == NULL((void*)0)) {
3586 return NGX_OK0;
3587 }
3588
3589 if (r->cache->valid_sec != 0) {
3590 return NGX_OK0;
3591 }
3592
3593 expires = ngx_http_parse_time(h->value.data, h->value.len);
3594
3595 if (expires == NGX_ERROR-1 || expires < ngx_time()ngx_cached_time->sec) {
3596 u->cacheable = 0;
3597 return NGX_OK0;
3598 }
3599
3600 r->cache->valid_sec = expires;
3601 }
3602#endif
3603
3604 return NGX_OK0;
3605}
3606
3607
3608static ngx_int_t
3609ngx_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_CACHE1)
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_EXPIRES0x00000004) {
3624 return NGX_OK0;
3625 }
3626
3627 if (r->cache == NULL((void*)0)) {
3628 return NGX_OK0;
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-1:
3643 return NGX_OK0;
3644
3645 default:
3646 r->cache->valid_sec = ngx_time()ngx_cached_time->sec + n;
3647 return NGX_OK0;
3648 }
3649 }
3650
3651 p++;
3652 len--;
3653
3654 n = ngx_atoi(p, len);
3655
3656 if (n != NGX_ERROR-1) {
3657 r->cache->valid_sec = n;
3658 }
3659 }
3660#endif
3661
3662 return NGX_OK0;
3663}
3664
3665
3666static ngx_int_t
3667ngx_http_upstream_process_limit_rate(ngx_http_request_t *r, ngx_table_elt_t *h,
3668 ngx_uint_t offset)
3669{
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_RATE0x00000040) {
3677 return NGX_OK0;
3678 }
3679
3680 n = ngx_atoi(h->value.data, h->value.len);
3681
3682 if (n != NGX_ERROR-1) {
3683 r->limit_rate = (size_t) n;
3684 }
3685
3686 return NGX_OK0;
3687}
3688
3689
3690static ngx_int_t
3691ngx_http_upstream_process_buffering(ngx_http_request_t *r, ngx_table_elt_t *h,
3692 ngx_uint_t offset)
3693{
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_BUFFERING0x00000080) {
3700 return NGX_OK0;
3701 }
3702
3703 if (u->conf->change_buffering) {
3704
3705 if (h->value.len == 2) {
3706 c0 = ngx_tolower(h->value.data[0])(u_char) ((h->value.data[0] >= 'A' && h->value
.data[0] <= 'Z') ? (h->value.data[0] | 0x20) : h->value
.data[0])
;
3707 c1 = ngx_tolower(h->value.data[1])(u_char) ((h->value.data[1] >= 'A' && h->value
.data[1] <= 'Z') ? (h->value.data[1] | 0x20) : h->value
.data[1])
;
3708
3709 if (c0 == 'n' && c1 == 'o') {
3710 u->buffering = 0;
3711 }
3712
3713 } else if (h->value.len == 3) {
3714 c0 = ngx_tolower(h->value.data[0])(u_char) ((h->value.data[0] >= 'A' && h->value
.data[0] <= 'Z') ? (h->value.data[0] | 0x20) : h->value
.data[0])
;
3715 c1 = ngx_tolower(h->value.data[1])(u_char) ((h->value.data[1] >= 'A' && h->value
.data[1] <= 'Z') ? (h->value.data[1] | 0x20) : h->value
.data[1])
;
3716 c2 = ngx_tolower(h->value.data[2])(u_char) ((h->value.data[2] >= 'A' && h->value
.data[2] <= 'Z') ? (h->value.data[2] | 0x20) : h->value
.data[2])
;
3717
3718 if (c0 == 'y' && c1 == 'e' && c2 == 's') {
3719 u->buffering = 1;
3720 }
3721 }
3722 }
3723
3724 return NGX_OK0;
3725}
3726
3727
3728static ngx_int_t
3729ngx_http_upstream_process_charset(ngx_http_request_t *r, ngx_table_elt_t *h,
3730 ngx_uint_t offset)
3731{
3732 if (r->upstream->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_XA_CHARSET0x00000100) {
3733 return NGX_OK0;
3734 }
3735
3736 r->headers_out.override_charset = &h->value;
3737
3738 return NGX_OK0;
3739}
3740
3741
3742static ngx_int_t
3743ngx_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((void*)0))
3751 {
3752 r->upstream->headers_in.connection_close = 1;
3753 }
3754
3755 return NGX_OK0;
3756}
3757
3758
3759static ngx_int_t
3760ngx_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((void*)0))
3768 {
3769 r->upstream->headers_in.chunked = 1;
3770 }
3771
3772 return NGX_OK0;
3773}
3774
3775
3776static ngx_int_t
3777ngx_http_upstream_copy_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
3778 ngx_uint_t offset)
3779{
3780 ngx_table_elt_t *ho, **ph;
3781
3782 ho = ngx_list_push(&r->headers_out.headers);
3783 if (ho == NULL((void*)0)) {
3784 return NGX_ERROR-1;
3785 }
3786
3787 *ho = *h;
3788
3789 if (offset) {
3790 ph = (ngx_table_elt_t **) ((char *) &r->headers_out + offset);
3791 *ph = ho;
3792 }
3793
3794 return NGX_OK0;
3795}
3796
3797
3798static ngx_int_t
3799ngx_http_upstream_copy_multi_header_lines(ngx_http_request_t *r,
3800 ngx_table_elt_t *h, ngx_uint_t offset)
3801{
3802 ngx_array_t *pa;
3803 ngx_table_elt_t *ho, **ph;
3804
3805 pa = (ngx_array_t *) ((char *) &r->headers_out + offset);
3806
3807 if (pa->elts == NULL((void*)0)) {
3808 if (ngx_array_init(pa, r->pool, 2, sizeof(ngx_table_elt_t *)) != NGX_OK0)
3809 {
3810 return NGX_ERROR-1;
3811 }
3812 }
3813
3814 ph = ngx_array_push(pa);
3815 if (ph == NULL((void*)0)) {
3816 return NGX_ERROR-1;
3817 }
3818
3819 ho = ngx_list_push(&r->headers_out.headers);
3820 if (ho == NULL((void*)0)) {
3821 return NGX_ERROR-1;
3822 }
3823
3824 *ho = *h;
3825 *ph = ho;
3826
3827 return NGX_OK0;
3828}
3829
3830
3831static ngx_int_t
3832ngx_http_upstream_copy_content_type(ngx_http_request_t *r, ngx_table_elt_t *h,
3833 ngx_uint_t offset)
3834{
3835 u_char *p, *last;
3836
3837 r->headers_out.content_type_len = h->value.len;
3838 r->headers_out.content_type = h->value;
3839 r->headers_out.content_type_lowcase = NULL((void*)0);
3840
3841 for (p = h->value.data; *p; p++) {
3842
3843 if (*p != ';') {
3844 continue;
3845 }
3846
3847 last = p;
3848
3849 while (*++p == ' ') { /* void */ }
3850
3851 if (*p == '\0') {
3852 return NGX_OK0;
3853 }
3854
3855 if (ngx_strncasecmp(p, (u_char *) "charset=", 8) != 0) {
3856 continue;
3857 }
3858
3859 p += 8;
3860
3861 r->headers_out.content_type_len = last - h->value.data;
3862
3863 if (*p == '"') {
3864 p++;
3865 }
3866
3867 last = h->value.data + h->value.len;
3868
3869 if (*(last - 1) == '"') {
3870 last--;
3871 }
3872
3873 r->headers_out.charset.len = last - p;
3874 r->headers_out.charset.data = p;
3875
3876 return NGX_OK0;
3877 }
3878
3879 return NGX_OK0;
3880}
3881
3882
3883static ngx_int_t
3884ngx_http_upstream_copy_last_modified(ngx_http_request_t *r, ngx_table_elt_t *h,
3885 ngx_uint_t offset)
3886{
3887 ngx_table_elt_t *ho;
3888
3889 ho = ngx_list_push(&r->headers_out.headers);
3890 if (ho == NULL((void*)0)) {
3891 return NGX_ERROR-1;
3892 }
3893
3894 *ho = *h;
3895
3896 r->headers_out.last_modified = ho;
3897
3898#if (NGX_HTTP_CACHE1)
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
3906
3907 return NGX_OK0;
3908}
3909
3910
3911static ngx_int_t
3912ngx_http_upstream_rewrite_location(ngx_http_request_t *r, ngx_table_elt_t *h,
3913 ngx_uint_t offset)
3914{
3915 ngx_int_t rc;
3916 ngx_table_elt_t *ho;
3917
3918 ho = ngx_list_push(&r->headers_out.headers);
3919 if (ho == NULL((void*)0)) {
3920 return NGX_ERROR-1;
3921 }
3922
3923 *ho = *h;
3924
3925 if (r->upstream->rewrite_redirect) {
3926 rc = r->upstream->rewrite_redirect(r, ho, 0);
3927
3928 if (rc == NGX_DECLINED-5) {
3929 return NGX_OK0;
3930 }
3931
3932 if (rc == NGX_OK0) {
3933 r->headers_out.location = ho;
3934
3935 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
3936 "rewritten location: \"%V\"", &ho->value);
3937 }
3938
3939 return rc;
3940 }
3941
3942 if (ho->value.data[0] != '/') {
3943 r->headers_out.location = ho;
3944 }
3945
3946 /*
3947 * we do not set r->headers_out.location here to avoid the handling
3948 * the local redirects without a host name by ngx_http_header_filter()
3949 */
3950
3951 return NGX_OK0;
3952}
3953
3954
3955static ngx_int_t
3956ngx_http_upstream_rewrite_refresh(ngx_http_request_t *r, ngx_table_elt_t *h,
3957 ngx_uint_t offset)
3958{
3959 u_char *p;
3960 ngx_int_t rc;
3961 ngx_table_elt_t *ho;
3962
3963 ho = ngx_list_push(&r->headers_out.headers);
3964 if (ho == NULL((void*)0)) {
3965 return NGX_ERROR-1;
3966 }
3967
3968 *ho = *h;
3969
3970 if (r->upstream->rewrite_redirect) {
3971
3972 p = ngx_strcasestrn(ho->value.data, "url=", 4 - 1);
3973
3974 if (p) {
3975 rc = r->upstream->rewrite_redirect(r, ho, p + 4 - ho->value.data);
3976
3977 } else {
3978 return NGX_OK0;
3979 }
3980
3981 if (rc == NGX_DECLINED-5) {
3982 return NGX_OK0;
3983 }
3984
3985 if (rc == NGX_OK0) {
3986 r->headers_out.refresh = ho;
3987
3988 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
3989 "rewritten refresh: \"%V\"", &ho->value);
3990 }
3991
3992 return rc;
3993 }
3994
3995 r->headers_out.refresh = ho;
3996
3997 return NGX_OK0;
3998}
3999
4000
4001static ngx_int_t
4002ngx_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((void*)0)) {
4010 return NGX_ERROR-1;
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-5) {
4019 return NGX_OK0;
4020 }
4021
4022#if (NGX_DEBUG)
4023 if (rc == NGX_OK0) {
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_OK0;
4033}
4034
4035
4036static ngx_int_t
4037ngx_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_CACHE1)
4043
4044 if (r->cached) {
4045 r->allow_ranges = 1;
4046 return NGX_OK0;
4047
4048 }
4049
4050#endif
4051
4052 ho = ngx_list_push(&r->headers_out.headers);
4053 if (ho == NULL((void*)0)) {
4054 return NGX_ERROR-1;
4055 }
4056
4057 *ho = *h;
4058
4059 r->headers_out.accept_ranges = ho;
4060
4061 return NGX_OK0;
4062}
4063
4064
4065#if (NGX_HTTP_GZIP1)
4066
4067static ngx_int_t
4068ngx_http_upstream_copy_content_encoding(ngx_http_request_t *r,
4069 ngx_table_elt_t *h, ngx_uint_t offset)
4070{
4071 ngx_table_elt_t *ho;
4072
4073 ho = ngx_list_push(&r->headers_out.headers);
4074 if (ho == NULL((void*)0)) {
4075 return NGX_ERROR-1;
4076 }
4077
4078 *ho = *h;
4079
4080 r->headers_out.content_encoding = ho;
4081
4082 return NGX_OK0;
4083}
4084
4085#endif
4086
4087
4088static ngx_int_t
4089ngx_http_upstream_add_variables(ngx_conf_t *cf)
4090{
4091 ngx_http_variable_t *var, *v;
4092
4093 for (v = ngx_http_upstream_vars; v->name.len; v++) {
4094 var = ngx_http_add_variable(cf, &v->name, v->flags);
4095 if (var == NULL((void*)0)) {
4096 return NGX_ERROR-1;
4097 }
4098
4099 var->get_handler = v->get_handler;
4100 var->data = v->data;
4101 }
4102
4103 return NGX_OK0;
4104}
4105
4106
4107static ngx_int_t
4108ngx_http_upstream_addr_variable(ngx_http_request_t *r,
4109 ngx_http_variable_value_t *v, uintptr_t data)
4110{
4111 u_char *p;
4112 size_t len;
4113 ngx_uint_t i;
4114 ngx_http_upstream_state_t *state;
4115
4116 v->valid = 1;
4117 v->no_cacheable = 0;
4118 v->not_found = 0;
4119
4120 if (r->upstream_states == NULL((void*)0) || r->upstream_states->nelts == 0) {
4121 v->not_found = 1;
4122 return NGX_OK0;
4123 }
4124
4125 len = 0;
4126 state = r->upstream_states->elts;
4127
4128 for (i = 0; i < r->upstream_states->nelts; i++) {
4129 if (state[i].peer) {
4130 len += state[i].peer->len + 2;
4131
4132 } else {
4133 len += 3;
4134 }
4135 }
4136
4137 p = ngx_pnalloc(r->pool, len);
4138 if (p == NULL((void*)0)) {
4139 return NGX_ERROR-1;
4140 }
4141
4142 v->data = p;
4143
4144 i = 0;
4145
4146 for ( ;; ) {
4147 if (state[i].peer) {
4148 p = ngx_cpymem(p, state[i].peer->data, state[i].peer->len)(((u_char *) ((__builtin_object_size (p, 0) != (size_t) -1) ?
__builtin___memcpy_chk (p, state[i].peer->data, state[i].
peer->len, __builtin_object_size (p, 0)) : __inline_memcpy_chk
(p, state[i].peer->data, state[i].peer->len))) + (state
[i].peer->len))
;
4149 }
4150
4151 if (++i == r->upstream_states->nelts) {
4152 break;
4153 }
4154
4155 if (state[i].peer) {
4156 *p++ = ',';
4157 *p++ = ' ';
4158
4159 } else {
4160 *p++ = ' ';
4161 *p++ = ':';
4162 *p++ = ' ';
4163
4164 if (++i == r->upstream_states->nelts) {
4165 break;
4166 }
4167
4168 continue;
4169 }
4170 }
4171
4172 v->len = p - v->data;
4173
4174 return NGX_OK0;
4175}
4176
4177
4178static ngx_int_t
4179ngx_http_upstream_status_variable(ngx_http_request_t *r,
4180 ngx_http_variable_value_t *v, uintptr_t data)
4181{
4182 u_char *p;
4183 size_t len;
4184 ngx_uint_t i;
4185 ngx_http_upstream_state_t *state;
4186
4187 v->valid = 1;
4188 v->no_cacheable = 0;
4189 v->not_found = 0;
4190
4191 if (r->upstream_states == NULL((void*)0) || r->upstream_states->nelts == 0) {
4192 v->not_found = 1;
4193 return NGX_OK0;
4194 }
4195
4196 len = r->upstream_states->nelts * (3 + 2);
4197
4198 p = ngx_pnalloc(r->pool, len);
4199 if (p == NULL((void*)0)) {
4200 return NGX_ERROR-1;
4201 }
4202
4203 v->data = p;
4204
4205 i = 0;
4206 state = r->upstream_states->elts;
4207
4208 for ( ;; ) {
4209 if (state[i].status) {
4210 p = ngx_sprintf(p, "%ui", state[i].status);
4211
4212 } else {
4213 *p++ = '-';
4214 }
4215
4216 if (++i == r->upstream_states->nelts) {
4217 break;
4218 }
4219
4220 if (state[i].peer) {
4221 *p++ = ',';
4222 *p++ = ' ';
4223
4224 } else {
4225 *p++ = ' ';
4226 *p++ = ':';
4227 *p++ = ' ';
4228
4229 if (++i == r->upstream_states->nelts) {
4230 break;
4231 }
4232
4233 continue;
4234 }
4235 }
4236
4237 v->len = p - v->data;
4238
4239 return NGX_OK0;
4240}
4241
4242
4243static ngx_int_t
4244ngx_http_upstream_response_time_variable(ngx_http_request_t *r,
4245 ngx_http_variable_value_t *v, uintptr_t data)
4246{
4247 u_char *p;
4248 size_t len;
4249 ngx_uint_t i;
4250 ngx_msec_int_t ms;
4251 ngx_http_upstream_state_t *state;
4252
4253 v->valid = 1;
4254 v->no_cacheable = 0;
4255 v->not_found = 0;
4256
4257 if (r->upstream_states == NULL((void*)0) || r->upstream_states->nelts == 0) {
4258 v->not_found = 1;
4259 return NGX_OK0;
4260 }
4261
4262 len = r->upstream_states->nelts * (NGX_TIME_T_LEN(sizeof("-9223372036854775808") - 1) + 4 + 2);
4263
4264 p = ngx_pnalloc(r->pool, len);
4265 if (p == NULL((void*)0)) {
4266 return NGX_ERROR-1;
4267 }
4268
4269 v->data = p;
4270
4271 i = 0;
4272 state = r->upstream_states->elts;
4273
4274 for ( ;; ) {
4275 if (state[i].status) {
4276 ms = (ngx_msec_int_t)
4277 (state[i].response_sec * 1000 + state[i].response_msec);
4278 ms = ngx_max(ms, 0)((ms < 0) ? (0) : (ms));
4279 p = ngx_sprintf(p, "%d.%03d", ms / 1000, ms % 1000);
4280
4281 } else {
4282 *p++ = '-';
4283 }
4284
4285 if (++i == r->upstream_states->nelts) {
4286 break;
4287 }
4288
4289 if (state[i].peer) {
4290 *p++ = ',';
4291 *p++ = ' ';
4292
4293 } else {
4294 *p++ = ' ';
4295 *p++ = ':';
4296 *p++ = ' ';
4297
4298 if (++i == r->upstream_states->nelts) {
4299 break;
4300 }
4301
4302 continue;
4303 }
4304 }
4305
4306 v->len = p - v->data;
4307
4308 return NGX_OK0;
4309}
4310
4311
4312static ngx_int_t
4313ngx_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((void*)0) || r->upstream_states->nelts == 0) {
4326 v->not_found = 1;
4327 return NGX_OK0;
4328 }
4329
4330 len = r->upstream_states->nelts * (NGX_OFF_T_LEN(sizeof("-9223372036854775808") - 1) + 2);
4331
4332 p = ngx_pnalloc(r->pool, len);
4333 if (p == NULL((void*)0)) {
4334 return NGX_ERROR-1;
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_OK0;
4369}
4370
4371
4372ngx_int_t
4373ngx_http_upstream_header_variable(ngx_http_request_t *r,
4374 ngx_http_variable_value_t *v, uintptr_t data)
4375{
4376 if (r->upstream == NULL((void*)0)) {
4377 v->not_found = 1;
4378 return NGX_OK0;
4379 }
4380
4381 return ngx_http_variable_unknown_header(v, (ngx_str_t *) data,
4382 &r->upstream->headers_in.headers.part,
4383 sizeof("upstream_http_") - 1);
4384}
4385
4386
4387#if (NGX_HTTP_CACHE1)
4388
4389ngx_int_t
4390ngx_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((void*)0) || r->upstream->cache_status == 0) {
4396 v->not_found = 1;
4397 return NGX_OK0;
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_OK0;
4409}
4410
4411#endif
4412
4413
4414static char *
4415ngx_http_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
4416{
4417 char *rv;
4418 void *mconf;
4419 ngx_str_t *value;
4420 ngx_url_t u;
4421 ngx_uint_t m;
4422 ngx_conf_t pcf;
4423 ngx_http_module_t *module;
4424 ngx_http_conf_ctx_t *ctx, *http_ctx;
4425 ngx_http_upstream_srv_conf_t *uscf;
4426
4427 ngx_memzero(&u, sizeof(ngx_url_t))(void) ((__builtin_object_size (&u, 0) != (size_t) -1) ? __builtin___memset_chk
(&u, 0, sizeof(ngx_url_t), __builtin_object_size (&u
, 0)) : __inline_memset_chk (&u, 0, sizeof(ngx_url_t)))
;
4428
4429 value = cf->args->elts;
4430 u.host = value[1];
4431 u.no_resolve = 1;
4432 u.no_port = 1;
4433
4434 uscf = ngx_http_upstream_add(cf, &u, NGX_HTTP_UPSTREAM_CREATE0x0001
4435 |NGX_HTTP_UPSTREAM_WEIGHT0x0002
4436 |NGX_HTTP_UPSTREAM_MAX_FAILS0x0004
4437 |NGX_HTTP_UPSTREAM_FAIL_TIMEOUT0x0008
4438 |NGX_HTTP_UPSTREAM_DOWN0x0010
4439 |NGX_HTTP_UPSTREAM_BACKUP0x0020);
4440 if (uscf == NULL((void*)0)) {
4441 return NGX_CONF_ERROR(void *) -1;
4442 }
4443
4444
4445 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
4446 if (ctx == NULL((void*)0)) {
4447 return NGX_CONF_ERROR(void *) -1;
4448 }
4449
4450 http_ctx = cf->ctx;
4451 ctx->main_conf = http_ctx->main_conf;
4452
4453 /* the upstream{}'s srv_conf */
4454
4455 ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
4456 if (ctx->srv_conf == NULL((void*)0)) {
4457 return NGX_CONF_ERROR(void *) -1;
4458 }
4459
4460 ctx->srv_conf[ngx_http_upstream_module.ctx_index] = uscf;
4461
4462 uscf->srv_conf = ctx->srv_conf;
4463
4464
4465 /* the upstream{}'s loc_conf */
4466
4467 ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
4468 if (ctx->loc_conf == NULL((void*)0)) {
4469 return NGX_CONF_ERROR(void *) -1;
4470 }
4471
4472 for (m = 0; ngx_modules[m]; m++) {
4473 if (ngx_modules[m]->type != NGX_HTTP_MODULE0x50545448) {
4474 continue;
4475 }
4476
4477 module = ngx_modules[m]->ctx;
4478
4479 if (module->create_srv_conf) {
4480 mconf = module->create_srv_conf(cf);
4481 if (mconf == NULL((void*)0)) {
4482 return NGX_CONF_ERROR(void *) -1;
4483 }
4484
4485 ctx->srv_conf[ngx_modules[m]->ctx_index] = mconf;
4486 }
4487
4488 if (module->create_loc_conf) {
4489 mconf = module->create_loc_conf(cf);
4490 if (mconf == NULL((void*)0)) {
4491 return NGX_CONF_ERROR(void *) -1;
4492 }
4493
4494 ctx->loc_conf[ngx_modules[m]->ctx_index] = mconf;
4495 }
4496 }
4497
4498
4499 /* parse inside upstream{} */
4500
4501 pcf = *cf;
4502 cf->ctx = ctx;
4503 cf->cmd_type = NGX_HTTP_UPS_CONF0x10000000;
4504
4505 rv = ngx_conf_parse(cf, NULL((void*)0));
4506
4507 *cf = pcf;
4508
4509 if (rv != NGX_CONF_OK((void*)0)) {
4510 return rv;
4511 }
4512
4513 if (uscf->servers == NULL((void*)0)) {
4514 ngx_conf_log_error(NGX_LOG_EMERG1, cf, 0,
4515 "no servers are inside upstream");
4516 return NGX_CONF_ERROR(void *) -1;
4517 }
4518
4519 return rv;
4520}
4521
4522
4523static char *
4524ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
4525{
4526 ngx_http_upstream_srv_conf_t *uscf = conf;
4527
4528 time_t fail_timeout;
4529 ngx_str_t *value, s;
4530 ngx_url_t u;
4531 ngx_int_t weight, max_fails;
4532 ngx_uint_t i;
4533 ngx_http_upstream_server_t *us;
4534
4535 if (uscf->servers == NULL((void*)0)) {
4536 uscf->servers = ngx_array_create(cf->pool, 4,
4537 sizeof(ngx_http_upstream_server_t));
4538 if (uscf->servers == NULL((void*)0)) {
4539 return NGX_CONF_ERROR(void *) -1;
4540 }
4541 }
4542
4543 us = ngx_array_push(uscf->servers);
4544 if (us == NULL((void*)0)) {
4545 return NGX_CONF_ERROR(void *) -1;
4546 }
4547
4548 ngx_memzero(us, sizeof(ngx_http_upstream_server_t))(void) ((__builtin_object_size (us, 0) != (size_t) -1) ? __builtin___memset_chk
(us, 0, sizeof(ngx_http_upstream_server_t), __builtin_object_size
(us, 0)) : __inline_memset_chk (us, 0, sizeof(ngx_http_upstream_server_t
)))
;
4549
4550 value = cf->args->elts;
4551
4552 ngx_memzero(&u, sizeof(ngx_url_t))(void) ((__builtin_object_size (&u, 0) != (size_t) -1) ? __builtin___memset_chk
(&u, 0, sizeof(ngx_url_t), __builtin_object_size (&u
, 0)) : __inline_memset_chk (&u, 0, sizeof(ngx_url_t)))
;
4553
4554 u.url = value[1];
4555 u.default_port = 80;
4556
4557 if (ngx_parse_url(cf->pool, &u) != NGX_OK0) {
4558 if (u.err) {
4559 ngx_conf_log_error(NGX_LOG_EMERG1, cf, 0,
4560 "%s in upstream \"%V\"", u.err, &u.url);
4561 }
4562
4563 return NGX_CONF_ERROR(void *) -1;
4564 }
4565
4566 weight = 1;
4567 max_fails = 1;
4568 fail_timeout = 10;
4569
4570 for (i = 2; i < cf->args->nelts; i++) {
4571
4572 if (ngx_strncmp(value[i].data, "weight=", 7)strncmp((const char *) value[i].data, (const char *) "weight="
, 7)
== 0) {
4573
4574 if (!(uscf->flags & NGX_HTTP_UPSTREAM_WEIGHT0x0002)) {
4575 goto invalid;
4576 }
4577
4578 weight = ngx_atoi(&value[i].data[7], value[i].len - 7);
4579
4580 if (weight == NGX_ERROR-1 || weight == 0) {
4581 goto invalid;
4582 }
4583
4584 continue;
4585 }
4586
4587 if (ngx_strncmp(value[i].data, "max_fails=", 10)strncmp((const char *) value[i].data, (const char *) "max_fails="
, 10)
== 0) {
4588
4589 if (!(uscf->flags & NGX_HTTP_UPSTREAM_MAX_FAILS0x0004)) {
4590 goto invalid;
4591 }
4592
4593 max_fails = ngx_atoi(&value[i].data[10], value[i].len - 10);
4594
4595 if (max_fails == NGX_ERROR-1) {
4596 goto invalid;
4597 }
4598
4599 continue;
4600 }
4601
4602 if (ngx_strncmp(value[i].data, "fail_timeout=", 13)strncmp((const char *) value[i].data, (const char *) "fail_timeout="
, 13)
== 0) {
4603
4604 if (!(uscf->flags & NGX_HTTP_UPSTREAM_FAIL_TIMEOUT0x0008)) {
4605 goto invalid;
4606 }
4607
4608 s.len = value[i].len - 13;
4609 s.data = &value[i].data[13];
4610
4611 fail_timeout = ngx_parse_time(&s, 1);
4612
4613 if (fail_timeout == (time_t) NGX_ERROR-1) {
4614 goto invalid;
4615 }
4616
4617 continue;
4618 }
4619
4620 if (ngx_strncmp(value[i].data, "backup", 6)strncmp((const char *) value[i].data, (const char *) "backup"
, 6)
== 0) {
4621
4622 if (!(uscf->flags & NGX_HTTP_UPSTREAM_BACKUP0x0020)) {
4623 goto invalid;
4624 }
4625
4626 us->backup = 1;
4627
4628 continue;
4629 }
4630
4631 if (ngx_strncmp(value[i].data, "down", 4)strncmp((const char *) value[i].data, (const char *) "down", 4
)
== 0) {
4632
4633 if (!(uscf->flags & NGX_HTTP_UPSTREAM_DOWN0x0010)) {
4634 goto invalid;
4635 }
4636
4637 us->down = 1;
4638
4639 continue;
4640 }
4641
4642 goto invalid;
4643 }
4644
4645 us->addrs = u.addrs;
4646 us->naddrs = u.naddrs;
4647 us->weight = weight;
4648 us->max_fails = max_fails;
4649 us->fail_timeout = fail_timeout;
4650
4651 return NGX_CONF_OK((void*)0);
4652
4653invalid:
4654
4655 ngx_conf_log_error(NGX_LOG_EMERG1, cf, 0,
4656 "invalid parameter \"%V\"", &value[i]);
4657
4658 return NGX_CONF_ERROR(void *) -1;
4659}
4660
4661
4662ngx_http_upstream_srv_conf_t *
4663ngx_http_upstream_add(ngx_conf_t *cf, ngx_url_t *u, ngx_uint_t flags)
4664{
4665 ngx_uint_t i;
4666 ngx_http_upstream_server_t *us;
4667 ngx_http_upstream_srv_conf_t *uscf, **uscfp;
4668 ngx_http_upstream_main_conf_t *umcf;
4669
4670 if (!(flags & NGX_HTTP_UPSTREAM_CREATE0x0001)) {
4671
4672 if (ngx_parse_url(cf->pool, u) != NGX_OK0) {
4673 if (u->err) {
4674 ngx_conf_log_error(NGX_LOG_EMERG1, cf, 0,
4675 "%s in upstream \"%V\"", u->err, &u->url);
4676 }
4677
4678 return NULL((void*)0);
4679 }
4680 }
4681
4682 umcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_upstream_module)((ngx_http_conf_ctx_t *) cf->ctx)->main_conf[ngx_http_upstream_module
.ctx_index]
;
4683
4684 uscfp = umcf->upstreams.elts;
4685
4686 for (i = 0; i < umcf->upstreams.nelts; i++) {
4687
4688 if (uscfp[i]->host.len != u->host.len
4689 || ngx_strncasecmp(uscfp[i]->host.data, u->host.data, u->host.len)
4690 != 0)
4691 {
4692 continue;
4693 }
4694
4695 if ((flags & NGX_HTTP_UPSTREAM_CREATE0x0001)
4696 && (uscfp[i]->flags & NGX_HTTP_UPSTREAM_CREATE0x0001))
4697 {
4698 ngx_conf_log_error(NGX_LOG_EMERG1, cf, 0,
4699 "duplicate upstream \"%V\"", &u->host);
4700 return NULL((void*)0);
4701 }
4702
4703 if ((uscfp[i]->flags & NGX_HTTP_UPSTREAM_CREATE0x0001) && !u->no_port) {
4704 ngx_conf_log_error(NGX_LOG_WARN5, cf, 0,
4705 "upstream \"%V\" may not have port %d",
4706 &u->host, u->port);
4707 return NULL((void*)0);
4708 }
4709
4710 if ((flags & NGX_HTTP_UPSTREAM_CREATE0x0001) && !uscfp[i]->no_port) {
4711 ngx_log_error(NGX_LOG_WARN, cf->log, 0,if ((cf->log)->log_level >= 5) ngx_log_error_core(5,
cf->log, 0, "upstream \"%V\" may not have port %d in %s:%ui"
, &u->host, uscfp[i]->port, uscfp[i]->file_name,
uscfp[i]->line)
4712 "upstream \"%V\" may not have port %d in %s:%ui",if ((cf->log)->log_level >= 5) ngx_log_error_core(5,
cf->log, 0, "upstream \"%V\" may not have port %d in %s:%ui"
, &u->host, uscfp[i]->port, uscfp[i]->file_name,
uscfp[i]->line)
4713 &u->host, uscfp[i]->port,if ((cf->log)->log_level >= 5) ngx_log_error_core(5,
cf->log, 0, "upstream \"%V\" may not have port %d in %s:%ui"
, &u->host, uscfp[i]->port, uscfp[i]->file_name,
uscfp[i]->line)
4714 uscfp[i]->file_name, uscfp[i]->line)if ((cf->log)->log_level >= 5) ngx_log_error_core(5,
cf->log, 0, "upstream \"%V\" may not have port %d in %s:%ui"
, &u->host, uscfp[i]->port, uscfp[i]->file_name,
uscfp[i]->line)
;
4715 return NULL((void*)0);
4716 }
4717
4718 if (uscfp[i]->port && u->port
4719 && uscfp[i]->port != u->port)
4720 {
4721 continue;
4722 }
4723
4724 if (uscfp[i]->default_port && u->default_port
4725 && uscfp[i]->default_port != u->default_port)
4726 {
4727 continue;
4728 }
4729
4730 if (flags & NGX_HTTP_UPSTREAM_CREATE0x0001) {
4731 uscfp[i]->flags = flags;
4732 }
4733
4734 return uscfp[i];
4735 }
4736
4737 uscf = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_srv_conf_t));
4738 if (uscf == NULL((void*)0)) {
4739 return NULL((void*)0);
4740 }
4741
4742 uscf->flags = flags;
4743 uscf->host = u->host;
4744 uscf->file_name = cf->conf_file->file.name.data;
4745 uscf->line = cf->conf_file->line;
4746 uscf->port = u->port;
4747 uscf->default_port = u->default_port;
4748 uscf->no_port = u->no_port;
4749
4750 if (u->naddrs == 1) {
4751 uscf->servers = ngx_array_create(cf->pool, 1,
4752 sizeof(ngx_http_upstream_server_t));
4753 if (uscf->servers == NULL((void*)0)) {
4754 return NULL((void*)0);
4755 }
4756
4757 us = ngx_array_push(uscf->servers);
4758 if (us == NULL((void*)0)) {
4759 return NULL((void*)0);
4760 }
4761
4762 ngx_memzero(us, sizeof(ngx_http_upstream_server_t))(void) ((__builtin_object_size (us, 0) != (size_t) -1) ? __builtin___memset_chk
(us, 0, sizeof(ngx_http_upstream_server_t), __builtin_object_size
(us, 0)) : __inline_memset_chk (us, 0, sizeof(ngx_http_upstream_server_t
)))
;
4763
4764 us->addrs = u->addrs;
4765 us->naddrs = 1;
4766 }
4767
4768 uscfp = ngx_array_push(&umcf->upstreams);
4769 if (uscfp == NULL((void*)0)) {
4770 return NULL((void*)0);
4771 }
4772
4773 *uscfp = uscf;
4774
4775 return uscf;
4776}
4777
4778
4779char *
4780ngx_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(void *) -1) {
4794 return "is duplicate";
4795 }
4796
4797 value = cf->args->elts;
4798
4799 if (ngx_strcmp(value[1].data, "off")strcmp((const char *) value[1].data, (const char *) "off") == 0) {
4800 *plocal = NULL((void*)0);
4801 return NGX_CONF_OK((void*)0);
4802 }
4803
4804 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t))(void) ((__builtin_object_size (&ccv, 0) != (size_t) -1) ?
__builtin___memset_chk (&ccv, 0, sizeof(ngx_http_compile_complex_value_t
), __builtin_object_size (&ccv, 0)) : __inline_memset_chk
(&ccv, 0, 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_OK0) {
4811 return NGX_CONF_ERROR(void *) -1;
4812 }
4813
4814 local = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_local_t));
4815 if (local == NULL((void*)0)) {
4816 return NGX_CONF_ERROR(void *) -1;
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((void*)0)) {
4824 return NGX_CONF_ERROR(void *) -1;
4825 }
4826
4827 *local->value = cv;
4828
4829 return NGX_CONF_OK((void*)0);
4830 }
4831
4832 local->addr = ngx_palloc(cf->pool, sizeof(ngx_addr_t));
4833 if (local->addr == NULL((void*)0)) {
4834 return NGX_CONF_ERROR(void *) -1;
4835 }
4836
4837 rc = ngx_parse_addr(cf->pool, local->addr, value[1].data, value[1].len);
4838
4839 switch (rc) {
4840 case NGX_OK0:
4841 local->addr->name = value[1];
4842 return NGX_CONF_OK((void*)0);
4843
4844 case NGX_DECLINED-5:
4845 ngx_conf_log_error(NGX_LOG_EMERG1, cf, 0,
4846 "invalid address \"%V\"", &value[1]);
4847 /* fall through */
4848
4849 default:
4850 return NGX_CONF_ERROR(void *) -1;
4851 }
4852}
4853
4854
4855static ngx_addr_t *
4856ngx_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((void*)0)) {
4864 return NULL((void*)0);
4865 }
4866
4867 if (local->value == NULL((void*)0)) {
4868 return local->addr;
4869 }
4870
4871 if (ngx_http_complex_value(r, local->value, &val) != NGX_OK0) {
4872 return NULL((void*)0);
4873 }
4874
4875 if (val.len == 0) {
4876 return NULL((void*)0);
4877 }
4878
4879 addr = ngx_palloc(r->pool, sizeof(ngx_addr_t));
4880 if (addr == NULL((void*)0)) {
4881 return NULL((void*)0);
4882 }
4883
4884 rc = ngx_parse_addr(r->pool, addr, val.data, val.len);
4885
4886 switch (rc) {
4887 case NGX_OK0:
4888 addr->name = val;
4889 return addr;
4890
4891 case NGX_DECLINED-5:
4892 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,if ((r->connection->log)->log_level >= 4) ngx_log_error_core
(4, r->connection->log, 0, "invalid local address \"%V\""
, &val)
4893 "invalid local address \"%V\"", &val)if ((r->connection->log)->log_level >= 4) ngx_log_error_core
(4, r->connection->log, 0, "invalid local address \"%V\""
, &val)
;
4894 /* fall through */
4895
4896 default:
4897 return NULL((void*)0);
4898 }
4899}
4900
4901
4902char *
4903ngx_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((void*)0)) {
4915 *a = ngx_array_create(cf->pool, 4, sizeof(ngx_http_upstream_param_t));
4916 if (*a == NULL((void*)0)) {
4917 return NGX_CONF_ERROR(void *) -1;
4918 }
4919 }
4920
4921 param = ngx_array_push(*a);
4922 if (param == NULL((void*)0)) {
4923 return NGX_CONF_ERROR(void *) -1;
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")strcmp((const char *) value[3].data, (const char *) "if_not_empty"
)
!= 0) {
4934 ngx_conf_log_error(NGX_LOG_EMERG1, cf, 0,
4935 "invalid parameter \"%V\"", &value[3]);
4936 return NGX_CONF_ERROR(void *) -1;
4937 }
4938
4939 param->skip_empty = 1;
4940 }
4941
4942 return NGX_CONF_OK((void*)0);
4943}
4944
4945
4946ngx_int_t
4947ngx_http_upstream_hide_headers_hash(ngx_conf_t *cf,
4948 ngx_http_upstream_conf_t *conf, ngx_http_upstream_conf_t *prev,
4949 ngx_str_t *default_hide_headers, ngx_hash_init_t *hash)
4950{
4951 ngx_str_t *h;
4952 ngx_uint_t i, j;
4953 ngx_array_t hide_headers;
4954 ngx_hash_key_t *hk;
4955
4956 if (conf->hide_headers == NGX_CONF_UNSET_PTR(void *) -1
4957 && conf->pass_headers == NGX_CONF_UNSET_PTR(void *) -1)
4958 {
4959 conf->hide_headers = prev->hide_headers;
4960 conf->pass_headers = prev->pass_headers;
4961
4962 conf->hide_headers_hash = prev->hide_headers_hash;
4963
4964 if (conf->hide_headers_hash.buckets
4965#if (NGX_HTTP_CACHE1)
4966 && ((conf->cache == NULL((void*)0)) == (prev->cache == NULL((void*)0)))
4967#endif
4968 )
4969 {
4970 return NGX_OK0;
4971 }
4972
4973 } else {
4974 if (conf->hide_headers == NGX_CONF_UNSET_PTR(void *) -1) {
4975 conf->hide_headers = prev->hide_headers;
4976 }
4977
4978 if (conf->pass_headers == NGX_CONF_UNSET_PTR(void *) -1) {
4979 conf->pass_headers = prev->pass_headers;
4980 }
4981 }
4982
4983 if (ngx_array_init(&hide_headers, cf->temp_pool, 4, sizeof(ngx_hash_key_t))
4984 != NGX_OK0)
4985 {
4986 return NGX_ERROR-1;
4987 }
4988
4989 for (h = default_hide_headers; h->len; h++) {
4990 hk = ngx_array_push(&hide_headers);
4991 if (hk == NULL((void*)0)) {
4992 return NGX_ERROR-1;
4993 }
4994
4995 hk->key = *h;
4996 hk->key_hash = ngx_hash_key_lc(h->data, h->len);
4997 hk->value = (void *) 1;
4998 }
4999
5000 if (conf->hide_headers != NGX_CONF_UNSET_PTR(void *) -1) {
5001
5002 h = conf->hide_headers->elts;
5003
5004 for (i = 0; i < conf->hide_headers->nelts; i++) {
5005
5006 hk = hide_headers.elts;
5007
5008 for (j = 0; j < hide_headers.nelts; j++) {
5009 if (ngx_strcasecmp(h[i].data, hk[j].key.data) == 0) {
5010 goto exist;
5011 }
5012 }
5013
5014 hk = ngx_array_push(&hide_headers);
5015 if (hk == NULL((void*)0)) {
5016 return NGX_ERROR-1;
5017 }
5018
5019 hk->key = h[i];
5020 hk->key_hash = ngx_hash_key_lc(h[i].data, h[i].len);
5021 hk->value = (void *) 1;
5022
5023 exist:
5024
5025 continue;
5026 }
5027 }
5028
5029 if (conf->pass_headers != NGX_CONF_UNSET_PTR(void *) -1) {
5030
5031 h = conf->pass_headers->elts;
5032 hk = hide_headers.elts;
5033
5034 for (i = 0; i < conf->pass_headers->nelts; i++) {
5035 for (j = 0; j < hide_headers.nelts; j++) {
5036
5037 if (hk[j].key.data == NULL((void*)0)) {
5038 continue;
5039 }
5040
5041 if (ngx_strcasecmp(h[i].data, hk[j].key.data) == 0) {
5042 hk[j].key.data = NULL((void*)0);
5043 break;
5044 }
5045 }
5046 }
5047 }
5048
5049 hash->hash = &conf->hide_headers_hash;
5050 hash->key = ngx_hash_key_lc;
5051 hash->pool = cf->pool;
5052 hash->temp_pool = NULL((void*)0);
5053
5054 return ngx_hash_init(hash, hide_headers.elts, hide_headers.nelts);
5055}
5056
5057
5058static void *
5059ngx_http_upstream_create_main_conf(ngx_conf_t *cf)
5060{
5061 ngx_http_upstream_main_conf_t *umcf;
5062
5063 umcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_main_conf_t));
5064 if (umcf == NULL((void*)0)) {
5065 return NULL((void*)0);
5066 }
5067
5068 if (ngx_array_init(&umcf->upstreams, cf->pool, 4,
5069 sizeof(ngx_http_upstream_srv_conf_t *))
5070 != NGX_OK0)
5071 {
5072 return NULL((void*)0);
5073 }
5074
5075 return umcf;
5076}
5077
5078
5079static char *
5080ngx_http_upstream_init_main_conf(ngx_conf_t *cf, void *conf)
5081{
5082 ngx_http_upstream_main_conf_t *umcf = conf;
5083
5084 ngx_uint_t i;
5085 ngx_array_t headers_in;
5086 ngx_hash_key_t *hk;
5087 ngx_hash_init_t hash;
5088 ngx_http_upstream_init_pt init;
5089 ngx_http_upstream_header_t *header;
5090 ngx_http_upstream_srv_conf_t **uscfp;
5091
5092 uscfp = umcf->upstreams.elts;
5093
5094 for (i = 0; i < umcf->upstreams.nelts; i++) {
5095
5096 init = uscfp[i]->peer.init_upstream ? uscfp[i]->peer.init_upstream:
5097 ngx_http_upstream_init_round_robin;
5098
5099 if (init(cf, uscfp[i]) != NGX_OK0) {
5100 return NGX_CONF_ERROR(void *) -1;
5101 }
5102 }
5103
5104
5105 /* upstream_headers_in_hash */
5106
5107 if (ngx_array_init(&headers_in, cf->temp_pool, 32, sizeof(ngx_hash_key_t))
5108 != NGX_OK0)
5109 {
5110 return NGX_CONF_ERROR(void *) -1;
5111 }
5112
5113 for (header = ngx_http_upstream_headers_in; header->name.len; header++) {
5114 hk = ngx_array_push(&headers_in);
5115 if (hk == NULL((void*)0)) {
5116 return NGX_CONF_ERROR(void *) -1;
5117 }
5118
5119 hk->key = header->name;
5120 hk->key_hash = ngx_hash_key_lc(header->name.data, header->name.len);
5121 hk->value = header;
5122 }
5123
5124 hash.hash = &umcf->headers_in_hash;
5125 hash.key = ngx_hash_key_lc;
5126 hash.max_size = 512;
5127 hash.bucket_size = ngx_align(64, ngx_cacheline_size)(((64) + (ngx_cacheline_size - 1)) & ~(ngx_cacheline_size
- 1))
;
5128 hash.name = "upstream_headers_in_hash";
5129 hash.pool = cf->pool;
5130 hash.temp_pool = NULL((void*)0);
5131
5132 if (ngx_hash_init(&hash, headers_in.elts, headers_in.nelts) != NGX_OK0) {
5133 return NGX_CONF_ERROR(void *) -1;
5134 }
5135
5136 return NGX_CONF_OK((void*)0);
5137}