Bug Summary

File:http/ngx_http_upstream.c
Location:line 4178, 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_get(ngx_http_request_t *r,
17 ngx_http_upstream_t *u, ngx_http_file_cache_t **cache);
18static ngx_int_t ngx_http_upstream_cache_send(ngx_http_request_t *r,
19 ngx_http_upstream_t *u);
20static ngx_int_t ngx_http_upstream_cache_status(ngx_http_request_t *r,
21 ngx_http_variable_value_t *v, uintptr_t data);
22static ngx_int_t ngx_http_upstream_cache_last_modified(ngx_http_request_t *r,
23 ngx_http_variable_value_t *v, uintptr_t data);
24static ngx_int_t ngx_http_upstream_cache_etag(ngx_http_request_t *r,
25 ngx_http_variable_value_t *v, uintptr_t data);
26#endif
27
28static void ngx_http_upstream_init_request(ngx_http_request_t *r);
29static void ngx_http_upstream_resolve_handler(ngx_resolver_ctx_t *ctx);
30static void ngx_http_upstream_rd_check_broken_connection(ngx_http_request_t *r);
31static void ngx_http_upstream_wr_check_broken_connection(ngx_http_request_t *r);
32static void ngx_http_upstream_check_broken_connection(ngx_http_request_t *r,
33 ngx_event_t *ev);
34static void ngx_http_upstream_connect(ngx_http_request_t *r,
35 ngx_http_upstream_t *u);
36static ngx_int_t ngx_http_upstream_reinit(ngx_http_request_t *r,
37 ngx_http_upstream_t *u);
38static void ngx_http_upstream_send_request(ngx_http_request_t *r,
39 ngx_http_upstream_t *u, ngx_uint_t do_write);
40static ngx_int_t ngx_http_upstream_send_request_body(ngx_http_request_t *r,
41 ngx_http_upstream_t *u, ngx_uint_t do_write);
42static void ngx_http_upstream_send_request_handler(ngx_http_request_t *r,
43 ngx_http_upstream_t *u);
44static void ngx_http_upstream_read_request_handler(ngx_http_request_t *r);
45static void ngx_http_upstream_process_header(ngx_http_request_t *r,
46 ngx_http_upstream_t *u);
47static ngx_int_t ngx_http_upstream_test_next(ngx_http_request_t *r,
48 ngx_http_upstream_t *u);
49static ngx_int_t ngx_http_upstream_intercept_errors(ngx_http_request_t *r,
50 ngx_http_upstream_t *u);
51static ngx_int_t ngx_http_upstream_test_connect(ngx_connection_t *c);
52static ngx_int_t ngx_http_upstream_process_headers(ngx_http_request_t *r,
53 ngx_http_upstream_t *u);
54static void ngx_http_upstream_process_body_in_memory(ngx_http_request_t *r,
55 ngx_http_upstream_t *u);
56static void ngx_http_upstream_send_response(ngx_http_request_t *r,
57 ngx_http_upstream_t *u);
58static void ngx_http_upstream_upgrade(ngx_http_request_t *r,
59 ngx_http_upstream_t *u);
60static void ngx_http_upstream_upgraded_read_downstream(ngx_http_request_t *r);
61static void ngx_http_upstream_upgraded_write_downstream(ngx_http_request_t *r);
62static void ngx_http_upstream_upgraded_read_upstream(ngx_http_request_t *r,
63 ngx_http_upstream_t *u);
64static void ngx_http_upstream_upgraded_write_upstream(ngx_http_request_t *r,
65 ngx_http_upstream_t *u);
66static void ngx_http_upstream_process_upgraded(ngx_http_request_t *r,
67 ngx_uint_t from_upstream, ngx_uint_t do_write);
68static void
69 ngx_http_upstream_process_non_buffered_downstream(ngx_http_request_t *r);
70static void
71 ngx_http_upstream_process_non_buffered_upstream(ngx_http_request_t *r,
72 ngx_http_upstream_t *u);
73static void
74 ngx_http_upstream_process_non_buffered_request(ngx_http_request_t *r,
75 ngx_uint_t do_write);
76static ngx_int_t ngx_http_upstream_non_buffered_filter_init(void *data);
77static ngx_int_t ngx_http_upstream_non_buffered_filter(void *data,
78 ssize_t bytes);
79#if (NGX_THREADS)
80static ngx_int_t ngx_http_upstream_thread_handler(ngx_thread_task_t *task,
81 ngx_file_t *file);
82static void ngx_http_upstream_thread_event_handler(ngx_event_t *ev);
83#endif
84static ngx_int_t ngx_http_upstream_output_filter(void *data,
85 ngx_chain_t *chain);
86static void ngx_http_upstream_process_downstream(ngx_http_request_t *r);
87static void ngx_http_upstream_process_upstream(ngx_http_request_t *r,
88 ngx_http_upstream_t *u);
89static void ngx_http_upstream_process_request(ngx_http_request_t *r,
90 ngx_http_upstream_t *u);
91static void ngx_http_upstream_store(ngx_http_request_t *r,
92 ngx_http_upstream_t *u);
93static void ngx_http_upstream_dummy_handler(ngx_http_request_t *r,
94 ngx_http_upstream_t *u);
95static void ngx_http_upstream_next(ngx_http_request_t *r,
96 ngx_http_upstream_t *u, ngx_uint_t ft_type);
97static void ngx_http_upstream_cleanup(void *data);
98static void ngx_http_upstream_finalize_request(ngx_http_request_t *r,
99 ngx_http_upstream_t *u, ngx_int_t rc);
100
101static ngx_int_t ngx_http_upstream_process_header_line(ngx_http_request_t *r,
102 ngx_table_elt_t *h, ngx_uint_t offset);
103static ngx_int_t ngx_http_upstream_process_content_length(ngx_http_request_t *r,
104 ngx_table_elt_t *h, ngx_uint_t offset);
105static ngx_int_t ngx_http_upstream_process_last_modified(ngx_http_request_t *r,
106 ngx_table_elt_t *h, ngx_uint_t offset);
107static ngx_int_t ngx_http_upstream_process_set_cookie(ngx_http_request_t *r,
108 ngx_table_elt_t *h, ngx_uint_t offset);
109static ngx_int_t
110 ngx_http_upstream_process_cache_control(ngx_http_request_t *r,
111 ngx_table_elt_t *h, ngx_uint_t offset);
112static ngx_int_t ngx_http_upstream_ignore_header_line(ngx_http_request_t *r,
113 ngx_table_elt_t *h, ngx_uint_t offset);
114static ngx_int_t ngx_http_upstream_process_expires(ngx_http_request_t *r,
115 ngx_table_elt_t *h, ngx_uint_t offset);
116static ngx_int_t ngx_http_upstream_process_accel_expires(ngx_http_request_t *r,
117 ngx_table_elt_t *h, ngx_uint_t offset);
118static ngx_int_t ngx_http_upstream_process_limit_rate(ngx_http_request_t *r,
119 ngx_table_elt_t *h, ngx_uint_t offset);
120static ngx_int_t ngx_http_upstream_process_buffering(ngx_http_request_t *r,
121 ngx_table_elt_t *h, ngx_uint_t offset);
122static ngx_int_t ngx_http_upstream_process_charset(ngx_http_request_t *r,
123 ngx_table_elt_t *h, ngx_uint_t offset);
124static ngx_int_t ngx_http_upstream_process_connection(ngx_http_request_t *r,
125 ngx_table_elt_t *h, ngx_uint_t offset);
126static ngx_int_t
127 ngx_http_upstream_process_transfer_encoding(ngx_http_request_t *r,
128 ngx_table_elt_t *h, ngx_uint_t offset);
129static ngx_int_t ngx_http_upstream_process_vary(ngx_http_request_t *r,
130 ngx_table_elt_t *h, ngx_uint_t offset);
131static ngx_int_t ngx_http_upstream_copy_header_line(ngx_http_request_t *r,
132 ngx_table_elt_t *h, ngx_uint_t offset);
133static ngx_int_t
134 ngx_http_upstream_copy_multi_header_lines(ngx_http_request_t *r,
135 ngx_table_elt_t *h, ngx_uint_t offset);
136static ngx_int_t ngx_http_upstream_copy_content_type(ngx_http_request_t *r,
137 ngx_table_elt_t *h, ngx_uint_t offset);
138static ngx_int_t ngx_http_upstream_copy_last_modified(ngx_http_request_t *r,
139 ngx_table_elt_t *h, ngx_uint_t offset);
140static ngx_int_t ngx_http_upstream_rewrite_location(ngx_http_request_t *r,
141 ngx_table_elt_t *h, ngx_uint_t offset);
142static ngx_int_t ngx_http_upstream_rewrite_refresh(ngx_http_request_t *r,
143 ngx_table_elt_t *h, ngx_uint_t offset);
144static ngx_int_t ngx_http_upstream_rewrite_set_cookie(ngx_http_request_t *r,
145 ngx_table_elt_t *h, ngx_uint_t offset);
146static ngx_int_t ngx_http_upstream_copy_allow_ranges(ngx_http_request_t *r,
147 ngx_table_elt_t *h, ngx_uint_t offset);
148
149#if (NGX_HTTP_GZIP1)
150static ngx_int_t ngx_http_upstream_copy_content_encoding(ngx_http_request_t *r,
151 ngx_table_elt_t *h, ngx_uint_t offset);
152#endif
153
154static ngx_int_t ngx_http_upstream_add_variables(ngx_conf_t *cf);
155static ngx_int_t ngx_http_upstream_addr_variable(ngx_http_request_t *r,
156 ngx_http_variable_value_t *v, uintptr_t data);
157static ngx_int_t ngx_http_upstream_status_variable(ngx_http_request_t *r,
158 ngx_http_variable_value_t *v, uintptr_t data);
159static ngx_int_t ngx_http_upstream_response_time_variable(ngx_http_request_t *r,
160 ngx_http_variable_value_t *v, uintptr_t data);
161static ngx_int_t ngx_http_upstream_response_length_variable(
162 ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data);
163
164static char *ngx_http_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy);
165static char *ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd,
166 void *conf);
167
168static ngx_int_t ngx_http_upstream_set_local(ngx_http_request_t *r,
169 ngx_http_upstream_t *u, ngx_http_upstream_local_t *local);
170
171static void *ngx_http_upstream_create_main_conf(ngx_conf_t *cf);
172static char *ngx_http_upstream_init_main_conf(ngx_conf_t *cf, void *conf);
173
174#if (NGX_HTTP_SSL)
175static void ngx_http_upstream_ssl_init_connection(ngx_http_request_t *,
176 ngx_http_upstream_t *u, ngx_connection_t *c);
177static void ngx_http_upstream_ssl_handshake(ngx_connection_t *c);
178static ngx_int_t ngx_http_upstream_ssl_name(ngx_http_request_t *r,
179 ngx_http_upstream_t *u, ngx_connection_t *c);
180#endif
181
182
183ngx_http_upstream_header_t ngx_http_upstream_headers_in[] = {
184
185 { ngx_string("Status"){ sizeof("Status") - 1, (u_char *) "Status" },
186 ngx_http_upstream_process_header_line,
187 offsetof(ngx_http_upstream_headers_in_t, status)__builtin_offsetof(ngx_http_upstream_headers_in_t, status),
188 ngx_http_upstream_copy_header_line, 0, 0 },
189
190 { ngx_string("Content-Type"){ sizeof("Content-Type") - 1, (u_char *) "Content-Type" },
191 ngx_http_upstream_process_header_line,
192 offsetof(ngx_http_upstream_headers_in_t, content_type)__builtin_offsetof(ngx_http_upstream_headers_in_t, content_type
)
,
193 ngx_http_upstream_copy_content_type, 0, 1 },
194
195 { ngx_string("Content-Length"){ sizeof("Content-Length") - 1, (u_char *) "Content-Length" },
196 ngx_http_upstream_process_content_length, 0,
197 ngx_http_upstream_ignore_header_line, 0, 0 },
198
199 { ngx_string("Date"){ sizeof("Date") - 1, (u_char *) "Date" },
200 ngx_http_upstream_process_header_line,
201 offsetof(ngx_http_upstream_headers_in_t, date)__builtin_offsetof(ngx_http_upstream_headers_in_t, date),
202 ngx_http_upstream_copy_header_line,
203 offsetof(ngx_http_headers_out_t, date)__builtin_offsetof(ngx_http_headers_out_t, date), 0 },
204
205 { ngx_string("Last-Modified"){ sizeof("Last-Modified") - 1, (u_char *) "Last-Modified" },
206 ngx_http_upstream_process_last_modified, 0,
207 ngx_http_upstream_copy_last_modified, 0, 0 },
208
209 { ngx_string("ETag"){ sizeof("ETag") - 1, (u_char *) "ETag" },
210 ngx_http_upstream_process_header_line,
211 offsetof(ngx_http_upstream_headers_in_t, etag)__builtin_offsetof(ngx_http_upstream_headers_in_t, etag),
212 ngx_http_upstream_copy_header_line,
213 offsetof(ngx_http_headers_out_t, etag)__builtin_offsetof(ngx_http_headers_out_t, etag), 0 },
214
215 { ngx_string("Server"){ sizeof("Server") - 1, (u_char *) "Server" },
216 ngx_http_upstream_process_header_line,
217 offsetof(ngx_http_upstream_headers_in_t, server)__builtin_offsetof(ngx_http_upstream_headers_in_t, server),
218 ngx_http_upstream_copy_header_line,
219 offsetof(ngx_http_headers_out_t, server)__builtin_offsetof(ngx_http_headers_out_t, server), 0 },
220
221 { ngx_string("WWW-Authenticate"){ sizeof("WWW-Authenticate") - 1, (u_char *) "WWW-Authenticate"
}
,
222 ngx_http_upstream_process_header_line,
223 offsetof(ngx_http_upstream_headers_in_t, www_authenticate)__builtin_offsetof(ngx_http_upstream_headers_in_t, www_authenticate
)
,
224 ngx_http_upstream_copy_header_line, 0, 0 },
225
226 { ngx_string("Location"){ sizeof("Location") - 1, (u_char *) "Location" },
227 ngx_http_upstream_process_header_line,
228 offsetof(ngx_http_upstream_headers_in_t, location)__builtin_offsetof(ngx_http_upstream_headers_in_t, location),
229 ngx_http_upstream_rewrite_location, 0, 0 },
230
231 { ngx_string("Refresh"){ sizeof("Refresh") - 1, (u_char *) "Refresh" },
232 ngx_http_upstream_ignore_header_line, 0,
233 ngx_http_upstream_rewrite_refresh, 0, 0 },
234
235 { ngx_string("Set-Cookie"){ sizeof("Set-Cookie") - 1, (u_char *) "Set-Cookie" },
236 ngx_http_upstream_process_set_cookie,
237 offsetof(ngx_http_upstream_headers_in_t, cookies)__builtin_offsetof(ngx_http_upstream_headers_in_t, cookies),
238 ngx_http_upstream_rewrite_set_cookie, 0, 1 },
239
240 { ngx_string("Content-Disposition"){ sizeof("Content-Disposition") - 1, (u_char *) "Content-Disposition"
}
,
241 ngx_http_upstream_ignore_header_line, 0,
242 ngx_http_upstream_copy_header_line, 0, 1 },
243
244 { ngx_string("Cache-Control"){ sizeof("Cache-Control") - 1, (u_char *) "Cache-Control" },
245 ngx_http_upstream_process_cache_control, 0,
246 ngx_http_upstream_copy_multi_header_lines,
247 offsetof(ngx_http_headers_out_t, cache_control)__builtin_offsetof(ngx_http_headers_out_t, cache_control), 1 },
248
249 { ngx_string("Expires"){ sizeof("Expires") - 1, (u_char *) "Expires" },
250 ngx_http_upstream_process_expires, 0,
251 ngx_http_upstream_copy_header_line,
252 offsetof(ngx_http_headers_out_t, expires)__builtin_offsetof(ngx_http_headers_out_t, expires), 1 },
253
254 { ngx_string("Accept-Ranges"){ sizeof("Accept-Ranges") - 1, (u_char *) "Accept-Ranges" },
255 ngx_http_upstream_process_header_line,
256 offsetof(ngx_http_upstream_headers_in_t, accept_ranges)__builtin_offsetof(ngx_http_upstream_headers_in_t, accept_ranges
)
,
257 ngx_http_upstream_copy_allow_ranges,
258 offsetof(ngx_http_headers_out_t, accept_ranges)__builtin_offsetof(ngx_http_headers_out_t, accept_ranges), 1 },
259
260 { ngx_string("Content-Range"){ sizeof("Content-Range") - 1, (u_char *) "Content-Range" },
261 ngx_http_upstream_ignore_header_line, 0,
262 ngx_http_upstream_copy_header_line,
263 offsetof(ngx_http_headers_out_t, content_range)__builtin_offsetof(ngx_http_headers_out_t, content_range), 0 },
264
265 { ngx_string("Connection"){ sizeof("Connection") - 1, (u_char *) "Connection" },
266 ngx_http_upstream_process_connection, 0,
267 ngx_http_upstream_ignore_header_line, 0, 0 },
268
269 { ngx_string("Keep-Alive"){ sizeof("Keep-Alive") - 1, (u_char *) "Keep-Alive" },
270 ngx_http_upstream_ignore_header_line, 0,
271 ngx_http_upstream_ignore_header_line, 0, 0 },
272
273 { ngx_string("Vary"){ sizeof("Vary") - 1, (u_char *) "Vary" },
274 ngx_http_upstream_process_vary, 0,
275 ngx_http_upstream_copy_header_line, 0, 0 },
276
277 { ngx_string("X-Powered-By"){ sizeof("X-Powered-By") - 1, (u_char *) "X-Powered-By" },
278 ngx_http_upstream_ignore_header_line, 0,
279 ngx_http_upstream_copy_header_line, 0, 0 },
280
281 { ngx_string("X-Accel-Expires"){ sizeof("X-Accel-Expires") - 1, (u_char *) "X-Accel-Expires"
}
,
282 ngx_http_upstream_process_accel_expires, 0,
283 ngx_http_upstream_copy_header_line, 0, 0 },
284
285 { ngx_string("X-Accel-Redirect"){ sizeof("X-Accel-Redirect") - 1, (u_char *) "X-Accel-Redirect"
}
,
286 ngx_http_upstream_process_header_line,
287 offsetof(ngx_http_upstream_headers_in_t, x_accel_redirect)__builtin_offsetof(ngx_http_upstream_headers_in_t, x_accel_redirect
)
,
288 ngx_http_upstream_copy_header_line, 0, 0 },
289
290 { ngx_string("X-Accel-Limit-Rate"){ sizeof("X-Accel-Limit-Rate") - 1, (u_char *) "X-Accel-Limit-Rate"
}
,
291 ngx_http_upstream_process_limit_rate, 0,
292 ngx_http_upstream_copy_header_line, 0, 0 },
293
294 { ngx_string("X-Accel-Buffering"){ sizeof("X-Accel-Buffering") - 1, (u_char *) "X-Accel-Buffering"
}
,
295 ngx_http_upstream_process_buffering, 0,
296 ngx_http_upstream_copy_header_line, 0, 0 },
297
298 { ngx_string("X-Accel-Charset"){ sizeof("X-Accel-Charset") - 1, (u_char *) "X-Accel-Charset"
}
,
299 ngx_http_upstream_process_charset, 0,
300 ngx_http_upstream_copy_header_line, 0, 0 },
301
302 { ngx_string("Transfer-Encoding"){ sizeof("Transfer-Encoding") - 1, (u_char *) "Transfer-Encoding"
}
,
303 ngx_http_upstream_process_transfer_encoding, 0,
304 ngx_http_upstream_ignore_header_line, 0, 0 },
305
306#if (NGX_HTTP_GZIP1)
307 { ngx_string("Content-Encoding"){ sizeof("Content-Encoding") - 1, (u_char *) "Content-Encoding"
}
,
308 ngx_http_upstream_process_header_line,
309 offsetof(ngx_http_upstream_headers_in_t, content_encoding)__builtin_offsetof(ngx_http_upstream_headers_in_t, content_encoding
)
,
310 ngx_http_upstream_copy_content_encoding, 0, 0 },
311#endif
312
313 { ngx_null_string{ 0, ((void*)0) }, NULL((void*)0), 0, NULL((void*)0), 0, 0 }
314};
315
316
317static ngx_command_t ngx_http_upstream_commands[] = {
318
319 { ngx_string("upstream"){ sizeof("upstream") - 1, (u_char *) "upstream" },
320 NGX_HTTP_MAIN_CONF0x02000000|NGX_CONF_BLOCK0x00000100|NGX_CONF_TAKE10x00000002,
321 ngx_http_upstream,
322 0,
323 0,
324 NULL((void*)0) },
325
326 { ngx_string("server"){ sizeof("server") - 1, (u_char *) "server" },
327 NGX_HTTP_UPS_CONF0x10000000|NGX_CONF_1MORE0x00000800,
328 ngx_http_upstream_server,
329 NGX_HTTP_SRV_CONF_OFFSET__builtin_offsetof(ngx_http_conf_ctx_t, srv_conf),
330 0,
331 NULL((void*)0) },
332
333 ngx_null_command{ { 0, ((void*)0) }, 0, ((void*)0), 0, 0, ((void*)0) }
334};
335
336
337static ngx_http_module_t ngx_http_upstream_module_ctx = {
338 ngx_http_upstream_add_variables, /* preconfiguration */
339 NULL((void*)0), /* postconfiguration */
340
341 ngx_http_upstream_create_main_conf, /* create main configuration */
342 ngx_http_upstream_init_main_conf, /* init main configuration */
343
344 NULL((void*)0), /* create server configuration */
345 NULL((void*)0), /* merge server configuration */
346
347 NULL((void*)0), /* create location configuration */
348 NULL((void*)0) /* merge location configuration */
349};
350
351
352ngx_module_t ngx_http_upstream_module = {
353 NGX_MODULE_V1(ngx_uint_t) -1, (ngx_uint_t) -1, ((void*)0), 0, 0, 1011001, "8"
"," "4" "," "8" "," "0" "0" "0" "0" "1" "1" "1" "0" "0" "1" "0"
"1" "0" "1" "1" "1" "1" "1" "1" "1" "1" "0" "1" "0" "0" "1" "0"
"1" "0" "0" "0" "1" "1"
,
354 &ngx_http_upstream_module_ctx, /* module context */
355 ngx_http_upstream_commands, /* module directives */
356 NGX_HTTP_MODULE0x50545448, /* module type */
357 NULL((void*)0), /* init master */
358 NULL((void*)0), /* init module */
359 NULL((void*)0), /* init process */
360 NULL((void*)0), /* init thread */
361 NULL((void*)0), /* exit thread */
362 NULL((void*)0), /* exit process */
363 NULL((void*)0), /* exit master */
364 NGX_MODULE_V1_PADDING0, 0, 0, 0, 0, 0, 0, 0
365};
366
367
368static ngx_http_variable_t ngx_http_upstream_vars[] = {
369
370 { ngx_string("upstream_addr"){ sizeof("upstream_addr") - 1, (u_char *) "upstream_addr" }, NULL((void*)0),
371 ngx_http_upstream_addr_variable, 0,
372 NGX_HTTP_VAR_NOCACHEABLE2, 0 },
373
374 { ngx_string("upstream_status"){ sizeof("upstream_status") - 1, (u_char *) "upstream_status"
}
, NULL((void*)0),
375 ngx_http_upstream_status_variable, 0,
376 NGX_HTTP_VAR_NOCACHEABLE2, 0 },
377
378 { ngx_string("upstream_connect_time"){ sizeof("upstream_connect_time") - 1, (u_char *) "upstream_connect_time"
}
, NULL((void*)0),
379 ngx_http_upstream_response_time_variable, 2,
380 NGX_HTTP_VAR_NOCACHEABLE2, 0 },
381
382 { ngx_string("upstream_header_time"){ sizeof("upstream_header_time") - 1, (u_char *) "upstream_header_time"
}
, NULL((void*)0),
383 ngx_http_upstream_response_time_variable, 1,
384 NGX_HTTP_VAR_NOCACHEABLE2, 0 },
385
386 { ngx_string("upstream_response_time"){ sizeof("upstream_response_time") - 1, (u_char *) "upstream_response_time"
}
, NULL((void*)0),
387 ngx_http_upstream_response_time_variable, 0,
388 NGX_HTTP_VAR_NOCACHEABLE2, 0 },
389
390 { ngx_string("upstream_response_length"){ sizeof("upstream_response_length") - 1, (u_char *) "upstream_response_length"
}
, NULL((void*)0),
391 ngx_http_upstream_response_length_variable, 0,
392 NGX_HTTP_VAR_NOCACHEABLE2, 0 },
393
394#if (NGX_HTTP_CACHE1)
395
396 { ngx_string("upstream_cache_status"){ sizeof("upstream_cache_status") - 1, (u_char *) "upstream_cache_status"
}
, NULL((void*)0),
397 ngx_http_upstream_cache_status, 0,
398 NGX_HTTP_VAR_NOCACHEABLE2, 0 },
399
400 { ngx_string("upstream_cache_last_modified"){ sizeof("upstream_cache_last_modified") - 1, (u_char *) "upstream_cache_last_modified"
}
, NULL((void*)0),
401 ngx_http_upstream_cache_last_modified, 0,
402 NGX_HTTP_VAR_NOCACHEABLE2|NGX_HTTP_VAR_NOHASH8, 0 },
403
404 { ngx_string("upstream_cache_etag"){ sizeof("upstream_cache_etag") - 1, (u_char *) "upstream_cache_etag"
}
, NULL((void*)0),
405 ngx_http_upstream_cache_etag, 0,
406 NGX_HTTP_VAR_NOCACHEABLE2|NGX_HTTP_VAR_NOHASH8, 0 },
407
408#endif
409
410 { ngx_null_string{ 0, ((void*)0) }, NULL((void*)0), NULL((void*)0), 0, 0, 0 }
411};
412
413
414static ngx_http_upstream_next_t ngx_http_upstream_next_errors[] = {
415 { 500, NGX_HTTP_UPSTREAM_FT_HTTP_5000x00000010 },
416 { 502, NGX_HTTP_UPSTREAM_FT_HTTP_5020x00000020 },
417 { 503, NGX_HTTP_UPSTREAM_FT_HTTP_5030x00000040 },
418 { 504, NGX_HTTP_UPSTREAM_FT_HTTP_5040x00000080 },
419 { 403, NGX_HTTP_UPSTREAM_FT_HTTP_4030x00000100 },
420 { 404, NGX_HTTP_UPSTREAM_FT_HTTP_4040x00000200 },
421 { 0, 0 }
422};
423
424
425ngx_conf_bitmask_t ngx_http_upstream_cache_method_mask[] = {
426 { ngx_string("GET"){ sizeof("GET") - 1, (u_char *) "GET" }, NGX_HTTP_GET0x0002 },
427 { ngx_string("HEAD"){ sizeof("HEAD") - 1, (u_char *) "HEAD" }, NGX_HTTP_HEAD0x0004 },
428 { ngx_string("POST"){ sizeof("POST") - 1, (u_char *) "POST" }, NGX_HTTP_POST0x0008 },
429 { ngx_null_string{ 0, ((void*)0) }, 0 }
430};
431
432
433ngx_conf_bitmask_t ngx_http_upstream_ignore_headers_masks[] = {
434 { ngx_string("X-Accel-Redirect"){ sizeof("X-Accel-Redirect") - 1, (u_char *) "X-Accel-Redirect"
}
, NGX_HTTP_UPSTREAM_IGN_XA_REDIRECT0x00000002 },
435 { ngx_string("X-Accel-Expires"){ sizeof("X-Accel-Expires") - 1, (u_char *) "X-Accel-Expires"
}
, NGX_HTTP_UPSTREAM_IGN_XA_EXPIRES0x00000004 },
436 { 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 },
437 { ngx_string("X-Accel-Buffering"){ sizeof("X-Accel-Buffering") - 1, (u_char *) "X-Accel-Buffering"
}
, NGX_HTTP_UPSTREAM_IGN_XA_BUFFERING0x00000080 },
438 { ngx_string("X-Accel-Charset"){ sizeof("X-Accel-Charset") - 1, (u_char *) "X-Accel-Charset"
}
, NGX_HTTP_UPSTREAM_IGN_XA_CHARSET0x00000100 },
439 { ngx_string("Expires"){ sizeof("Expires") - 1, (u_char *) "Expires" }, NGX_HTTP_UPSTREAM_IGN_EXPIRES0x00000008 },
440 { ngx_string("Cache-Control"){ sizeof("Cache-Control") - 1, (u_char *) "Cache-Control" }, NGX_HTTP_UPSTREAM_IGN_CACHE_CONTROL0x00000010 },
441 { ngx_string("Set-Cookie"){ sizeof("Set-Cookie") - 1, (u_char *) "Set-Cookie" }, NGX_HTTP_UPSTREAM_IGN_SET_COOKIE0x00000020 },
442 { ngx_string("Vary"){ sizeof("Vary") - 1, (u_char *) "Vary" }, NGX_HTTP_UPSTREAM_IGN_VARY0x00000200 },
443 { ngx_null_string{ 0, ((void*)0) }, 0 }
444};
445
446
447ngx_int_t
448ngx_http_upstream_create(ngx_http_request_t *r)
449{
450 ngx_http_upstream_t *u;
451
452 u = r->upstream;
453
454 if (u && u->cleanup) {
455 r->main->count++;
456 ngx_http_upstream_cleanup(r);
457 }
458
459 u = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_t));
460 if (u == NULL((void*)0)) {
461 return NGX_ERROR-1;
462 }
463
464 r->upstream = u;
465
466 u->peer.log = r->connection->log;
467 u->peer.log_error = NGX_ERROR_ERR;
468
469#if (NGX_HTTP_CACHE1)
470 r->cache = NULL((void*)0);
471#endif
472
473 u->headers_in.content_length_n = -1;
474 u->headers_in.last_modified_time = -1;
475
476 return NGX_OK0;
477}
478
479
480void
481ngx_http_upstream_init(ngx_http_request_t *r)
482{
483 ngx_connection_t *c;
484
485 c = r->connection;
486
487 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
488 "http init upstream, client timer: %d", c->read->timer_set);
489
490#if (NGX_HTTP_V2)
491 if (r->stream) {
492 ngx_http_upstream_init_request(r);
493 return;
494 }
495#endif
496
497 if (c->read->timer_set) {
498 ngx_del_timerngx_event_del_timer(c->read);
499 }
500
501 if (ngx_event_flags & NGX_USE_CLEAR_EVENT0x00000004) {
502
503 if (!c->write->active) {
504 if (ngx_add_eventngx_event_actions.add(c->write, NGX_WRITE_EVENTEPOLLOUT, NGX_CLEAR_EVENTEPOLLET)
505 == NGX_ERROR-1)
506 {
507 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR500);
508 return;
509 }
510 }
511 }
512
513 ngx_http_upstream_init_request(r);
514}
515
516
517static void
518ngx_http_upstream_init_request(ngx_http_request_t *r)
519{
520 ngx_str_t *host;
521 ngx_uint_t i;
522 ngx_resolver_ctx_t *ctx, temp;
523 ngx_http_cleanup_t *cln;
524 ngx_http_upstream_t *u;
525 ngx_http_core_loc_conf_t *clcf;
526 ngx_http_upstream_srv_conf_t *uscf, **uscfp;
527 ngx_http_upstream_main_conf_t *umcf;
528
529 if (r->aio) {
530 return;
531 }
532
533 u = r->upstream;
534
535#if (NGX_HTTP_CACHE1)
536
537 if (u->conf->cache) {
538 ngx_int_t rc;
539
540 rc = ngx_http_upstream_cache(r, u);
541
542 if (rc == NGX_BUSY-3) {
543 r->write_event_handler = ngx_http_upstream_init_request;
544 return;
545 }
546
547 r->write_event_handler = ngx_http_request_empty_handler;
548
549 if (rc == NGX_ERROR-1) {
550 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR500);
551 return;
552 }
553
554 if (rc == NGX_OK0) {
555 rc = ngx_http_upstream_cache_send(r, u);
556
557 if (rc == NGX_DONE-4) {
558 return;
559 }
560
561 if (rc == NGX_HTTP_UPSTREAM_INVALID_HEADER40) {
562 rc = NGX_DECLINED-5;
563 r->cached = 0;
564 }
565 }
566
567 if (rc != NGX_DECLINED-5) {
568 ngx_http_finalize_request(r, rc);
569 return;
570 }
571 }
572
573#endif
574
575 u->store = u->conf->store;
576
577 if (!u->store && !r->post_action && !u->conf->ignore_client_abort) {
578 r->read_event_handler = ngx_http_upstream_rd_check_broken_connection;
579 r->write_event_handler = ngx_http_upstream_wr_check_broken_connection;
580 }
581
582 if (r->request_body) {
583 u->request_bufs = r->request_body->bufs;
584 }
585
586 if (u->create_request(r) != NGX_OK0) {
587 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR500);
588 return;
589 }
590
591 if (ngx_http_upstream_set_local(r, u, u->conf->local) != NGX_OK0) {
592 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR500);
593 return;
594 }
595
596 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module)(r)->loc_conf[ngx_http_core_module.ctx_index];
597
598 u->output.alignment = clcf->directio_alignment;
599 u->output.pool = r->pool;
600 u->output.bufs.num = 1;
601 u->output.bufs.size = clcf->client_body_buffer_size;
602
603 if (u->output.output_filter == NULL((void*)0)) {
604 u->output.output_filter = ngx_chain_writer;
605 u->output.filter_ctx = &u->writer;
606 }
607
608 u->writer.pool = r->pool;
609
610 if (r->upstream_states == NULL((void*)0)) {
611
612 r->upstream_states = ngx_array_create(r->pool, 1,
613 sizeof(ngx_http_upstream_state_t));
614 if (r->upstream_states == NULL((void*)0)) {
615 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR500);
616 return;
617 }
618
619 } else {
620
621 u->state = ngx_array_push(r->upstream_states);
622 if (u->state == NULL((void*)0)) {
623 ngx_http_upstream_finalize_request(r, u,
624 NGX_HTTP_INTERNAL_SERVER_ERROR500);
625 return;
626 }
627
628 ngx_memzero(u->state, sizeof(ngx_http_upstream_state_t))(void) memset(u->state, 0, sizeof(ngx_http_upstream_state_t
))
;
629 }
630
631 cln = ngx_http_cleanup_add(r, 0);
632 if (cln == NULL((void*)0)) {
633 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR500);
634 return;
635 }
636
637 cln->handler = ngx_http_upstream_cleanup;
638 cln->data = r;
639 u->cleanup = &cln->handler;
640
641 if (u->resolved == NULL((void*)0)) {
642
643 uscf = u->conf->upstream;
644
645 } else {
646
647#if (NGX_HTTP_SSL)
648 u->ssl_name = u->resolved->host;
649#endif
650
651 host = &u->resolved->host;
652
653 if (u->resolved->sockaddr) {
654
655 if (u->resolved->port == 0
656 && u->resolved->sockaddr->sa_family != AF_UNIX1)
657 {
658 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)
659 "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)
;
660 ngx_http_upstream_finalize_request(r, u,
661 NGX_HTTP_INTERNAL_SERVER_ERROR500);
662 return;
663 }
664
665 if (ngx_http_upstream_create_round_robin_peer(r, u->resolved)
666 != NGX_OK0)
667 {
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 return;
676 }
677
678 umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module)(r)->main_conf[ngx_http_upstream_module.ctx_index];
679
680 uscfp = umcf->upstreams.elts;
681
682 for (i = 0; i < umcf->upstreams.nelts; i++) {
683
684 uscf = uscfp[i];
685
686 if (uscf->host.len == host->len
687 && ((uscf->port == 0 && u->resolved->no_port)
688 || uscf->port == u->resolved->port)
689 && ngx_strncasecmp(uscf->host.data, host->data, host->len) == 0)
690 {
691 goto found;
692 }
693 }
694
695 if (u->resolved->port == 0) {
696 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)
697 "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)
;
698 ngx_http_upstream_finalize_request(r, u,
699 NGX_HTTP_INTERNAL_SERVER_ERROR500);
700 return;
701 }
702
703 temp.name = *host;
704
705 ctx = ngx_resolve_start(clcf->resolver, &temp);
706 if (ctx == NULL((void*)0)) {
707 ngx_http_upstream_finalize_request(r, u,
708 NGX_HTTP_INTERNAL_SERVER_ERROR500);
709 return;
710 }
711
712 if (ctx == NGX_NO_RESOLVER(void *) -1) {
713 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)
714 "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)
;
715
716 ngx_http_upstream_finalize_request(r, u, NGX_HTTP_BAD_GATEWAY502);
717 return;
718 }
719
720 ctx->name = *host;
721 ctx->handler = ngx_http_upstream_resolve_handler;
722 ctx->data = r;
723 ctx->timeout = clcf->resolver_timeout;
724
725 u->resolved->ctx = ctx;
726
727 if (ngx_resolve_name(ctx) != NGX_OK0) {
728 u->resolved->ctx = NULL((void*)0);
729 ngx_http_upstream_finalize_request(r, u,
730 NGX_HTTP_INTERNAL_SERVER_ERROR500);
731 return;
732 }
733
734 return;
735 }
736
737found:
738
739 if (uscf == NULL((void*)0)) {
740 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")
741 "no upstream configuration")if ((r->connection->log)->log_level >= 2) ngx_log_error_core
(2, r->connection->log, 0, "no upstream configuration")
;
742 ngx_http_upstream_finalize_request(r, u,
743 NGX_HTTP_INTERNAL_SERVER_ERROR500);
744 return;
745 }
746
747#if (NGX_HTTP_SSL)
748 u->ssl_name = uscf->host;
749#endif
750
751 if (uscf->peer.init(r, uscf) != NGX_OK0) {
752 ngx_http_upstream_finalize_request(r, u,
753 NGX_HTTP_INTERNAL_SERVER_ERROR500);
754 return;
755 }
756
757 u->peer.start_time = ngx_current_msec;
758
759 if (u->conf->next_upstream_tries
760 && u->peer.tries > u->conf->next_upstream_tries)
761 {
762 u->peer.tries = u->conf->next_upstream_tries;
763 }
764
765 ngx_http_upstream_connect(r, u);
766}
767
768
769#if (NGX_HTTP_CACHE1)
770
771static ngx_int_t
772ngx_http_upstream_cache(ngx_http_request_t *r, ngx_http_upstream_t *u)
773{
774 ngx_int_t rc;
775 ngx_http_cache_t *c;
776 ngx_http_file_cache_t *cache;
777
778 c = r->cache;
779
780 if (c == NULL((void*)0)) {
781
782 if (!(r->method & u->conf->cache_methods)) {
783 return NGX_DECLINED-5;
784 }
785
786 rc = ngx_http_upstream_cache_get(r, u, &cache);
787
788 if (rc != NGX_OK0) {
789 return rc;
790 }
791
792 if (r->method == NGX_HTTP_HEAD0x0004 && u->conf->cache_convert_head) {
793 u->method = ngx_http_core_get_method;
794 }
795
796 if (ngx_http_file_cache_new(r) != NGX_OK0) {
797 return NGX_ERROR-1;
798 }
799
800 if (u->create_key(r) != NGX_OK0) {
801 return NGX_ERROR-1;
802 }
803
804 /* TODO: add keys */
805
806 ngx_http_file_cache_create_key(r);
807
808 if (r->cache->header_start + 256 >= u->conf->buffer_size) {
809 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 be increased to at least %uz", &u->conf->
module, u->conf->buffer_size, (((r->cache->header_start
+ 256) + (1024 - 1)) & ~(1024 - 1)))
810 "%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 be increased to at least %uz", &u->conf->
module, u->conf->buffer_size, (((r->cache->header_start
+ 256) + (1024 - 1)) & ~(1024 - 1)))
811 "it should be increased to at least %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 be increased to at least %uz", &u->conf->
module, u->conf->buffer_size, (((r->cache->header_start
+ 256) + (1024 - 1)) & ~(1024 - 1)))
812 &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 be increased to at least %uz", &u->conf->
module, u->conf->buffer_size, (((r->cache->header_start
+ 256) + (1024 - 1)) & ~(1024 - 1)))
813 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 be increased to at least %uz", &u->conf->
module, u->conf->buffer_size, (((r->cache->header_start
+ 256) + (1024 - 1)) & ~(1024 - 1)))
;
814
815 r->cache = NULL((void*)0);
816 return NGX_DECLINED-5;
817 }
818
819 u->cacheable = 1;
820
821 c = r->cache;
822
823 c->body_start = u->conf->buffer_size;
824 c->min_uses = u->conf->cache_min_uses;
825 c->file_cache = cache;
826
827 switch (ngx_http_test_predicates(r, u->conf->cache_bypass)) {
828
829 case NGX_ERROR-1:
830 return NGX_ERROR-1;
831
832 case NGX_DECLINED-5:
833 u->cache_status = NGX_HTTP_CACHE_BYPASS2;
834 return NGX_DECLINED-5;
835
836 default: /* NGX_OK */
837 break;
838 }
839
840 c->lock = u->conf->cache_lock;
841 c->lock_timeout = u->conf->cache_lock_timeout;
842 c->lock_age = u->conf->cache_lock_age;
843
844 u->cache_status = NGX_HTTP_CACHE_MISS1;
845 }
846
847 rc = ngx_http_file_cache_open(r);
848
849 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
850 "http upstream cache: %i", rc);
851
852 switch (rc) {
853
854 case NGX_HTTP_CACHE_UPDATING5:
855
856 if (u->conf->cache_use_stale & NGX_HTTP_UPSTREAM_FT_UPDATING0x00000400) {
857 u->cache_status = rc;
858 rc = NGX_OK0;
859
860 } else {
861 rc = NGX_HTTP_CACHE_STALE4;
862 }
863
864 break;
865
866 case NGX_OK0:
867 u->cache_status = NGX_HTTP_CACHE_HIT7;
868 }
869
870 switch (rc) {
871
872 case NGX_OK0:
873
874 return NGX_OK0;
875
876 case NGX_HTTP_CACHE_STALE4:
877
878 c->valid_sec = 0;
879 u->buffer.start = NULL((void*)0);
880 u->cache_status = NGX_HTTP_CACHE_EXPIRED3;
881
882 break;
883
884 case NGX_DECLINED-5:
885
886 if ((size_t) (u->buffer.end - u->buffer.start) < u->conf->buffer_size) {
887 u->buffer.start = NULL((void*)0);
888
889 } else {
890 u->buffer.pos = u->buffer.start + c->header_start;
891 u->buffer.last = u->buffer.pos;
892 }
893
894 break;
895
896 case NGX_HTTP_CACHE_SCARCE8:
897
898 u->cacheable = 0;
899
900 break;
901
902 case NGX_AGAIN-2:
903
904 return NGX_BUSY-3;
905
906 case NGX_ERROR-1:
907
908 return NGX_ERROR-1;
909
910 default:
911
912 /* cached NGX_HTTP_BAD_GATEWAY, NGX_HTTP_GATEWAY_TIME_OUT, etc. */
913
914 u->cache_status = NGX_HTTP_CACHE_HIT7;
915
916 return rc;
917 }
918
919 r->cached = 0;
920
921 return NGX_DECLINED-5;
922}
923
924
925static ngx_int_t
926ngx_http_upstream_cache_get(ngx_http_request_t *r, ngx_http_upstream_t *u,
927 ngx_http_file_cache_t **cache)
928{
929 ngx_str_t *name, val;
930 ngx_uint_t i;
931 ngx_http_file_cache_t **caches;
932
933 if (u->conf->cache_zone) {
934 *cache = u->conf->cache_zone->data;
935 return NGX_OK0;
936 }
937
938 if (ngx_http_complex_value(r, u->conf->cache_value, &val) != NGX_OK0) {
939 return NGX_ERROR-1;
940 }
941
942 if (val.len == 0
943 || (val.len == 3 && ngx_strncmp(val.data, "off", 3)(__extension__ (__builtin_constant_p (3) && ((__builtin_constant_p
((const char *) val.data) && strlen ((const char *) val
.data) < ((size_t) (3))) || (__builtin_constant_p ((const char
*) "off") && strlen ((const char *) "off") < ((size_t
) (3)))) ? __extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
((const char *) val.data) && __builtin_constant_p ((
const char *) "off") && (__s1_len = strlen ((const char
*) val.data), __s2_len = strlen ((const char *) "off"), (!((
size_t)(const void *)(((const char *) val.data) + 1) - (size_t
)(const void *)((const char *) val.data) == 1) || __s1_len >=
4) && (!((size_t)(const void *)(((const char *) "off"
) + 1) - (size_t)(const void *)((const char *) "off") == 1) ||
__s2_len >= 4)) ? __builtin_strcmp ((const char *) val.data
, (const char *) "off") : (__builtin_constant_p ((const char *
) val.data) && ((size_t)(const void *)(((const char *
) val.data) + 1) - (size_t)(const void *)((const char *) val.
data) == 1) && (__s1_len = strlen ((const char *) val
.data), __s1_len < 4) ? (__builtin_constant_p ((const char
*) "off") && ((size_t)(const void *)(((const char *)
"off") + 1) - (size_t)(const void *)((const char *) "off") ==
1) ? __builtin_strcmp ((const char *) val.data, (const char *
) "off") : (__extension__ ({ const unsigned char *__s2 = (const
unsigned char *) (const char *) ((const char *) "off"); int __result
= (((const unsigned char *) (const char *) ((const char *) val
.data))[0] - __s2[0]); if (__s1_len > 0 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
(const char *) val.data))[1] - __s2[1]); if (__s1_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) ((const char *) val.data))[2] - __s2[2]); if (__s1_len
> 2 && __result == 0) __result = (((const unsigned
char *) (const char *) ((const char *) val.data))[3] - __s2[
3]); } } __result; }))) : (__builtin_constant_p ((const char *
) "off") && ((size_t)(const void *)(((const char *) "off"
) + 1) - (size_t)(const void *)((const char *) "off") == 1) &&
(__s2_len = strlen ((const char *) "off"), __s2_len < 4) ?
(__builtin_constant_p ((const char *) val.data) && (
(size_t)(const void *)(((const char *) val.data) + 1) - (size_t
)(const void *)((const char *) val.data) == 1) ? __builtin_strcmp
((const char *) val.data, (const char *) "off") : (- (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) ((const char *) val.data); int __result = (((const unsigned
char *) (const char *) ((const char *) "off"))[0] - __s2[0])
; if (__s2_len > 0 && __result == 0) { __result = (
((const unsigned char *) (const char *) ((const char *) "off"
))[1] - __s2[1]); if (__s2_len > 1 && __result == 0
) { __result = (((const unsigned char *) (const char *) ((const
char *) "off"))[2] - __s2[2]); if (__s2_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) ((const char *) "off"))[3] - __s2[3]); } } __result; })))
) : __builtin_strcmp ((const char *) val.data, (const char *)
"off")))); }) : strncmp ((const char *) val.data, (const char
*) "off", 3)))
== 0))
944 {
945 return NGX_DECLINED-5;
946 }
947
948 caches = u->caches->elts;
949
950 for (i = 0; i < u->caches->nelts; i++) {
951 name = &caches[i]->shm_zone->shm.name;
952
953 if (name->len == val.len
954 && ngx_strncmp(name->data, val.data, val.len)(__extension__ (__builtin_constant_p (val.len) && ((__builtin_constant_p
((const char *) name->data) && strlen ((const char
*) name->data) < ((size_t) (val.len))) || (__builtin_constant_p
((const char *) val.data) && strlen ((const char *) val
.data) < ((size_t) (val.len)))) ? __extension__ ({ size_t __s1_len
, __s2_len; (__builtin_constant_p ((const char *) name->data
) && __builtin_constant_p ((const char *) val.data) &&
(__s1_len = strlen ((const char *) name->data), __s2_len =
strlen ((const char *) val.data), (!((size_t)(const void *)(
((const char *) name->data) + 1) - (size_t)(const void *)(
(const char *) name->data) == 1) || __s1_len >= 4) &&
(!((size_t)(const void *)(((const char *) val.data) + 1) - (
size_t)(const void *)((const char *) val.data) == 1) || __s2_len
>= 4)) ? __builtin_strcmp ((const char *) name->data, (
const char *) val.data) : (__builtin_constant_p ((const char *
) name->data) && ((size_t)(const void *)(((const char
*) name->data) + 1) - (size_t)(const void *)((const char *
) name->data) == 1) && (__s1_len = strlen ((const char
*) name->data), __s1_len < 4) ? (__builtin_constant_p (
(const char *) val.data) && ((size_t)(const void *)((
(const char *) val.data) + 1) - (size_t)(const void *)((const
char *) val.data) == 1) ? __builtin_strcmp ((const char *) name
->data, (const char *) val.data) : (__extension__ ({ const
unsigned char *__s2 = (const unsigned char *) (const char *)
((const char *) val.data); int __result = (((const unsigned char
*) (const char *) ((const char *) name->data))[0] - __s2[
0]); if (__s1_len > 0 && __result == 0) { __result
= (((const unsigned char *) (const char *) ((const char *) name
->data))[1] - __s2[1]); if (__s1_len > 1 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
(const char *) name->data))[2] - __s2[2]); if (__s1_len >
2 && __result == 0) __result = (((const unsigned char
*) (const char *) ((const char *) name->data))[3] - __s2[
3]); } } __result; }))) : (__builtin_constant_p ((const char *
) val.data) && ((size_t)(const void *)(((const char *
) val.data) + 1) - (size_t)(const void *)((const char *) val.
data) == 1) && (__s2_len = strlen ((const char *) val
.data), __s2_len < 4) ? (__builtin_constant_p ((const char
*) name->data) && ((size_t)(const void *)(((const
char *) name->data) + 1) - (size_t)(const void *)((const char
*) name->data) == 1) ? __builtin_strcmp ((const char *) name
->data, (const char *) val.data) : (- (__extension__ ({ const
unsigned char *__s2 = (const unsigned char *) (const char *)
((const char *) name->data); int __result = (((const unsigned
char *) (const char *) ((const char *) val.data))[0] - __s2[
0]); if (__s2_len > 0 && __result == 0) { __result
= (((const unsigned char *) (const char *) ((const char *) val
.data))[1] - __s2[1]); if (__s2_len > 1 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
(const char *) val.data))[2] - __s2[2]); if (__s2_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) ((const char *) val.data))[3] - __s2[3]); } } __result; }
)))) : __builtin_strcmp ((const char *) name->data, (const
char *) val.data)))); }) : strncmp ((const char *) name->
data, (const char *) val.data, val.len)))
== 0)
955 {
956 *cache = caches[i];
957 return NGX_OK0;
958 }
959 }
960
961 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, "cache \"%V\" not found", &
val)
962 "cache \"%V\" not found", &val)if ((r->connection->log)->log_level >= 4) ngx_log_error_core
(4, r->connection->log, 0, "cache \"%V\" not found", &
val)
;
963
964 return NGX_ERROR-1;
965}
966
967
968static ngx_int_t
969ngx_http_upstream_cache_send(ngx_http_request_t *r, ngx_http_upstream_t *u)
970{
971 ngx_int_t rc;
972 ngx_http_cache_t *c;
973
974 r->cached = 1;
975 c = r->cache;
976
977 if (c->header_start == c->body_start) {
978 r->http_version = NGX_HTTP_VERSION_99;
979 return ngx_http_cache_send(r);
980 }
981
982 /* TODO: cache stack */
983
984 u->buffer = *c->buf;
985 u->buffer.pos += c->header_start;
986
987 ngx_memzero(&u->headers_in, sizeof(ngx_http_upstream_headers_in_t))(void) memset(&u->headers_in, 0, sizeof(ngx_http_upstream_headers_in_t
))
;
988 u->headers_in.content_length_n = -1;
989 u->headers_in.last_modified_time = -1;
990
991 if (ngx_list_init(&u->headers_in.headers, r->pool, 8,
992 sizeof(ngx_table_elt_t))
993 != NGX_OK0)
994 {
995 return NGX_ERROR-1;
996 }
997
998 rc = u->process_header(r);
999
1000 if (rc == NGX_OK0) {
1001
1002 if (ngx_http_upstream_process_headers(r, u) != NGX_OK0) {
1003 return NGX_DONE-4;
1004 }
1005
1006 return ngx_http_cache_send(r);
1007 }
1008
1009 if (rc == NGX_ERROR-1) {
1010 return NGX_ERROR-1;
1011 }
1012
1013 /* rc == NGX_HTTP_UPSTREAM_INVALID_HEADER */
1014
1015 /* TODO: delete file */
1016
1017 return rc;
1018}
1019
1020#endif
1021
1022
1023static void
1024ngx_http_upstream_resolve_handler(ngx_resolver_ctx_t *ctx)
1025{
1026 ngx_connection_t *c;
1027 ngx_http_request_t *r;
1028 ngx_http_upstream_t *u;
1029 ngx_http_upstream_resolved_t *ur;
1030
1031 r = ctx->data;
1032 c = r->connection;
1033
1034 u = r->upstream;
1035 ur = u->resolved;
1036
1037 ngx_http_set_log_request(c->log, r)((ngx_http_log_ctx_t *) c->log->data)->current_request
= r
;
1038
1039 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
1040 "http upstream resolve: \"%V?%V\"", &r->uri, &r->args);
1041
1042 if (ctx->state) {
1043 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))
1044 "%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))
1045 &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))
1046 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))
;
1047
1048 ngx_http_upstream_finalize_request(r, u, NGX_HTTP_BAD_GATEWAY502);
1049 goto failed;
1050 }
1051
1052 ur->naddrs = ctx->naddrs;
1053 ur->addrs = ctx->addrs;
1054
1055#if (NGX_DEBUG)
1056 {
1057 u_char text[NGX_SOCKADDR_STRLEN(sizeof("unix:") - 1 + (sizeof(struct sockaddr_un) - __builtin_offsetof
(struct sockaddr_un, sun_path)))
];
1058 ngx_str_t addr;
1059 ngx_uint_t i;
1060
1061 addr.data = text;
1062
1063 for (i = 0; i < ctx->naddrs; i++) {
1064 addr.len = ngx_sock_ntop(ur->addrs[i].sockaddr, ur->addrs[i].socklen,
1065 text, NGX_SOCKADDR_STRLEN(sizeof("unix:") - 1 + (sizeof(struct sockaddr_un) - __builtin_offsetof
(struct sockaddr_un, sun_path)))
, 0);
1066
1067 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1068 "name was resolved to %V", &addr);
1069 }
1070 }
1071#endif
1072
1073 if (ngx_http_upstream_create_round_robin_peer(r, ur) != NGX_OK0) {
1074 ngx_http_upstream_finalize_request(r, u,
1075 NGX_HTTP_INTERNAL_SERVER_ERROR500);
1076 goto failed;
1077 }
1078
1079 ngx_resolve_name_done(ctx);
1080 ur->ctx = NULL((void*)0);
1081
1082 u->peer.start_time = ngx_current_msec;
1083
1084 if (u->conf->next_upstream_tries
1085 && u->peer.tries > u->conf->next_upstream_tries)
1086 {
1087 u->peer.tries = u->conf->next_upstream_tries;
1088 }
1089
1090 ngx_http_upstream_connect(r, u);
1091
1092failed:
1093
1094 ngx_http_run_posted_requests(c);
1095}
1096
1097
1098static void
1099ngx_http_upstream_handler(ngx_event_t *ev)
1100{
1101 ngx_connection_t *c;
1102 ngx_http_request_t *r;
1103 ngx_http_upstream_t *u;
1104
1105 c = ev->data;
1106 r = c->data;
1107
1108 u = r->upstream;
1109 c = r->connection;
1110
1111 ngx_http_set_log_request(c->log, r)((ngx_http_log_ctx_t *) c->log->data)->current_request
= r
;
1112
1113 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
1114 "http upstream request: \"%V?%V\"", &r->uri, &r->args);
1115
1116 if (ev->write) {
1117 u->write_event_handler(r, u);
1118
1119 } else {
1120 u->read_event_handler(r, u);
1121 }
1122
1123 ngx_http_run_posted_requests(c);
1124}
1125
1126
1127static void
1128ngx_http_upstream_rd_check_broken_connection(ngx_http_request_t *r)
1129{
1130 ngx_http_upstream_check_broken_connection(r, r->connection->read);
1131}
1132
1133
1134static void
1135ngx_http_upstream_wr_check_broken_connection(ngx_http_request_t *r)
1136{
1137 ngx_http_upstream_check_broken_connection(r, r->connection->write);
1138}
1139
1140
1141static void
1142ngx_http_upstream_check_broken_connection(ngx_http_request_t *r,
1143 ngx_event_t *ev)
1144{
1145 int n;
1146 char buf[1];
1147 ngx_err_t err;
1148 ngx_int_t event;
1149 ngx_connection_t *c;
1150 ngx_http_upstream_t *u;
1151
1152 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, ev->log, 0,
1153 "http upstream check client, write event:%d, \"%V\"",
1154 ev->write, &r->uri);
1155
1156 c = r->connection;
1157 u = r->upstream;
1158
1159 if (c->error) {
1160 if ((ngx_event_flags & NGX_USE_LEVEL_EVENT0x00000001) && ev->active) {
1161
1162 event = ev->write ? NGX_WRITE_EVENTEPOLLOUT : NGX_READ_EVENT(EPOLLIN|EPOLLRDHUP);
1163
1164 if (ngx_del_eventngx_event_actions.del(ev, event, 0) != NGX_OK0) {
1165 ngx_http_upstream_finalize_request(r, u,
1166 NGX_HTTP_INTERNAL_SERVER_ERROR500);
1167 return;
1168 }
1169 }
1170
1171 if (!u->cacheable) {
1172 ngx_http_upstream_finalize_request(r, u,
1173 NGX_HTTP_CLIENT_CLOSED_REQUEST499);
1174 }
1175
1176 return;
1177 }
1178
1179#if (NGX_HTTP_V2)
1180 if (r->stream) {
1181 return;
1182 }
1183#endif
1184
1185#if (NGX_HAVE_KQUEUE)
1186
1187 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT0x00000008) {
1188
1189 if (!ev->pending_eof) {
1190 return;
1191 }
1192
1193 ev->eof = 1;
1194 c->error = 1;
1195
1196 if (ev->kq_errno) {
1197 ev->error = 1;
1198 }
1199
1200 if (!u->cacheable && u->peer.connection) {
1201 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")
1202 "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")
1203 "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")
;
1204 ngx_http_upstream_finalize_request(r, u,
1205 NGX_HTTP_CLIENT_CLOSED_REQUEST499);
1206 return;
1207 }
1208
1209 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")
1210 "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")
1211 "connection")if ((ev->log)->log_level >= 7) ngx_log_error_core(7,
ev->log, ev->kq_errno, "kevent() reported that client prematurely closed "
"connection")
;
1212
1213 if (u->peer.connection == NULL((void*)0)) {
1214 ngx_http_upstream_finalize_request(r, u,
1215 NGX_HTTP_CLIENT_CLOSED_REQUEST499);
1216 }
1217
1218 return;
1219 }
1220
1221#endif
1222
1223#if (NGX_HAVE_EPOLLRDHUP1)
1224
1225 if ((ngx_event_flags & NGX_USE_EPOLL_EVENT0x00000040) && ngx_use_epoll_rdhup) {
1226 socklen_t len;
1227
1228 if (!ev->pending_eof) {
1229 return;
1230 }
1231
1232 ev->eof = 1;
1233 c->error = 1;
1234
1235 err = 0;
1236 len = sizeof(ngx_err_t);
1237
1238 /*
1239 * BSDs and Linux return 0 and set a pending error in err
1240 * Solaris returns -1 and sets errno
1241 */
1242
1243 if (getsockopt(c->fd, SOL_SOCKET1, SO_ERROR4, (void *) &err, &len)
1244 == -1)
1245 {
1246 err = ngx_socket_errno(*__errno_location ());
1247 }
1248
1249 if (err) {
1250 ev->error = 1;
1251 }
1252
1253 if (!u->cacheable && u->peer.connection) {
1254 ngx_log_error(NGX_LOG_INFO, ev->log, err,if ((ev->log)->log_level >= 7) ngx_log_error_core(7,
ev->log, err, "epoll_wait() reported that client prematurely closed "
"connection, so upstream connection is closed too")
1255 "epoll_wait() reported that client prematurely closed "if ((ev->log)->log_level >= 7) ngx_log_error_core(7,
ev->log, err, "epoll_wait() reported that client prematurely closed "
"connection, so upstream connection is closed too")
1256 "connection, so upstream connection is closed too")if ((ev->log)->log_level >= 7) ngx_log_error_core(7,
ev->log, err, "epoll_wait() reported that client prematurely closed "
"connection, so upstream connection is closed too")
;
1257 ngx_http_upstream_finalize_request(r, u,
1258 NGX_HTTP_CLIENT_CLOSED_REQUEST499);
1259 return;
1260 }
1261
1262 ngx_log_error(NGX_LOG_INFO, ev->log, err,if ((ev->log)->log_level >= 7) ngx_log_error_core(7,
ev->log, err, "epoll_wait() reported that client prematurely closed "
"connection")
1263 "epoll_wait() reported that client prematurely closed "if ((ev->log)->log_level >= 7) ngx_log_error_core(7,
ev->log, err, "epoll_wait() reported that client prematurely closed "
"connection")
1264 "connection")if ((ev->log)->log_level >= 7) ngx_log_error_core(7,
ev->log, err, "epoll_wait() reported that client prematurely closed "
"connection")
;
1265
1266 if (u->peer.connection == NULL((void*)0)) {
1267 ngx_http_upstream_finalize_request(r, u,
1268 NGX_HTTP_CLIENT_CLOSED_REQUEST499);
1269 }
1270
1271 return;
1272 }
1273
1274#endif
1275
1276 n = recv(c->fd, buf, 1, MSG_PEEKMSG_PEEK);
1277
1278 err = ngx_socket_errno(*__errno_location ());
1279
1280 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ev->log, err,
1281 "http upstream recv(): %d", n);
1282
1283 if (ev->write && (n >= 0 || err == NGX_EAGAIN11)) {
1284 return;
1285 }
1286
1287 if ((ngx_event_flags & NGX_USE_LEVEL_EVENT0x00000001) && ev->active) {
1288
1289 event = ev->write ? NGX_WRITE_EVENTEPOLLOUT : NGX_READ_EVENT(EPOLLIN|EPOLLRDHUP);
1290
1291 if (ngx_del_eventngx_event_actions.del(ev, event, 0) != NGX_OK0) {
1292 ngx_http_upstream_finalize_request(r, u,
1293 NGX_HTTP_INTERNAL_SERVER_ERROR500);
1294 return;
1295 }
1296 }
1297
1298 if (n > 0) {
1299 return;
1300 }
1301
1302 if (n == -1) {
1303 if (err == NGX_EAGAIN11) {
1304 return;
1305 }
1306
1307 ev->error = 1;
1308
1309 } else { /* n == 0 */
1310 err = 0;
1311 }
1312
1313 ev->eof = 1;
1314 c->error = 1;
1315
1316 if (!u->cacheable && u->peer.connection) {
1317 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"
)
1318 "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"
)
1319 "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"
)
;
1320 ngx_http_upstream_finalize_request(r, u,
1321 NGX_HTTP_CLIENT_CLOSED_REQUEST499);
1322 return;
1323 }
1324
1325 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")
1326 "client prematurely closed connection")if ((ev->log)->log_level >= 7) ngx_log_error_core(7,
ev->log, err, "client prematurely closed connection")
;
1327
1328 if (u->peer.connection == NULL((void*)0)) {
1329 ngx_http_upstream_finalize_request(r, u,
1330 NGX_HTTP_CLIENT_CLOSED_REQUEST499);
1331 }
1332}
1333
1334
1335static void
1336ngx_http_upstream_connect(ngx_http_request_t *r, ngx_http_upstream_t *u)
1337{
1338 ngx_int_t rc;
1339 ngx_connection_t *c;
1340
1341 r->connection->log->action = "connecting to upstream";
1342
1343 if (u->state && u->state->response_time) {
1344 u->state->response_time = ngx_current_msec - u->state->response_time;
1345 }
1346
1347 u->state = ngx_array_push(r->upstream_states);
1348 if (u->state == NULL((void*)0)) {
1349 ngx_http_upstream_finalize_request(r, u,
1350 NGX_HTTP_INTERNAL_SERVER_ERROR500);
1351 return;
1352 }
1353
1354 ngx_memzero(u->state, sizeof(ngx_http_upstream_state_t))(void) memset(u->state, 0, sizeof(ngx_http_upstream_state_t
))
;
1355
1356 u->state->response_time = ngx_current_msec;
1357 u->state->connect_time = (ngx_msec_t) -1;
1358 u->state->header_time = (ngx_msec_t) -1;
1359
1360 rc = ngx_event_connect_peer(&u->peer);
1361
1362 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1363 "http upstream connect: %i", rc);
1364
1365 if (rc == NGX_ERROR-1) {
1366 ngx_http_upstream_finalize_request(r, u,
1367 NGX_HTTP_INTERNAL_SERVER_ERROR500);
1368 return;
1369 }
1370
1371 u->state->peer = u->peer.name;
1372
1373 if (rc == NGX_BUSY-3) {
1374 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")
;
1375 ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_NOLIVE0x40000000);
1376 return;
1377 }
1378
1379 if (rc == NGX_DECLINED-5) {
1380 ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR0x00000002);
1381 return;
1382 }
1383
1384 /* rc == NGX_OK || rc == NGX_AGAIN || rc == NGX_DONE */
1385
1386 c = u->peer.connection;
1387
1388 c->data = r;
1389
1390 c->write->handler = ngx_http_upstream_handler;
1391 c->read->handler = ngx_http_upstream_handler;
1392
1393 u->write_event_handler = ngx_http_upstream_send_request_handler;
1394 u->read_event_handler = ngx_http_upstream_process_header;
1395
1396 c->sendfile &= r->connection->sendfile;
1397 u->output.sendfile = c->sendfile;
1398
1399 if (c->pool == NULL((void*)0)) {
1400
1401 /* we need separate pool here to be able to cache SSL connections */
1402
1403 c->pool = ngx_create_pool(128, r->connection->log);
1404 if (c->pool == NULL((void*)0)) {
1405 ngx_http_upstream_finalize_request(r, u,
1406 NGX_HTTP_INTERNAL_SERVER_ERROR500);
1407 return;
1408 }
1409 }
1410
1411 c->log = r->connection->log;
1412 c->pool->log = c->log;
1413 c->read->log = c->log;
1414 c->write->log = c->log;
1415
1416 /* init or reinit the ngx_output_chain() and ngx_chain_writer() contexts */
1417
1418 u->writer.out = NULL((void*)0);
1419 u->writer.last = &u->writer.out;
1420 u->writer.connection = c;
1421 u->writer.limit = 0;
1422
1423 if (u->request_sent) {
1424 if (ngx_http_upstream_reinit(r, u) != NGX_OK0) {
1425 ngx_http_upstream_finalize_request(r, u,
1426 NGX_HTTP_INTERNAL_SERVER_ERROR500);
1427 return;
1428 }
1429 }
1430
1431 if (r->request_body
1432 && r->request_body->buf
1433 && r->request_body->temp_file
1434 && r == r->main)
1435 {
1436 /*
1437 * the r->request_body->buf can be reused for one request only,
1438 * the subrequests should allocate their own temporary bufs
1439 */
1440
1441 u->output.free = ngx_alloc_chain_link(r->pool);
1442 if (u->output.free == NULL((void*)0)) {
1443 ngx_http_upstream_finalize_request(r, u,
1444 NGX_HTTP_INTERNAL_SERVER_ERROR500);
1445 return;
1446 }
1447
1448 u->output.free->buf = r->request_body->buf;
1449 u->output.free->next = NULL((void*)0);
1450 u->output.allocated = 1;
1451
1452 r->request_body->buf->pos = r->request_body->buf->start;
1453 r->request_body->buf->last = r->request_body->buf->start;
1454 r->request_body->buf->tag = u->output.tag;
1455 }
1456
1457 u->request_sent = 0;
1458 u->request_body_sent = 0;
1459
1460 if (rc == NGX_AGAIN-2) {
1461 ngx_add_timerngx_event_add_timer(c->write, u->conf->connect_timeout);
1462 return;
1463 }
1464
1465#if (NGX_HTTP_SSL)
1466
1467 if (u->ssl && c->ssl == NULL((void*)0)) {
1468 ngx_http_upstream_ssl_init_connection(r, u, c);
1469 return;
1470 }
1471
1472#endif
1473
1474 ngx_http_upstream_send_request(r, u, 1);
1475}
1476
1477
1478#if (NGX_HTTP_SSL)
1479
1480static void
1481ngx_http_upstream_ssl_init_connection(ngx_http_request_t *r,
1482 ngx_http_upstream_t *u, ngx_connection_t *c)
1483{
1484 int tcp_nodelay;
1485 ngx_int_t rc;
1486 ngx_http_core_loc_conf_t *clcf;
1487
1488 if (ngx_http_upstream_test_connect(c) != NGX_OK0) {
1489 ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR0x00000002);
1490 return;
1491 }
1492
1493 if (ngx_ssl_create_connection(u->conf->ssl, c,
1494 NGX_SSL_BUFFER|NGX_SSL_CLIENT)
1495 != NGX_OK0)
1496 {
1497 ngx_http_upstream_finalize_request(r, u,
1498 NGX_HTTP_INTERNAL_SERVER_ERROR500);
1499 return;
1500 }
1501
1502 c->sendfile = 0;
1503 u->output.sendfile = 0;
1504
1505 if (u->conf->ssl_server_name || u->conf->ssl_verify) {
1506 if (ngx_http_upstream_ssl_name(r, u, c) != NGX_OK0) {
1507 ngx_http_upstream_finalize_request(r, u,
1508 NGX_HTTP_INTERNAL_SERVER_ERROR500);
1509 return;
1510 }
1511 }
1512
1513 if (u->conf->ssl_session_reuse) {
1514 if (u->peer.set_session(&u->peer, u->peer.data) != NGX_OK0) {
1515 ngx_http_upstream_finalize_request(r, u,
1516 NGX_HTTP_INTERNAL_SERVER_ERROR500);
1517 return;
1518 }
1519
1520 /* abbreviated SSL handshake may interact badly with Nagle */
1521
1522 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module)(r)->loc_conf[ngx_http_core_module.ctx_index];
1523
1524 if (clcf->tcp_nodelay && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) {
1525 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay");
1526
1527 tcp_nodelay = 1;
1528
1529 if (setsockopt(c->fd, IPPROTO_TCPIPPROTO_TCP, TCP_NODELAY1,
1530 (const void *) &tcp_nodelay, sizeof(int)) == -1)
1531 {
1532 ngx_connection_error(c, ngx_socket_errno(*__errno_location ()),
1533 "setsockopt(TCP_NODELAY) failed");
1534 ngx_http_upstream_finalize_request(r, u,
1535 NGX_HTTP_INTERNAL_SERVER_ERROR500);
1536 return;
1537 }
1538
1539 c->tcp_nodelay = NGX_TCP_NODELAY_SET;
1540 }
1541 }
1542
1543 r->connection->log->action = "SSL handshaking to upstream";
1544
1545 rc = ngx_ssl_handshake(c);
1546
1547 if (rc == NGX_AGAIN-2) {
1548
1549 if (!c->write->timer_set) {
1550 ngx_add_timerngx_event_add_timer(c->write, u->conf->connect_timeout);
1551 }
1552
1553 c->ssl->handler = ngx_http_upstream_ssl_handshake;
1554 return;
1555 }
1556
1557 ngx_http_upstream_ssl_handshake(c);
1558}
1559
1560
1561static void
1562ngx_http_upstream_ssl_handshake(ngx_connection_t *c)
1563{
1564 long rc;
1565 ngx_http_request_t *r;
1566 ngx_http_upstream_t *u;
1567
1568 r = c->data;
1569 u = r->upstream;
1570
1571 ngx_http_set_log_request(c->log, r)((ngx_http_log_ctx_t *) c->log->data)->current_request
= r
;
1572
1573 if (c->ssl->handshaked) {
1574
1575 if (u->conf->ssl_verify) {
1576 rc = SSL_get_verify_result(c->ssl->connection);
1577
1578 if (rc != X509_V_OK) {
1579 ngx_log_error(NGX_LOG_ERR, c->log, 0,if ((c->log)->log_level >= 4) ngx_log_error_core(4, c
->log, 0, "upstream SSL certificate verify error: (%l:%s)"
, rc, X509_verify_cert_error_string(rc))
1580 "upstream SSL certificate verify error: (%l:%s)",if ((c->log)->log_level >= 4) ngx_log_error_core(4, c
->log, 0, "upstream SSL certificate verify error: (%l:%s)"
, rc, X509_verify_cert_error_string(rc))
1581 rc, X509_verify_cert_error_string(rc))if ((c->log)->log_level >= 4) ngx_log_error_core(4, c
->log, 0, "upstream SSL certificate verify error: (%l:%s)"
, rc, X509_verify_cert_error_string(rc))
;
1582 goto failed;
1583 }
1584
1585 if (ngx_ssl_check_host(c, &u->ssl_name) != NGX_OK0) {
1586 ngx_log_error(NGX_LOG_ERR, c->log, 0,if ((c->log)->log_level >= 4) ngx_log_error_core(4, c
->log, 0, "upstream SSL certificate does not match \"%V\""
, &u->ssl_name)
1587 "upstream SSL certificate does not match \"%V\"",if ((c->log)->log_level >= 4) ngx_log_error_core(4, c
->log, 0, "upstream SSL certificate does not match \"%V\""
, &u->ssl_name)
1588 &u->ssl_name)if ((c->log)->log_level >= 4) ngx_log_error_core(4, c
->log, 0, "upstream SSL certificate does not match \"%V\""
, &u->ssl_name)
;
1589 goto failed;
1590 }
1591 }
1592
1593 if (u->conf->ssl_session_reuse) {
1594 u->peer.save_session(&u->peer, u->peer.data);
1595 }
1596
1597 c->write->handler = ngx_http_upstream_handler;
1598 c->read->handler = ngx_http_upstream_handler;
1599
1600 c = r->connection;
1601
1602 ngx_http_upstream_send_request(r, u, 1);
1603
1604 ngx_http_run_posted_requests(c);
1605 return;
1606 }
1607
1608failed:
1609
1610 c = r->connection;
1611
1612 ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR0x00000002);
1613
1614 ngx_http_run_posted_requests(c);
1615}
1616
1617
1618static ngx_int_t
1619ngx_http_upstream_ssl_name(ngx_http_request_t *r, ngx_http_upstream_t *u,
1620 ngx_connection_t *c)
1621{
1622 u_char *p, *last;
1623 ngx_str_t name;
1624
1625 if (u->conf->ssl_name) {
1626 if (ngx_http_complex_value(r, u->conf->ssl_name, &name) != NGX_OK0) {
1627 return NGX_ERROR-1;
1628 }
1629
1630 } else {
1631 name = u->ssl_name;
1632 }
1633
1634 if (name.len == 0) {
1635 goto done;
1636 }
1637
1638 /*
1639 * ssl name here may contain port, notably if derived from $proxy_host
1640 * or $http_host; we have to strip it
1641 */
1642
1643 p = name.data;
1644 last = name.data + name.len;
1645
1646 if (*p == '[') {
1647 p = ngx_strlchr(p, last, ']');
1648
1649 if (p == NULL((void*)0)) {
1650 p = name.data;
1651 }
1652 }
1653
1654 p = ngx_strlchr(p, last, ':');
1655
1656 if (p != NULL((void*)0)) {
1657 name.len = p - name.data;
1658 }
1659
1660 if (!u->conf->ssl_server_name) {
1661 goto done;
1662 }
1663
1664#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
1665
1666 /* as per RFC 6066, literal IPv4 and IPv6 addresses are not permitted */
1667
1668 if (name.len == 0 || *name.data == '[') {
1669 goto done;
1670 }
1671
1672 if (ngx_inet_addr(name.data, name.len) != INADDR_NONE((in_addr_t) 0xffffffff)) {
1673 goto done;
1674 }
1675
1676 /*
1677 * SSL_set_tlsext_host_name() needs a null-terminated string,
1678 * hence we explicitly null-terminate name here
1679 */
1680
1681 p = ngx_pnalloc(r->pool, name.len + 1);
1682 if (p == NULL((void*)0)) {
1683 return NGX_ERROR-1;
1684 }
1685
1686 (void) ngx_cpystrn(p, name.data, name.len + 1);
1687
1688 name.data = p;
1689
1690 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1691 "upstream SSL server name: \"%s\"", name.data);
1692
1693 if (SSL_set_tlsext_host_name(c->ssl->connection, name.data) == 0) {
1694 ngx_ssl_error(NGX_LOG_ERR4, r->connection->log, 0,
1695 "SSL_set_tlsext_host_name(\"%s\") failed", name.data);
1696 return NGX_ERROR-1;
1697 }
1698
1699#endif
1700
1701done:
1702
1703 u->ssl_name = name;
1704
1705 return NGX_OK0;
1706}
1707
1708#endif
1709
1710
1711static ngx_int_t
1712ngx_http_upstream_reinit(ngx_http_request_t *r, ngx_http_upstream_t *u)
1713{
1714 off_t file_pos;
1715 ngx_chain_t *cl;
1716
1717 if (u->reinit_request(r) != NGX_OK0) {
1718 return NGX_ERROR-1;
1719 }
1720
1721 u->keepalive = 0;
1722 u->upgrade = 0;
1723
1724 ngx_memzero(&u->headers_in, sizeof(ngx_http_upstream_headers_in_t))(void) memset(&u->headers_in, 0, sizeof(ngx_http_upstream_headers_in_t
))
;
1725 u->headers_in.content_length_n = -1;
1726 u->headers_in.last_modified_time = -1;
1727
1728 if (ngx_list_init(&u->headers_in.headers, r->pool, 8,
1729 sizeof(ngx_table_elt_t))
1730 != NGX_OK0)
1731 {
1732 return NGX_ERROR-1;
1733 }
1734
1735 /* reinit the request chain */
1736
1737 file_pos = 0;
1738
1739 for (cl = u->request_bufs; cl; cl = cl->next) {
1740 cl->buf->pos = cl->buf->start;
1741
1742 /* there is at most one file */
1743
1744 if (cl->buf->in_file) {
1745 cl->buf->file_pos = file_pos;
1746 file_pos = cl->buf->file_last;
1747 }
1748 }
1749
1750 /* reinit the subrequest's ngx_output_chain() context */
1751
1752 if (r->request_body && r->request_body->temp_file
1753 && r != r->main && u->output.buf)
1754 {
1755 u->output.free = ngx_alloc_chain_link(r->pool);
1756 if (u->output.free == NULL((void*)0)) {
1757 return NGX_ERROR-1;
1758 }
1759
1760 u->output.free->buf = u->output.buf;
1761 u->output.free->next = NULL((void*)0);
1762
1763 u->output.buf->pos = u->output.buf->start;
1764 u->output.buf->last = u->output.buf->start;
1765 }
1766
1767 u->output.buf = NULL((void*)0);
1768 u->output.in = NULL((void*)0);
1769 u->output.busy = NULL((void*)0);
1770
1771 /* reinit u->buffer */
1772
1773 u->buffer.pos = u->buffer.start;
1774
1775#if (NGX_HTTP_CACHE1)
1776
1777 if (r->cache) {
1778 u->buffer.pos += r->cache->header_start;
1779 }
1780
1781#endif
1782
1783 u->buffer.last = u->buffer.pos;
1784
1785 return NGX_OK0;
1786}
1787
1788
1789static void
1790ngx_http_upstream_send_request(ngx_http_request_t *r, ngx_http_upstream_t *u,
1791 ngx_uint_t do_write)
1792{
1793 ngx_int_t rc;
1794 ngx_connection_t *c;
1795
1796 c = u->peer.connection;
1797
1798 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
1799 "http upstream send request");
1800
1801 if (u->state->connect_time == (ngx_msec_t) -1) {
1802 u->state->connect_time = ngx_current_msec - u->state->response_time;
1803 }
1804
1805 if (!u->request_sent && ngx_http_upstream_test_connect(c) != NGX_OK0) {
1806 ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR0x00000002);
1807 return;
1808 }
1809
1810 c->log->action = "sending request to upstream";
1811
1812 rc = ngx_http_upstream_send_request_body(r, u, do_write);
1813
1814 if (rc == NGX_ERROR-1) {
1815 ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR0x00000002);
1816 return;
1817 }
1818
1819 if (rc >= NGX_HTTP_SPECIAL_RESPONSE300) {
1820 ngx_http_upstream_finalize_request(r, u, rc);
1821 return;
1822 }
1823
1824 if (rc == NGX_AGAIN-2) {
1825 if (!c->write->ready) {
1826 ngx_add_timerngx_event_add_timer(c->write, u->conf->send_timeout);
1827
1828 } else if (c->write->timer_set) {
1829 ngx_del_timerngx_event_del_timer(c->write);
1830 }
1831
1832 if (ngx_handle_write_event(c->write, u->conf->send_lowat) != NGX_OK0) {
1833 ngx_http_upstream_finalize_request(r, u,
1834 NGX_HTTP_INTERNAL_SERVER_ERROR500);
1835 return;
1836 }
1837
1838 return;
1839 }
1840
1841 /* rc == NGX_OK */
1842
1843 u->request_body_sent = 1;
1844
1845 if (c->write->timer_set) {
1846 ngx_del_timerngx_event_del_timer(c->write);
1847 }
1848
1849 if (c->tcp_nopush == NGX_TCP_NOPUSH_SET) {
1850 if (ngx_tcp_push(c->fd) == NGX_ERROR-1) {
1851 ngx_log_error(NGX_LOG_CRIT, c->log, ngx_socket_errno,if ((c->log)->log_level >= 3) ngx_log_error_core(3, c
->log, (*__errno_location ()), "setsockopt(!TCP_CORK)" " failed"
)
1852 ngx_tcp_push_n " failed")if ((c->log)->log_level >= 3) ngx_log_error_core(3, c
->log, (*__errno_location ()), "setsockopt(!TCP_CORK)" " failed"
)
;
1853 ngx_http_upstream_finalize_request(r, u,
1854 NGX_HTTP_INTERNAL_SERVER_ERROR500);
1855 return;
1856 }
1857
1858 c->tcp_nopush = NGX_TCP_NOPUSH_UNSET;
1859 }
1860
1861 u->write_event_handler = ngx_http_upstream_dummy_handler;
1862
1863 if (ngx_handle_write_event(c->write, 0) != NGX_OK0) {
1864 ngx_http_upstream_finalize_request(r, u,
1865 NGX_HTTP_INTERNAL_SERVER_ERROR500);
1866 return;
1867 }
1868
1869 ngx_add_timerngx_event_add_timer(c->read, u->conf->read_timeout);
1870
1871 if (c->read->ready) {
1872 ngx_http_upstream_process_header(r, u);
1873 return;
1874 }
1875}
1876
1877
1878static ngx_int_t
1879ngx_http_upstream_send_request_body(ngx_http_request_t *r,
1880 ngx_http_upstream_t *u, ngx_uint_t do_write)
1881{
1882 int tcp_nodelay;
1883 ngx_int_t rc;
1884 ngx_chain_t *out, *cl, *ln;
1885 ngx_connection_t *c;
1886 ngx_http_core_loc_conf_t *clcf;
1887
1888 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1889 "http upstream send request body");
1890
1891 if (!r->request_body_no_buffering) {
1892
1893 /* buffered request body */
1894
1895 if (!u->request_sent) {
1896 u->request_sent = 1;
1897 out = u->request_bufs;
1898
1899 } else {
1900 out = NULL((void*)0);
1901 }
1902
1903 return ngx_output_chain(&u->output, out);
1904 }
1905
1906 if (!u->request_sent) {
1907 u->request_sent = 1;
1908 out = u->request_bufs;
1909
1910 if (r->request_body->bufs) {
1911 for (cl = out; cl->next; cl = out->next) { /* void */ }
1912 cl->next = r->request_body->bufs;
1913 r->request_body->bufs = NULL((void*)0);
1914 }
1915
1916 c = u->peer.connection;
1917 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module)(r)->loc_conf[ngx_http_core_module.ctx_index];
1918
1919 if (clcf->tcp_nodelay && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) {
1920 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay");
1921
1922 tcp_nodelay = 1;
1923
1924 if (setsockopt(c->fd, IPPROTO_TCPIPPROTO_TCP, TCP_NODELAY1,
1925 (const void *) &tcp_nodelay, sizeof(int)) == -1)
1926 {
1927 ngx_connection_error(c, ngx_socket_errno(*__errno_location ()),
1928 "setsockopt(TCP_NODELAY) failed");
1929 return NGX_ERROR-1;
1930 }
1931
1932 c->tcp_nodelay = NGX_TCP_NODELAY_SET;
1933 }
1934
1935 r->read_event_handler = ngx_http_upstream_read_request_handler;
1936
1937 } else {
1938 out = NULL((void*)0);
1939 }
1940
1941 for ( ;; ) {
1942
1943 if (do_write) {
1944 rc = ngx_output_chain(&u->output, out);
1945
1946 if (rc == NGX_ERROR-1) {
1947 return NGX_ERROR-1;
1948 }
1949
1950 while (out) {
1951 ln = out;
1952 out = out->next;
1953 ngx_free_chain(r->pool, ln)ln->next = r->pool->chain; r->pool->chain = ln;
1954 }
1955
1956 if (rc == NGX_OK0 && !r->reading_body) {
1957 break;
1958 }
1959 }
1960
1961 if (r->reading_body) {
1962 /* read client request body */
1963
1964 rc = ngx_http_read_unbuffered_request_body(r);
1965
1966 if (rc >= NGX_HTTP_SPECIAL_RESPONSE300) {
1967 return rc;
1968 }
1969
1970 out = r->request_body->bufs;
1971 r->request_body->bufs = NULL((void*)0);
1972 }
1973
1974 /* stop if there is nothing to send */
1975
1976 if (out == NULL((void*)0)) {
1977 rc = NGX_AGAIN-2;
1978 break;
1979 }
1980
1981 do_write = 1;
1982 }
1983
1984 if (!r->reading_body) {
1985 if (!u->store && !r->post_action && !u->conf->ignore_client_abort) {
1986 r->read_event_handler =
1987 ngx_http_upstream_rd_check_broken_connection;
1988 }
1989 }
1990
1991 return rc;
1992}
1993
1994
1995static void
1996ngx_http_upstream_send_request_handler(ngx_http_request_t *r,
1997 ngx_http_upstream_t *u)
1998{
1999 ngx_connection_t *c;
2000
2001 c = u->peer.connection;
2002
2003 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2004 "http upstream send request handler");
2005
2006 if (c->write->timedout) {
2007 ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_TIMEOUT0x00000004);
2008 return;
2009 }
2010
2011#if (NGX_HTTP_SSL)
2012
2013 if (u->ssl && c->ssl == NULL((void*)0)) {
2014 ngx_http_upstream_ssl_init_connection(r, u, c);
2015 return;
2016 }
2017
2018#endif
2019
2020 if (u->header_sent) {
2021 u->write_event_handler = ngx_http_upstream_dummy_handler;
2022
2023 (void) ngx_handle_write_event(c->write, 0);
2024
2025 return;
2026 }
2027
2028 ngx_http_upstream_send_request(r, u, 1);
2029}
2030
2031
2032static void
2033ngx_http_upstream_read_request_handler(ngx_http_request_t *r)
2034{
2035 ngx_connection_t *c;
2036 ngx_http_upstream_t *u;
2037
2038 c = r->connection;
2039 u = r->upstream;
2040
2041 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2042 "http upstream read request handler");
2043
2044 if (c->read->timedout) {
2045 c->timedout = 1;
2046 ngx_http_upstream_finalize_request(r, u, NGX_HTTP_REQUEST_TIME_OUT408);
2047 return;
2048 }
2049
2050 ngx_http_upstream_send_request(r, u, 0);
2051}
2052
2053
2054static void
2055ngx_http_upstream_process_header(ngx_http_request_t *r, ngx_http_upstream_t *u)
2056{
2057 ssize_t n;
2058 ngx_int_t rc;
2059 ngx_connection_t *c;
2060
2061 c = u->peer.connection;
2062
2063 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
2064 "http upstream process header");
2065
2066 c->log->action = "reading response header from upstream";
2067
2068 if (c->read->timedout) {
2069 ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_TIMEOUT0x00000004);
2070 return;
2071 }
2072
2073 if (!u->request_sent && ngx_http_upstream_test_connect(c) != NGX_OK0) {
2074 ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR0x00000002);
2075 return;
2076 }
2077
2078 if (u->buffer.start == NULL((void*)0)) {
2079 u->buffer.start = ngx_palloc(r->pool, u->conf->buffer_size);
2080 if (u->buffer.start == NULL((void*)0)) {
2081 ngx_http_upstream_finalize_request(r, u,
2082 NGX_HTTP_INTERNAL_SERVER_ERROR500);
2083 return;
2084 }
2085
2086 u->buffer.pos = u->buffer.start;
2087 u->buffer.last = u->buffer.start;
2088 u->buffer.end = u->buffer.start + u->conf->buffer_size;
2089 u->buffer.temporary = 1;
2090
2091 u->buffer.tag = u->output.tag;
2092
2093 if (ngx_list_init(&u->headers_in.headers, r->pool, 8,
2094 sizeof(ngx_table_elt_t))
2095 != NGX_OK0)
2096 {
2097 ngx_http_upstream_finalize_request(r, u,
2098 NGX_HTTP_INTERNAL_SERVER_ERROR500);
2099 return;
2100 }
2101
2102#if (NGX_HTTP_CACHE1)
2103
2104 if (r->cache) {
2105 u->buffer.pos += r->cache->header_start;
2106 u->buffer.last = u->buffer.pos;
2107 }
2108#endif
2109 }
2110
2111 for ( ;; ) {
2112
2113 n = c->recv(c, u->buffer.last, u->buffer.end - u->buffer.last);
2114
2115 if (n == NGX_AGAIN-2) {
2116#if 0
2117 ngx_add_timerngx_event_add_timer(rev, u->read_timeout);
2118#endif
2119
2120 if (ngx_handle_read_event(c->read, 0) != NGX_OK0) {
2121 ngx_http_upstream_finalize_request(r, u,
2122 NGX_HTTP_INTERNAL_SERVER_ERROR500);
2123 return;
2124 }
2125
2126 return;
2127 }
2128
2129 if (n == 0) {
2130 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")
2131 "upstream prematurely closed connection")if ((c->log)->log_level >= 4) ngx_log_error_core(4, c
->log, 0, "upstream prematurely closed connection")
;
2132 }
2133
2134 if (n == NGX_ERROR-1 || n == 0) {
2135 ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR0x00000002);
2136 return;
2137 }
2138
2139 u->buffer.last += n;
2140
2141#if 0
2142 u->valid_header_in = 0;
2143
2144 u->peer.cached = 0;
2145#endif
2146
2147 rc = u->process_header(r);
2148
2149 if (rc == NGX_AGAIN-2) {
2150
2151 if (u->buffer.last == u->buffer.end) {
2152 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")
2153 "upstream sent too big header")if ((c->log)->log_level >= 4) ngx_log_error_core(4, c
->log, 0, "upstream sent too big header")
;
2154
2155 ngx_http_upstream_next(r, u,
2156 NGX_HTTP_UPSTREAM_FT_INVALID_HEADER0x00000008);
2157 return;
2158 }
2159
2160 continue;
2161 }
2162
2163 break;
2164 }
2165
2166 if (rc == NGX_HTTP_UPSTREAM_INVALID_HEADER40) {
2167 ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_INVALID_HEADER0x00000008);
2168 return;
2169 }
2170
2171 if (rc == NGX_ERROR-1) {
2172 ngx_http_upstream_finalize_request(r, u,
2173 NGX_HTTP_INTERNAL_SERVER_ERROR500);
2174 return;
2175 }
2176
2177 /* rc == NGX_OK */
2178
2179 u->state->header_time = ngx_current_msec - u->state->response_time;
2180
2181 if (u->headers_in.status_n >= NGX_HTTP_SPECIAL_RESPONSE300) {
2182
2183 if (ngx_http_upstream_test_next(r, u) == NGX_OK0) {
2184 return;
2185 }
2186
2187 if (ngx_http_upstream_intercept_errors(r, u) == NGX_OK0) {
2188 return;
2189 }
2190 }
2191
2192 if (ngx_http_upstream_process_headers(r, u) != NGX_OK0) {
2193 return;
2194 }
2195
2196 if (!r->subrequest_in_memory) {
2197 ngx_http_upstream_send_response(r, u);
2198 return;
2199 }
2200
2201 /* subrequest content in memory */
2202
2203 if (u->input_filter == NULL((void*)0)) {
2204 u->input_filter_init = ngx_http_upstream_non_buffered_filter_init;
2205 u->input_filter = ngx_http_upstream_non_buffered_filter;
2206 u->input_filter_ctx = r;
2207 }
2208
2209 if (u->input_filter_init(u->input_filter_ctx) == NGX_ERROR-1) {
2210 ngx_http_upstream_finalize_request(r, u, NGX_ERROR-1);
2211 return;
2212 }
2213
2214 n = u->buffer.last - u->buffer.pos;
2215
2216 if (n) {
2217 u->buffer.last = u->buffer.pos;
2218
2219 u->state->response_length += n;
2220
2221 if (u->input_filter(u->input_filter_ctx, n) == NGX_ERROR-1) {
2222 ngx_http_upstream_finalize_request(r, u, NGX_ERROR-1);
2223 return;
2224 }
2225 }
2226
2227 if (u->length == 0) {
2228 ngx_http_upstream_finalize_request(r, u, 0);
2229 return;
2230 }
2231
2232 u->read_event_handler = ngx_http_upstream_process_body_in_memory;
2233
2234 ngx_http_upstream_process_body_in_memory(r, u);
2235}
2236
2237
2238static ngx_int_t
2239ngx_http_upstream_test_next(ngx_http_request_t *r, ngx_http_upstream_t *u)
2240{
2241 ngx_uint_t status;
2242 ngx_http_upstream_next_t *un;
2243
2244 status = u->headers_in.status_n;
2245
2246 for (un = ngx_http_upstream_next_errors; un->status; un++) {
2247
2248 if (status != un->status) {
2249 continue;
2250 }
2251
2252 if (u->peer.tries > 1 && (u->conf->next_upstream & un->mask)) {
2253 ngx_http_upstream_next(r, u, un->mask);
2254 return NGX_OK0;
2255 }
2256
2257#if (NGX_HTTP_CACHE1)
2258
2259 if (u->cache_status == NGX_HTTP_CACHE_EXPIRED3
2260 && (u->conf->cache_use_stale & un->mask))
2261 {
2262 ngx_int_t rc;
2263
2264 rc = u->reinit_request(r);
2265
2266 if (rc == NGX_OK0) {
2267 u->cache_status = NGX_HTTP_CACHE_STALE4;
2268 rc = ngx_http_upstream_cache_send(r, u);
2269 }
2270
2271 ngx_http_upstream_finalize_request(r, u, rc);
2272 return NGX_OK0;
2273 }
2274
2275#endif
2276 }
2277
2278#if (NGX_HTTP_CACHE1)
2279
2280 if (status == NGX_HTTP_NOT_MODIFIED304
2281 && u->cache_status == NGX_HTTP_CACHE_EXPIRED3
2282 && u->conf->cache_revalidate)
2283 {
2284 time_t now, valid;
2285 ngx_int_t rc;
2286
2287 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2288 "http upstream not modified");
2289
2290 now = ngx_time()ngx_cached_time->sec;
2291 valid = r->cache->valid_sec;
2292
2293 rc = u->reinit_request(r);
2294
2295 if (rc != NGX_OK0) {
2296 ngx_http_upstream_finalize_request(r, u, rc);
2297 return NGX_OK0;
2298 }
2299
2300 u->cache_status = NGX_HTTP_CACHE_REVALIDATED6;
2301 rc = ngx_http_upstream_cache_send(r, u);
2302
2303 if (valid == 0) {
2304 valid = r->cache->valid_sec;
2305 }
2306
2307 if (valid == 0) {
2308 valid = ngx_http_file_cache_valid(u->conf->cache_valid,
2309 u->headers_in.status_n);
2310 if (valid) {
2311 valid = now + valid;
2312 }
2313 }
2314
2315 if (valid) {
2316 r->cache->valid_sec = valid;
2317 r->cache->date = now;
2318
2319 ngx_http_file_cache_update_header(r);
2320 }
2321
2322 ngx_http_upstream_finalize_request(r, u, rc);
2323 return NGX_OK0;
2324 }
2325
2326#endif
2327
2328 return NGX_DECLINED-5;
2329}
2330
2331
2332static ngx_int_t
2333ngx_http_upstream_intercept_errors(ngx_http_request_t *r,
2334 ngx_http_upstream_t *u)
2335{
2336 ngx_int_t status;
2337 ngx_uint_t i;
2338 ngx_table_elt_t *h;
2339 ngx_http_err_page_t *err_page;
2340 ngx_http_core_loc_conf_t *clcf;
2341
2342 status = u->headers_in.status_n;
2343
2344 if (status == NGX_HTTP_NOT_FOUND404 && u->conf->intercept_404) {
2345 ngx_http_upstream_finalize_request(r, u, NGX_HTTP_NOT_FOUND404);
2346 return NGX_OK0;
2347 }
2348
2349 if (!u->conf->intercept_errors) {
2350 return NGX_DECLINED-5;
2351 }
2352
2353 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module)(r)->loc_conf[ngx_http_core_module.ctx_index];
2354
2355 if (clcf->error_pages == NULL((void*)0)) {
2356 return NGX_DECLINED-5;
2357 }
2358
2359 err_page = clcf->error_pages->elts;
2360 for (i = 0; i < clcf->error_pages->nelts; i++) {
2361
2362 if (err_page[i].status == status) {
2363
2364 if (status == NGX_HTTP_UNAUTHORIZED401
2365 && u->headers_in.www_authenticate)
2366 {
2367 h = ngx_list_push(&r->headers_out.headers);
2368
2369 if (h == NULL((void*)0)) {
2370 ngx_http_upstream_finalize_request(r, u,
2371 NGX_HTTP_INTERNAL_SERVER_ERROR500);
2372 return NGX_OK0;
2373 }
2374
2375 *h = *u->headers_in.www_authenticate;
2376
2377 r->headers_out.www_authenticate = h;
2378 }
2379
2380#if (NGX_HTTP_CACHE1)
2381
2382 if (r->cache) {
2383 time_t valid;
2384
2385 valid = ngx_http_file_cache_valid(u->conf->cache_valid, status);
2386
2387 if (valid) {
2388 r->cache->valid_sec = ngx_time()ngx_cached_time->sec + valid;
2389 r->cache->error = status;
2390 }
2391
2392 ngx_http_file_cache_free(r->cache, u->pipe->temp_file);
2393 }
2394#endif
2395 ngx_http_upstream_finalize_request(r, u, status);
2396
2397 return NGX_OK0;
2398 }
2399 }
2400
2401 return NGX_DECLINED-5;
2402}
2403
2404
2405static ngx_int_t
2406ngx_http_upstream_test_connect(ngx_connection_t *c)
2407{
2408 int err;
2409 socklen_t len;
2410
2411#if (NGX_HAVE_KQUEUE)
2412
2413 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT0x00000008) {
2414 if (c->write->pending_eof || c->read->pending_eof) {
2415 if (c->write->pending_eof) {
2416 err = c->write->kq_errno;
2417
2418 } else {
2419 err = c->read->kq_errno;
2420 }
2421
2422 c->log->action = "connecting to upstream";
2423 (void) ngx_connection_error(c, err,
2424 "kevent() reported that connect() failed");
2425 return NGX_ERROR-1;
2426 }
2427
2428 } else
2429#endif
2430 {
2431 err = 0;
2432 len = sizeof(int);
2433
2434 /*
2435 * BSDs and Linux return 0 and set a pending error in err
2436 * Solaris returns -1 and sets errno
2437 */
2438
2439 if (getsockopt(c->fd, SOL_SOCKET1, SO_ERROR4, (void *) &err, &len)
2440 == -1)
2441 {
2442 err = ngx_socket_errno(*__errno_location ());
2443 }
2444
2445 if (err) {
2446 c->log->action = "connecting to upstream";
2447 (void) ngx_connection_error(c, err, "connect() failed");
2448 return NGX_ERROR-1;
2449 }
2450 }
2451
2452 return NGX_OK0;
2453}
2454
2455
2456static ngx_int_t
2457ngx_http_upstream_process_headers(ngx_http_request_t *r, ngx_http_upstream_t *u)
2458{
2459 ngx_str_t uri, args;
2460 ngx_uint_t i, flags;
2461 ngx_list_part_t *part;
2462 ngx_table_elt_t *h;
2463 ngx_http_upstream_header_t *hh;
2464 ngx_http_upstream_main_conf_t *umcf;
2465
2466 umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module)(r)->main_conf[ngx_http_upstream_module.ctx_index];
2467
2468 if (u->headers_in.x_accel_redirect
2469 && !(u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_XA_REDIRECT0x00000002))
2470 {
2471 ngx_http_upstream_finalize_request(r, u, NGX_DECLINED-5);
2472
2473 part = &u->headers_in.headers.part;
2474 h = part->elts;
2475
2476 for (i = 0; /* void */; i++) {
2477
2478 if (i >= part->nelts) {
2479 if (part->next == NULL((void*)0)) {
2480 break;
2481 }
2482
2483 part = part->next;
2484 h = part->elts;
2485 i = 0;
2486 }
2487
2488 hh = ngx_hash_find(&umcf->headers_in_hash, h[i].hash,
2489 h[i].lowcase_key, h[i].key.len);
2490
2491 if (hh && hh->redirect) {
2492 if (hh->copy_handler(r, &h[i], hh->conf) != NGX_OK0) {
2493 ngx_http_finalize_request(r,
2494 NGX_HTTP_INTERNAL_SERVER_ERROR500);
2495 return NGX_DONE-4;
2496 }
2497 }
2498 }
2499
2500 uri = u->headers_in.x_accel_redirect->value;
2501
2502 if (uri.data[0] == '@') {
2503 ngx_http_named_location(r, &uri);
2504
2505 } else {
2506 ngx_str_null(&args)(&args)->len = 0; (&args)->data = ((void*)0);
2507 flags = NGX_HTTP_LOG_UNSAFE8;
2508
2509 if (ngx_http_parse_unsafe_uri(r, &uri, &args, &flags) != NGX_OK0) {
2510 ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND404);
2511 return NGX_DONE-4;
2512 }
2513
2514 if (r->method != NGX_HTTP_HEAD0x0004) {
2515 r->method = NGX_HTTP_GET0x0002;
2516 r->method_name = ngx_http_core_get_method;
2517 }
2518
2519 ngx_http_internal_redirect(r, &uri, &args);
2520 }
2521
2522 ngx_http_finalize_request(r, NGX_DONE-4);
2523 return NGX_DONE-4;
2524 }
2525
2526 part = &u->headers_in.headers.part;
2527 h = part->elts;
2528
2529 for (i = 0; /* void */; i++) {
2530
2531 if (i >= part->nelts) {
2532 if (part->next == NULL((void*)0)) {
2533 break;
2534 }
2535
2536 part = part->next;
2537 h = part->elts;
2538 i = 0;
2539 }
2540
2541 if (ngx_hash_find(&u->conf->hide_headers_hash, h[i].hash,
2542 h[i].lowcase_key, h[i].key.len))
2543 {
2544 continue;
2545 }
2546
2547 hh = ngx_hash_find(&umcf->headers_in_hash, h[i].hash,
2548 h[i].lowcase_key, h[i].key.len);
2549
2550 if (hh) {
2551 if (hh->copy_handler(r, &h[i], hh->conf) != NGX_OK0) {
2552 ngx_http_upstream_finalize_request(r, u,
2553 NGX_HTTP_INTERNAL_SERVER_ERROR500);
2554 return NGX_DONE-4;
2555 }
2556
2557 continue;
2558 }
2559
2560 if (ngx_http_upstream_copy_header_line(r, &h[i], 0) != NGX_OK0) {
2561 ngx_http_upstream_finalize_request(r, u,
2562 NGX_HTTP_INTERNAL_SERVER_ERROR500);
2563 return NGX_DONE-4;
2564 }
2565 }
2566
2567 if (r->headers_out.server && r->headers_out.server->value.data == NULL((void*)0)) {
2568 r->headers_out.server->hash = 0;
2569 }
2570
2571 if (r->headers_out.date && r->headers_out.date->value.data == NULL((void*)0)) {
2572 r->headers_out.date->hash = 0;
2573 }
2574
2575 r->headers_out.status = u->headers_in.status_n;
2576 r->headers_out.status_line = u->headers_in.status_line;
2577
2578 r->headers_out.content_length_n = u->headers_in.content_length_n;
2579
2580 r->disable_not_modified = !u->cacheable;
2581
2582 if (u->conf->force_ranges) {
2583 r->allow_ranges = 1;
2584 r->single_range = 1;
2585
2586#if (NGX_HTTP_CACHE1)
2587 if (r->cached) {
2588 r->single_range = 0;
2589 }
2590#endif
2591 }
2592
2593 u->length = -1;
2594
2595 return NGX_OK0;
2596}
2597
2598
2599static void
2600ngx_http_upstream_process_body_in_memory(ngx_http_request_t *r,
2601 ngx_http_upstream_t *u)
2602{
2603 size_t size;
2604 ssize_t n;
2605 ngx_buf_t *b;
2606 ngx_event_t *rev;
2607 ngx_connection_t *c;
2608
2609 c = u->peer.connection;
2610 rev = c->read;
2611
2612 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
2613 "http upstream process body on memory");
2614
2615 if (rev->timedout) {
2616 ngx_connection_error(c, NGX_ETIMEDOUT110, "upstream timed out");
2617 ngx_http_upstream_finalize_request(r, u, NGX_HTTP_GATEWAY_TIME_OUT504);
2618 return;
2619 }
2620
2621 b = &u->buffer;
2622
2623 for ( ;; ) {
2624
2625 size = b->end - b->last;
2626
2627 if (size == 0) {
2628 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")
2629 "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")
;
2630 ngx_http_upstream_finalize_request(r, u, NGX_ERROR-1);
2631 return;
2632 }
2633
2634 n = c->recv(c, b->last, size);
2635
2636 if (n == NGX_AGAIN-2) {
2637 break;
2638 }
2639
2640 if (n == 0 || n == NGX_ERROR-1) {
2641 ngx_http_upstream_finalize_request(r, u, n);
2642 return;
2643 }
2644
2645 u->state->response_length += n;
2646
2647 if (u->input_filter(u->input_filter_ctx, n) == NGX_ERROR-1) {
2648 ngx_http_upstream_finalize_request(r, u, NGX_ERROR-1);
2649 return;
2650 }
2651
2652 if (!rev->ready) {
2653 break;
2654 }
2655 }
2656
2657 if (u->length == 0) {
2658 ngx_http_upstream_finalize_request(r, u, 0);
2659 return;
2660 }
2661
2662 if (ngx_handle_read_event(rev, 0) != NGX_OK0) {
2663 ngx_http_upstream_finalize_request(r, u, NGX_ERROR-1);
2664 return;
2665 }
2666
2667 if (rev->active) {
2668 ngx_add_timerngx_event_add_timer(rev, u->conf->read_timeout);
2669
2670 } else if (rev->timer_set) {
2671 ngx_del_timerngx_event_del_timer(rev);
2672 }
2673}
2674
2675
2676static void
2677ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
2678{
2679 int tcp_nodelay;
2680 ssize_t n;
2681 ngx_int_t rc;
2682 ngx_event_pipe_t *p;
2683 ngx_connection_t *c;
2684 ngx_http_core_loc_conf_t *clcf;
2685
2686 rc = ngx_http_send_header(r);
2687
2688 if (rc == NGX_ERROR-1 || rc > NGX_OK0 || r->post_action) {
2689 ngx_http_upstream_finalize_request(r, u, rc);
2690 return;
2691 }
2692
2693 u->header_sent = 1;
2694
2695 if (u->upgrade) {
2696 ngx_http_upstream_upgrade(r, u);
2697 return;
2698 }
2699
2700 c = r->connection;
2701
2702 if (r->header_only) {
2703
2704 if (!u->buffering) {
2705 ngx_http_upstream_finalize_request(r, u, rc);
2706 return;
2707 }
2708
2709 if (!u->cacheable && !u->store) {
2710 ngx_http_upstream_finalize_request(r, u, rc);
2711 return;
2712 }
2713
2714 u->pipe->downstream_error = 1;
2715 }
2716
2717 if (r->request_body && r->request_body->temp_file) {
2718 ngx_pool_run_cleanup_file(r->pool, r->request_body->temp_file->file.fd);
2719 r->request_body->temp_file->file.fd = NGX_INVALID_FILE-1;
2720 }
2721
2722 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module)(r)->loc_conf[ngx_http_core_module.ctx_index];
2723
2724 if (!u->buffering) {
2725
2726 if (u->input_filter == NULL((void*)0)) {
2727 u->input_filter_init = ngx_http_upstream_non_buffered_filter_init;
2728 u->input_filter = ngx_http_upstream_non_buffered_filter;
2729 u->input_filter_ctx = r;
2730 }
2731
2732 u->read_event_handler = ngx_http_upstream_process_non_buffered_upstream;
2733 r->write_event_handler =
2734 ngx_http_upstream_process_non_buffered_downstream;
2735
2736 r->limit_rate = 0;
2737
2738 if (u->input_filter_init(u->input_filter_ctx) == NGX_ERROR-1) {
2739 ngx_http_upstream_finalize_request(r, u, NGX_ERROR-1);
2740 return;
2741 }
2742
2743 if (clcf->tcp_nodelay && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) {
2744 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay");
2745
2746 tcp_nodelay = 1;
2747
2748 if (setsockopt(c->fd, IPPROTO_TCPIPPROTO_TCP, TCP_NODELAY1,
2749 (const void *) &tcp_nodelay, sizeof(int)) == -1)
2750 {
2751 ngx_connection_error(c, ngx_socket_errno(*__errno_location ()),
2752 "setsockopt(TCP_NODELAY) failed");
2753 ngx_http_upstream_finalize_request(r, u, NGX_ERROR-1);
2754 return;
2755 }
2756
2757 c->tcp_nodelay = NGX_TCP_NODELAY_SET;
2758 }
2759
2760 n = u->buffer.last - u->buffer.pos;
2761
2762 if (n) {
2763 u->buffer.last = u->buffer.pos;
2764
2765 u->state->response_length += n;
2766
2767 if (u->input_filter(u->input_filter_ctx, n) == NGX_ERROR-1) {
2768 ngx_http_upstream_finalize_request(r, u, NGX_ERROR-1);
2769 return;
2770 }
2771
2772 ngx_http_upstream_process_non_buffered_downstream(r);
2773
2774 } else {
2775 u->buffer.pos = u->buffer.start;
2776 u->buffer.last = u->buffer.start;
2777
2778 if (ngx_http_send_special(r, NGX_HTTP_FLUSH2) == NGX_ERROR-1) {
2779 ngx_http_upstream_finalize_request(r, u, NGX_ERROR-1);
2780 return;
2781 }
2782
2783 if (u->peer.connection->read->ready || u->length == 0) {
2784 ngx_http_upstream_process_non_buffered_upstream(r, u);
2785 }
2786 }
2787
2788 return;
2789 }
2790
2791 /* TODO: preallocate event_pipe bufs, look "Content-Length" */
2792
2793#if (NGX_HTTP_CACHE1)
2794
2795 if (r->cache && r->cache->file.fd != NGX_INVALID_FILE-1) {
2796 ngx_pool_run_cleanup_file(r->pool, r->cache->file.fd);
2797 r->cache->file.fd = NGX_INVALID_FILE-1;
2798 }
2799
2800 switch (ngx_http_test_predicates(r, u->conf->no_cache)) {
2801
2802 case NGX_ERROR-1:
2803 ngx_http_upstream_finalize_request(r, u, NGX_ERROR-1);
2804 return;
2805
2806 case NGX_DECLINED-5:
2807 u->cacheable = 0;
2808 break;
2809
2810 default: /* NGX_OK */
2811
2812 if (u->cache_status == NGX_HTTP_CACHE_BYPASS2) {
2813
2814 /* create cache if previously bypassed */
2815
2816 if (ngx_http_file_cache_create(r) != NGX_OK0) {
2817 ngx_http_upstream_finalize_request(r, u, NGX_ERROR-1);
2818 return;
2819 }
2820 }
2821
2822 break;
2823 }
2824
2825 if (u->cacheable) {
2826 time_t now, valid;
2827
2828 now = ngx_time()ngx_cached_time->sec;
2829
2830 valid = r->cache->valid_sec;
2831
2832 if (valid == 0) {
2833 valid = ngx_http_file_cache_valid(u->conf->cache_valid,
2834 u->headers_in.status_n);
2835 if (valid) {
2836 r->cache->valid_sec = now + valid;
2837 }
2838 }
2839
2840 if (valid) {
2841 r->cache->date = now;
2842 r->cache->body_start = (u_short) (u->buffer.pos - u->buffer.start);
2843
2844 if (u->headers_in.status_n == NGX_HTTP_OK200
2845 || u->headers_in.status_n == NGX_HTTP_PARTIAL_CONTENT206)
2846 {
2847 r->cache->last_modified = u->headers_in.last_modified_time;
2848
2849 if (u->headers_in.etag) {
2850 r->cache->etag = u->headers_in.etag->value;
2851
2852 } else {
2853 ngx_str_null(&r->cache->etag)(&r->cache->etag)->len = 0; (&r->cache->
etag)->data = ((void*)0)
;
2854 }
2855
2856 } else {
2857 r->cache->last_modified = -1;
2858 ngx_str_null(&r->cache->etag)(&r->cache->etag)->len = 0; (&r->cache->
etag)->data = ((void*)0)
;
2859 }
2860
2861 if (ngx_http_file_cache_set_header(r, u->buffer.start) != NGX_OK0) {
2862 ngx_http_upstream_finalize_request(r, u, NGX_ERROR-1);
2863 return;
2864 }
2865
2866 } else {
2867 u->cacheable = 0;
2868 }
2869 }
2870
2871 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
2872 "http cacheable: %d", u->cacheable);
2873
2874 if (u->cacheable == 0 && r->cache) {
2875 ngx_http_file_cache_free(r->cache, u->pipe->temp_file);
2876 }
2877
2878 if (r->header_only && !u->cacheable && !u->store) {
2879 ngx_http_upstream_finalize_request(r, u, 0);
2880 return;
2881 }
2882
2883#endif
2884
2885 p = u->pipe;
2886
2887 p->output_filter = ngx_http_upstream_output_filter;
2888 p->output_ctx = r;
2889 p->tag = u->output.tag;
2890 p->bufs = u->conf->bufs;
2891 p->busy_size = u->conf->busy_buffers_size;
2892 p->upstream = u->peer.connection;
2893 p->downstream = c;
2894 p->pool = r->pool;
2895 p->log = c->log;
2896 p->limit_rate = u->conf->limit_rate;
2897 p->start_sec = ngx_time()ngx_cached_time->sec;
2898
2899 p->cacheable = u->cacheable || u->store;
2900
2901 p->temp_file = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t));
2902 if (p->temp_file == NULL((void*)0)) {
2903 ngx_http_upstream_finalize_request(r, u, NGX_ERROR-1);
2904 return;
2905 }
2906
2907 p->temp_file->file.fd = NGX_INVALID_FILE-1;
2908 p->temp_file->file.log = c->log;
2909 p->temp_file->path = u->conf->temp_path;
2910 p->temp_file->pool = r->pool;
2911
2912 if (p->cacheable) {
2913 p->temp_file->persistent = 1;
2914
2915#if (NGX_HTTP_CACHE1)
2916 if (r->cache && r->cache->file_cache->temp_path) {
2917 p->temp_file->path = r->cache->file_cache->temp_path;
2918 }
2919#endif
2920
2921 } else {
2922 p->temp_file->log_level = NGX_LOG_WARN5;
2923 p->temp_file->warn = "an upstream response is buffered "
2924 "to a temporary file";
2925 }
2926
2927 p->max_temp_file_size = u->conf->max_temp_file_size;
2928 p->temp_file_write_size = u->conf->temp_file_write_size;
2929
2930#if (NGX_THREADS)
2931 if (clcf->aio == NGX_HTTP_AIO_THREADS2 && clcf->aio_write) {
2932 p->thread_handler = ngx_http_upstream_thread_handler;
2933 p->thread_ctx = r;
2934 }
2935#endif
2936
2937 p->preread_bufs = ngx_alloc_chain_link(r->pool);
2938 if (p->preread_bufs == NULL((void*)0)) {
2939 ngx_http_upstream_finalize_request(r, u, NGX_ERROR-1);
2940 return;
2941 }
2942
2943 p->preread_bufs->buf = &u->buffer;
2944 p->preread_bufs->next = NULL((void*)0);
2945 u->buffer.recycled = 1;
2946
2947 p->preread_size = u->buffer.last - u->buffer.pos;
2948
2949 if (u->cacheable) {
2950
2951 p->buf_to_file = ngx_calloc_buf(r->pool)ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
2952 if (p->buf_to_file == NULL((void*)0)) {
2953 ngx_http_upstream_finalize_request(r, u, NGX_ERROR-1);
2954 return;
2955 }
2956
2957 p->buf_to_file->start = u->buffer.start;
2958 p->buf_to_file->pos = u->buffer.start;
2959 p->buf_to_file->last = u->buffer.pos;
2960 p->buf_to_file->temporary = 1;
2961 }
2962
2963 if (ngx_event_flags & NGX_USE_IOCP_EVENT0x00000200) {
2964 /* the posted aio operation may corrupt a shadow buffer */
2965 p->single_buf = 1;
2966 }
2967
2968 /* TODO: p->free_bufs = 0 if use ngx_create_chain_of_bufs() */
2969 p->free_bufs = 1;
2970
2971 /*
2972 * event_pipe would do u->buffer.last += p->preread_size
2973 * as though these bytes were read
2974 */
2975 u->buffer.last = u->buffer.pos;
2976
2977 if (u->conf->cyclic_temp_file) {
2978
2979 /*
2980 * we need to disable the use of sendfile() if we use cyclic temp file
2981 * because the writing a new data may interfere with sendfile()
2982 * that uses the same kernel file pages (at least on FreeBSD)
2983 */
2984
2985 p->cyclic_temp_file = 1;
2986 c->sendfile = 0;
2987
2988 } else {
2989 p->cyclic_temp_file = 0;
2990 }
2991
2992 p->read_timeout = u->conf->read_timeout;
2993 p->send_timeout = clcf->send_timeout;
2994 p->send_lowat = clcf->send_lowat;
2995
2996 p->length = -1;
2997
2998 if (u->input_filter_init
2999 && u->input_filter_init(p->input_ctx) != NGX_OK0)
3000 {
3001 ngx_http_upstream_finalize_request(r, u, NGX_ERROR-1);
3002 return;
3003 }
3004
3005 u->read_event_handler = ngx_http_upstream_process_upstream;
3006 r->write_event_handler = ngx_http_upstream_process_downstream;
3007
3008 ngx_http_upstream_process_upstream(r, u);
3009}
3010
3011
3012static void
3013ngx_http_upstream_upgrade(ngx_http_request_t *r, ngx_http_upstream_t *u)
3014{
3015 int tcp_nodelay;
3016 ngx_connection_t *c;
3017 ngx_http_core_loc_conf_t *clcf;
3018
3019 c = r->connection;
3020 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module)(r)->loc_conf[ngx_http_core_module.ctx_index];
3021
3022 /* TODO: prevent upgrade if not requested or not possible */
3023
3024 r->keepalive = 0;
3025 c->log->action = "proxying upgraded connection";
3026
3027 u->read_event_handler = ngx_http_upstream_upgraded_read_upstream;
3028 u->write_event_handler = ngx_http_upstream_upgraded_write_upstream;
3029 r->read_event_handler = ngx_http_upstream_upgraded_read_downstream;
3030 r->write_event_handler = ngx_http_upstream_upgraded_write_downstream;
3031
3032 if (clcf->tcp_nodelay) {
3033 tcp_nodelay = 1;
3034
3035 if (c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) {
3036 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay");
3037
3038 if (setsockopt(c->fd, IPPROTO_TCPIPPROTO_TCP, TCP_NODELAY1,
3039 (const void *) &tcp_nodelay, sizeof(int)) == -1)
3040 {
3041 ngx_connection_error(c, ngx_socket_errno(*__errno_location ()),
3042 "setsockopt(TCP_NODELAY) failed");
3043 ngx_http_upstream_finalize_request(r, u, NGX_ERROR-1);
3044 return;
3045 }
3046
3047 c->tcp_nodelay = NGX_TCP_NODELAY_SET;
3048 }
3049
3050 if (u->peer.connection->tcp_nodelay == NGX_TCP_NODELAY_UNSET) {
3051 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, u->peer.connection->log, 0,
3052 "tcp_nodelay");
3053
3054 if (setsockopt(u->peer.connection->fd, IPPROTO_TCPIPPROTO_TCP, TCP_NODELAY1,
3055 (const void *) &tcp_nodelay, sizeof(int)) == -1)
3056 {
3057 ngx_connection_error(u->peer.connection, ngx_socket_errno(*__errno_location ()),
3058 "setsockopt(TCP_NODELAY) failed");
3059 ngx_http_upstream_finalize_request(r, u, NGX_ERROR-1);
3060 return;
3061 }
3062
3063 u->peer.connection->tcp_nodelay = NGX_TCP_NODELAY_SET;
3064 }
3065 }
3066
3067 if (ngx_http_send_special(r, NGX_HTTP_FLUSH2) == NGX_ERROR-1) {
3068 ngx_http_upstream_finalize_request(r, u, NGX_ERROR-1);
3069 return;
3070 }
3071
3072 if (u->peer.connection->read->ready
3073 || u->buffer.pos != u->buffer.last)
3074 {
3075 ngx_post_event(c->read, &ngx_posted_events)if (!(c->read)->posted) { (c->read)->posted = 1; (
&(c->read)->queue)->prev = (&ngx_posted_events
)->prev; (&(c->read)->queue)->prev->next =
&(c->read)->queue; (&(c->read)->queue)->
next = &ngx_posted_events; (&ngx_posted_events)->prev
= &(c->read)->queue; ; } else { ; }
;
3076 ngx_http_upstream_process_upgraded(r, 1, 1);
3077 return;
3078 }
3079
3080 ngx_http_upstream_process_upgraded(r, 0, 1);
3081}
3082
3083
3084static void
3085ngx_http_upstream_upgraded_read_downstream(ngx_http_request_t *r)
3086{
3087 ngx_http_upstream_process_upgraded(r, 0, 0);
3088}
3089
3090
3091static void
3092ngx_http_upstream_upgraded_write_downstream(ngx_http_request_t *r)
3093{
3094 ngx_http_upstream_process_upgraded(r, 1, 1);
3095}
3096
3097
3098static void
3099ngx_http_upstream_upgraded_read_upstream(ngx_http_request_t *r,
3100 ngx_http_upstream_t *u)
3101{
3102 ngx_http_upstream_process_upgraded(r, 1, 0);
3103}
3104
3105
3106static void
3107ngx_http_upstream_upgraded_write_upstream(ngx_http_request_t *r,
3108 ngx_http_upstream_t *u)
3109{
3110 ngx_http_upstream_process_upgraded(r, 0, 1);
3111}
3112
3113
3114static void
3115ngx_http_upstream_process_upgraded(ngx_http_request_t *r,
3116 ngx_uint_t from_upstream, ngx_uint_t do_write)
3117{
3118 size_t size;
3119 ssize_t n;
3120 ngx_buf_t *b;
3121 ngx_connection_t *c, *downstream, *upstream, *dst, *src;
3122 ngx_http_upstream_t *u;
3123 ngx_http_core_loc_conf_t *clcf;
3124
3125 c = r->connection;
3126 u = r->upstream;
3127
3128 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
3129 "http upstream process upgraded, fu:%ui", from_upstream);
3130
3131 downstream = c;
3132 upstream = u->peer.connection;
3133
3134 if (downstream->write->timedout) {
3135 c->timedout = 1;
3136 ngx_connection_error(c, NGX_ETIMEDOUT110, "client timed out");
3137 ngx_http_upstream_finalize_request(r, u, NGX_HTTP_REQUEST_TIME_OUT408);
3138 return;
3139 }
3140
3141 if (upstream->read->timedout || upstream->write->timedout) {
3142 ngx_connection_error(c, NGX_ETIMEDOUT110, "upstream timed out");
3143 ngx_http_upstream_finalize_request(r, u, NGX_HTTP_GATEWAY_TIME_OUT504);
3144 return;
3145 }
3146
3147 if (from_upstream) {
3148 src = upstream;
3149 dst = downstream;
3150 b = &u->buffer;
3151
3152 } else {
3153 src = downstream;
3154 dst = upstream;
3155 b = &u->from_client;
3156
3157 if (r->header_in->last > r->header_in->pos) {
3158 b = r->header_in;
3159 b->end = b->last;
3160 do_write = 1;
3161 }
3162
3163 if (b->start == NULL((void*)0)) {
3164 b->start = ngx_palloc(r->pool, u->conf->buffer_size);
3165 if (b->start == NULL((void*)0)) {
3166 ngx_http_upstream_finalize_request(r, u, NGX_ERROR-1);
3167 return;
3168 }
3169
3170 b->pos = b->start;
3171 b->last = b->start;
3172 b->end = b->start + u->conf->buffer_size;
3173 b->temporary = 1;
3174 b->tag = u->output.tag;
3175 }
3176 }
3177
3178 for ( ;; ) {
3179
3180 if (do_write) {
3181
3182 size = b->last - b->pos;
3183
3184 if (size && dst->write->ready) {
3185
3186 n = dst->send(dst, b->pos, size);
3187
3188 if (n == NGX_ERROR-1) {
3189 ngx_http_upstream_finalize_request(r, u, NGX_ERROR-1);
3190 return;
3191 }
3192
3193 if (n > 0) {
3194 b->pos += n;
3195
3196 if (b->pos == b->last) {
3197 b->pos = b->start;
3198 b->last = b->start;
3199 }
3200 }
3201 }
3202 }
3203
3204 size = b->end - b->last;
3205
3206 if (size && src->read->ready) {
3207
3208 n = src->recv(src, b->last, size);
3209
3210 if (n == NGX_AGAIN-2 || n == 0) {
3211 break;
3212 }
3213
3214 if (n > 0) {
3215 do_write = 1;
3216 b->last += n;
3217
3218 continue;
3219 }
3220
3221 if (n == NGX_ERROR-1) {
3222 src->read->eof = 1;
3223 }
3224 }
3225
3226 break;
3227 }
3228
3229 if ((upstream->read->eof && u->buffer.pos == u->buffer.last)
3230 || (downstream->read->eof && u->from_client.pos == u->from_client.last)
3231 || (downstream->read->eof && upstream->read->eof))
3232 {
3233 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
3234 "http upstream upgraded done");
3235 ngx_http_upstream_finalize_request(r, u, 0);
3236 return;
3237 }
3238
3239 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module)(r)->loc_conf[ngx_http_core_module.ctx_index];
3240
3241 if (ngx_handle_write_event(upstream->write, u->conf->send_lowat)
3242 != NGX_OK0)
3243 {
3244 ngx_http_upstream_finalize_request(r, u, NGX_ERROR-1);
3245 return;
3246 }
3247
3248 if (upstream->write->active && !upstream->write->ready) {
3249 ngx_add_timerngx_event_add_timer(upstream->write, u->conf->send_timeout);
3250
3251 } else if (upstream->write->timer_set) {
3252 ngx_del_timerngx_event_del_timer(upstream->write);
3253 }
3254
3255 if (ngx_handle_read_event(upstream->read, 0) != NGX_OK0) {
3256 ngx_http_upstream_finalize_request(r, u, NGX_ERROR-1);
3257 return;
3258 }
3259
3260 if (upstream->read->active && !upstream->read->ready) {
3261 ngx_add_timerngx_event_add_timer(upstream->read, u->conf->read_timeout);
3262
3263 } else if (upstream->read->timer_set) {
3264 ngx_del_timerngx_event_del_timer(upstream->read);
3265 }
3266
3267 if (ngx_handle_write_event(downstream->write, clcf->send_lowat)
3268 != NGX_OK0)
3269 {
3270 ngx_http_upstream_finalize_request(r, u, NGX_ERROR-1);
3271 return;
3272 }
3273
3274 if (ngx_handle_read_event(downstream->read, 0) != NGX_OK0) {
3275 ngx_http_upstream_finalize_request(r, u, NGX_ERROR-1);
3276 return;
3277 }
3278
3279 if (downstream->write->active && !downstream->write->ready) {
3280 ngx_add_timerngx_event_add_timer(downstream->write, clcf->send_timeout);
3281
3282 } else if (downstream->write->timer_set) {
3283 ngx_del_timerngx_event_del_timer(downstream->write);
3284 }
3285}
3286
3287
3288static void
3289ngx_http_upstream_process_non_buffered_downstream(ngx_http_request_t *r)
3290{
3291 ngx_event_t *wev;
3292 ngx_connection_t *c;
3293 ngx_http_upstream_t *u;
3294
3295 c = r->connection;
3296 u = r->upstream;
3297 wev = c->write;
3298
3299 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
3300 "http upstream process non buffered downstream");
3301
3302 c->log->action = "sending to client";
3303
3304 if (wev->timedout) {
3305 c->timedout = 1;
3306 ngx_connection_error(c, NGX_ETIMEDOUT110, "client timed out");
3307 ngx_http_upstream_finalize_request(r, u, NGX_HTTP_REQUEST_TIME_OUT408);
3308 return;
3309 }
3310
3311 ngx_http_upstream_process_non_buffered_request(r, 1);
3312}
3313
3314
3315static void
3316ngx_http_upstream_process_non_buffered_upstream(ngx_http_request_t *r,
3317 ngx_http_upstream_t *u)
3318{
3319 ngx_connection_t *c;
3320
3321 c = u->peer.connection;
3322
3323 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
3324 "http upstream process non buffered upstream");
3325
3326 c->log->action = "reading upstream";
3327
3328 if (c->read->timedout) {
3329 ngx_connection_error(c, NGX_ETIMEDOUT110, "upstream timed out");
3330 ngx_http_upstream_finalize_request(r, u, NGX_HTTP_GATEWAY_TIME_OUT504);
3331 return;
3332 }
3333
3334 ngx_http_upstream_process_non_buffered_request(r, 0);
3335}
3336
3337
3338static void
3339ngx_http_upstream_process_non_buffered_request(ngx_http_request_t *r,
3340 ngx_uint_t do_write)
3341{
3342 size_t size;
3343 ssize_t n;
3344 ngx_buf_t *b;
3345 ngx_int_t rc;
3346 ngx_connection_t *downstream, *upstream;
3347 ngx_http_upstream_t *u;
3348 ngx_http_core_loc_conf_t *clcf;
3349
3350 u = r->upstream;
3351 downstream = r->connection;
3352 upstream = u->peer.connection;
3353
3354 b = &u->buffer;
3355
3356 do_write = do_write || u->length == 0;
3357
3358 for ( ;; ) {
3359
3360 if (do_write) {
3361
3362 if (u->out_bufs || u->busy_bufs) {
3363 rc = ngx_http_output_filter(r, u->out_bufs);
3364
3365 if (rc == NGX_ERROR-1) {
3366 ngx_http_upstream_finalize_request(r, u, NGX_ERROR-1);
3367 return;
3368 }
3369
3370 ngx_chain_update_chains(r->pool, &u->free_bufs, &u->busy_bufs,
3371 &u->out_bufs, u->output.tag);
3372 }
3373
3374 if (u->busy_bufs == NULL((void*)0)) {
3375
3376 if (u->length == 0
3377 || (upstream->read->eof && u->length == -1))
3378 {
3379 ngx_http_upstream_finalize_request(r, u, 0);
3380 return;
3381 }
3382
3383 if (upstream->read->eof) {
3384 ngx_log_error(NGX_LOG_ERR, upstream->log, 0,if ((upstream->log)->log_level >= 4) ngx_log_error_core
(4, upstream->log, 0, "upstream prematurely closed connection"
)
3385 "upstream prematurely closed connection")if ((upstream->log)->log_level >= 4) ngx_log_error_core
(4, upstream->log, 0, "upstream prematurely closed connection"
)
;
3386
3387 ngx_http_upstream_finalize_request(r, u,
3388 NGX_HTTP_BAD_GATEWAY502);
3389 return;
3390 }
3391
3392 if (upstream->read->error) {
3393 ngx_http_upstream_finalize_request(r, u,
3394 NGX_HTTP_BAD_GATEWAY502);
3395 return;
3396 }
3397
3398 b->pos = b->start;
3399 b->last = b->start;
3400 }
3401 }
3402
3403 size = b->end - b->last;
3404
3405 if (size && upstream->read->ready) {
3406
3407 n = upstream->recv(upstream, b->last, size);
3408
3409 if (n == NGX_AGAIN-2) {
3410 break;
3411 }
3412
3413 if (n > 0) {
3414 u->state->response_length += n;
3415
3416 if (u->input_filter(u->input_filter_ctx, n) == NGX_ERROR-1) {
3417 ngx_http_upstream_finalize_request(r, u, NGX_ERROR-1);
3418 return;
3419 }
3420 }
3421
3422 do_write = 1;
3423
3424 continue;
3425 }
3426
3427 break;
3428 }
3429
3430 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module)(r)->loc_conf[ngx_http_core_module.ctx_index];
3431
3432 if (downstream->data == r) {
3433 if (ngx_handle_write_event(downstream->write, clcf->send_lowat)
3434 != NGX_OK0)
3435 {
3436 ngx_http_upstream_finalize_request(r, u, NGX_ERROR-1);
3437 return;
3438 }
3439 }
3440
3441 if (downstream->write->active && !downstream->write->ready) {
3442 ngx_add_timerngx_event_add_timer(downstream->write, clcf->send_timeout);
3443
3444 } else if (downstream->write->timer_set) {
3445 ngx_del_timerngx_event_del_timer(downstream->write);
3446 }
3447
3448 if (ngx_handle_read_event(upstream->read, 0) != NGX_OK0) {
3449 ngx_http_upstream_finalize_request(r, u, NGX_ERROR-1);
3450 return;
3451 }
3452
3453 if (upstream->read->active && !upstream->read->ready) {
3454 ngx_add_timerngx_event_add_timer(upstream->read, u->conf->read_timeout);
3455
3456 } else if (upstream->read->timer_set) {
3457 ngx_del_timerngx_event_del_timer(upstream->read);
3458 }
3459}
3460
3461
3462static ngx_int_t
3463ngx_http_upstream_non_buffered_filter_init(void *data)
3464{
3465 return NGX_OK0;
3466}
3467
3468
3469static ngx_int_t
3470ngx_http_upstream_non_buffered_filter(void *data, ssize_t bytes)
3471{
3472 ngx_http_request_t *r = data;
3473
3474 ngx_buf_t *b;
3475 ngx_chain_t *cl, **ll;
3476 ngx_http_upstream_t *u;
3477
3478 u = r->upstream;
3479
3480 for (cl = u->out_bufs, ll = &u->out_bufs; cl; cl = cl->next) {
3481 ll = &cl->next;
3482 }
3483
3484 cl = ngx_chain_get_free_buf(r->pool, &u->free_bufs);
3485 if (cl == NULL((void*)0)) {
3486 return NGX_ERROR-1;
3487 }
3488
3489 *ll = cl;
3490
3491 cl->buf->flush = 1;
3492 cl->buf->memory = 1;
3493
3494 b = &u->buffer;
3495
3496 cl->buf->pos = b->last;
3497 b->last += bytes;
3498 cl->buf->last = b->last;
3499 cl->buf->tag = u->output.tag;
3500
3501 if (u->length == -1) {
3502 return NGX_OK0;
3503 }
3504
3505 u->length -= bytes;
3506
3507 return NGX_OK0;
3508}
3509
3510
3511#if (NGX_THREADS)
3512
3513static ngx_int_t
3514ngx_http_upstream_thread_handler(ngx_thread_task_t *task, ngx_file_t *file)
3515{
3516 ngx_str_t name;
3517 ngx_event_pipe_t *p;
3518 ngx_thread_pool_t *tp;
3519 ngx_http_request_t *r;
3520 ngx_http_core_loc_conf_t *clcf;
3521
3522 r = file->thread_ctx;
3523 p = r->upstream->pipe;
3524
3525 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module)(r)->loc_conf[ngx_http_core_module.ctx_index];
3526 tp = clcf->thread_pool;
3527
3528 if (tp == NULL((void*)0)) {
3529 if (ngx_http_complex_value(r, clcf->thread_pool_value, &name)
3530 != NGX_OK0)
3531 {
3532 return NGX_ERROR-1;
3533 }
3534
3535 tp = ngx_thread_pool_get((ngx_cycle_t *) ngx_cycle, &name);
3536
3537 if (tp == NULL((void*)0)) {
3538 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, "thread pool \"%V\" not found"
, &name)
3539 "thread pool \"%V\" not found", &name)if ((r->connection->log)->log_level >= 4) ngx_log_error_core
(4, r->connection->log, 0, "thread pool \"%V\" not found"
, &name)
;
3540 return NGX_ERROR-1;
3541 }
3542 }
3543
3544 task->event.data = r;
3545 task->event.handler = ngx_http_upstream_thread_event_handler;
3546
3547 if (ngx_thread_task_post(tp, task) != NGX_OK0) {
3548 return NGX_ERROR-1;
3549 }
3550
3551 r->main->blocked++;
3552 r->aio = 1;
3553 p->aio = 1;
3554
3555 return NGX_OK0;
3556}
3557
3558
3559static void
3560ngx_http_upstream_thread_event_handler(ngx_event_t *ev)
3561{
3562 ngx_connection_t *c;
3563 ngx_http_request_t *r;
3564
3565 r = ev->data;
3566 c = r->connection;
3567
3568 ngx_http_set_log_request(c->log, r)((ngx_http_log_ctx_t *) c->log->data)->current_request
= r
;
3569
3570 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
3571 "http upstream thread: \"%V?%V\"", &r->uri, &r->args);
3572
3573 r->main->blocked--;
3574 r->aio = 0;
3575
3576 r->write_event_handler(r);
3577
3578 ngx_http_run_posted_requests(c);
3579}
3580
3581#endif
3582
3583
3584static ngx_int_t
3585ngx_http_upstream_output_filter(void *data, ngx_chain_t *chain)
3586{
3587 ngx_int_t rc;
3588 ngx_event_pipe_t *p;
3589 ngx_http_request_t *r;
3590
3591 r = data;
3592 p = r->upstream->pipe;
3593
3594 rc = ngx_http_output_filter(r, chain);
3595
3596 p->aio = r->aio;
3597
3598 return rc;
3599}
3600
3601
3602static void
3603ngx_http_upstream_process_downstream(ngx_http_request_t *r)
3604{
3605 ngx_event_t *wev;
3606 ngx_connection_t *c;
3607 ngx_event_pipe_t *p;
3608 ngx_http_upstream_t *u;
3609
3610 c = r->connection;
3611 u = r->upstream;
3612 p = u->pipe;
3613 wev = c->write;
3614
3615 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
3616 "http upstream process downstream");
3617
3618 c->log->action = "sending to client";
3619
3620#if (NGX_THREADS)
3621 p->aio = r->aio;
3622#endif
3623
3624 if (wev->timedout) {
3625
3626 if (wev->delayed) {
3627
3628 wev->timedout = 0;
3629 wev->delayed = 0;
3630
3631 if (!wev->ready) {
3632 ngx_add_timerngx_event_add_timer(wev, p->send_timeout);
3633
3634 if (ngx_handle_write_event(wev, p->send_lowat) != NGX_OK0) {
3635 ngx_http_upstream_finalize_request(r, u, NGX_ERROR-1);
3636 }
3637
3638 return;
3639 }
3640
3641 if (ngx_event_pipe(p, wev->write) == NGX_ABORT-6) {
3642 ngx_http_upstream_finalize_request(r, u, NGX_ERROR-1);
3643 return;
3644 }
3645
3646 } else {
3647 p->downstream_error = 1;
3648 c->timedout = 1;
3649 ngx_connection_error(c, NGX_ETIMEDOUT110, "client timed out");
3650 }
3651
3652 } else {
3653
3654 if (wev->delayed) {
3655
3656 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
3657 "http downstream delayed");
3658
3659 if (ngx_handle_write_event(wev, p->send_lowat) != NGX_OK0) {
3660 ngx_http_upstream_finalize_request(r, u, NGX_ERROR-1);
3661 }
3662
3663 return;
3664 }
3665
3666 if (ngx_event_pipe(p, 1) == NGX_ABORT-6) {
3667 ngx_http_upstream_finalize_request(r, u, NGX_ERROR-1);
3668 return;
3669 }
3670 }
3671
3672 ngx_http_upstream_process_request(r, u);
3673}
3674
3675
3676static void
3677ngx_http_upstream_process_upstream(ngx_http_request_t *r,
3678 ngx_http_upstream_t *u)
3679{
3680 ngx_event_t *rev;
3681 ngx_event_pipe_t *p;
3682 ngx_connection_t *c;
3683
3684 c = u->peer.connection;
3685 p = u->pipe;
3686 rev = c->read;
3687
3688 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
3689 "http upstream process upstream");
3690
3691 c->log->action = "reading upstream";
3692
3693 if (rev->timedout) {
3694
3695 if (rev->delayed) {
3696
3697 rev->timedout = 0;
3698 rev->delayed = 0;
3699
3700 if (!rev->ready) {
3701 ngx_add_timerngx_event_add_timer(rev, p->read_timeout);
3702
3703 if (ngx_handle_read_event(rev, 0) != NGX_OK0) {
3704 ngx_http_upstream_finalize_request(r, u, NGX_ERROR-1);
3705 }
3706
3707 return;
3708 }
3709
3710 if (ngx_event_pipe(p, 0) == NGX_ABORT-6) {
3711 ngx_http_upstream_finalize_request(r, u, NGX_ERROR-1);
3712 return;
3713 }
3714
3715 } else {
3716 p->upstream_error = 1;
3717 ngx_connection_error(c, NGX_ETIMEDOUT110, "upstream timed out");
3718 }
3719
3720 } else {
3721
3722 if (rev->delayed) {
3723
3724 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
3725 "http upstream delayed");
3726
3727 if (ngx_handle_read_event(rev, 0) != NGX_OK0) {
3728 ngx_http_upstream_finalize_request(r, u, NGX_ERROR-1);
3729 }
3730
3731 return;
3732 }
3733
3734 if (ngx_event_pipe(p, 0) == NGX_ABORT-6) {
3735 ngx_http_upstream_finalize_request(r, u, NGX_ERROR-1);
3736 return;
3737 }
3738 }
3739
3740 ngx_http_upstream_process_request(r, u);
3741}
3742
3743
3744static void
3745ngx_http_upstream_process_request(ngx_http_request_t *r,
3746 ngx_http_upstream_t *u)
3747{
3748 ngx_temp_file_t *tf;
3749 ngx_event_pipe_t *p;
3750
3751 p = u->pipe;
3752
3753#if (NGX_THREADS)
3754 if (p->writing) {
3755 return;
3756 }
3757#endif
3758
3759 if (u->peer.connection) {
3760
3761 if (u->store) {
3762
3763 if (p->upstream_eof || p->upstream_done) {
3764
3765 tf = p->temp_file;
3766
3767 if (u->headers_in.status_n == NGX_HTTP_OK200
3768 && (p->upstream_done || p->length == -1)
3769 && (u->headers_in.content_length_n == -1
3770 || u->headers_in.content_length_n == tf->offset))
3771 {
3772 ngx_http_upstream_store(r, u);
3773 }
3774 }
3775 }
3776
3777#if (NGX_HTTP_CACHE1)
3778
3779 if (u->cacheable) {
3780
3781 if (p->upstream_done) {
3782 ngx_http_file_cache_update(r, p->temp_file);
3783
3784 } else if (p->upstream_eof) {
3785
3786 tf = p->temp_file;
3787
3788 if (p->length == -1
3789 && (u->headers_in.content_length_n == -1
3790 || u->headers_in.content_length_n
3791 == tf->offset - (off_t) r->cache->body_start))
3792 {
3793 ngx_http_file_cache_update(r, tf);
3794
3795 } else {
3796 ngx_http_file_cache_free(r->cache, tf);
3797 }
3798
3799 } else if (p->upstream_error) {
3800 ngx_http_file_cache_free(r->cache, p->temp_file);
3801 }
3802 }
3803
3804#endif
3805
3806 if (p->upstream_done || p->upstream_eof || p->upstream_error) {
3807 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
3808 "http upstream exit: %p", p->out);
3809
3810 if (p->upstream_done
3811 || (p->upstream_eof && p->length == -1))
3812 {
3813 ngx_http_upstream_finalize_request(r, u, 0);
3814 return;
3815 }
3816
3817 if (p->upstream_eof) {
3818 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, "upstream prematurely closed connection"
)
3819 "upstream prematurely closed connection")if ((r->connection->log)->log_level >= 4) ngx_log_error_core
(4, r->connection->log, 0, "upstream prematurely closed connection"
)
;
3820 }
3821
3822 ngx_http_upstream_finalize_request(r, u, NGX_HTTP_BAD_GATEWAY502);
3823 return;
3824 }
3825 }
3826
3827 if (p->downstream_error) {
3828 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
3829 "http upstream downstream error");
3830
3831 if (!u->cacheable && !u->store && u->peer.connection) {
3832 ngx_http_upstream_finalize_request(r, u, NGX_ERROR-1);
3833 }
3834 }
3835}
3836
3837
3838static void
3839ngx_http_upstream_store(ngx_http_request_t *r, ngx_http_upstream_t *u)
3840{
3841 size_t root;
3842 time_t lm;
3843 ngx_str_t path;
3844 ngx_temp_file_t *tf;
3845 ngx_ext_rename_file_t ext;
3846
3847 tf = u->pipe->temp_file;
3848
3849 if (tf->file.fd == NGX_INVALID_FILE-1) {
3850
3851 /* create file for empty 200 response */
3852
3853 tf = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t));
3854 if (tf == NULL((void*)0)) {
3855 return;
3856 }
3857
3858 tf->file.fd = NGX_INVALID_FILE-1;
3859 tf->file.log = r->connection->log;
3860 tf->path = u->conf->temp_path;
3861 tf->pool = r->pool;
3862 tf->persistent = 1;
3863
3864 if (ngx_create_temp_file(&tf->file, tf->path, tf->pool,
3865 tf->persistent, tf->clean, tf->access)
3866 != NGX_OK0)
3867 {
3868 return;
3869 }
3870
3871 u->pipe->temp_file = tf;
3872 }
3873
3874 ext.access = u->conf->store_access;
3875 ext.path_access = u->conf->store_access;
3876 ext.time = -1;
3877 ext.create_path = 1;
3878 ext.delete_file = 1;
3879 ext.log = r->connection->log;
3880
3881 if (u->headers_in.last_modified) {
3882
3883 lm = ngx_parse_http_time(u->headers_in.last_modified->value.data,
3884 u->headers_in.last_modified->value.len);
3885
3886 if (lm != NGX_ERROR-1) {
3887 ext.time = lm;
3888 ext.fd = tf->file.fd;
3889 }
3890 }
3891
3892 if (u->conf->store_lengths == NULL((void*)0)) {
3893
3894 if (ngx_http_map_uri_to_path(r, &path, &root, 0) == NULL((void*)0)) {
3895 return;
3896 }
3897
3898 } else {
3899 if (ngx_http_script_run(r, &path, u->conf->store_lengths->elts, 0,
3900 u->conf->store_values->elts)
3901 == NULL((void*)0))
3902 {
3903 return;
3904 }
3905 }
3906
3907 path.len--;
3908
3909 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
3910 "upstream stores \"%s\" to \"%s\"",
3911 tf->file.name.data, path.data);
3912
3913 (void) ngx_ext_rename_file(&tf->file.name, &path, &ext);
3914
3915 u->store = 0;
3916}
3917
3918
3919static void
3920ngx_http_upstream_dummy_handler(ngx_http_request_t *r, ngx_http_upstream_t *u)
3921{
3922 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
3923 "http upstream dummy handler");
3924}
3925
3926
3927static void
3928ngx_http_upstream_next(ngx_http_request_t *r, ngx_http_upstream_t *u,
3929 ngx_uint_t ft_type)
3930{
3931 ngx_msec_t timeout;
3932 ngx_uint_t status, state;
3933
3934 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
3935 "http next upstream, %xi", ft_type);
3936
3937 if (u->peer.sockaddr) {
3938
3939 if (ft_type == NGX_HTTP_UPSTREAM_FT_HTTP_4030x00000100
3940 || ft_type == NGX_HTTP_UPSTREAM_FT_HTTP_4040x00000200)
3941 {
3942 state = NGX_PEER_NEXT2;
3943
3944 } else {
3945 state = NGX_PEER_FAILED4;
3946 }
3947
3948 u->peer.free(&u->peer, u->peer.data, state);
3949 u->peer.sockaddr = NULL((void*)0);
3950 }
3951
3952 if (ft_type == NGX_HTTP_UPSTREAM_FT_TIMEOUT0x00000004) {
3953 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, 110, "upstream timed out")
3954 "upstream timed out")if ((r->connection->log)->log_level >= 4) ngx_log_error_core
(4, r->connection->log, 110, "upstream timed out")
;
3955 }
3956
3957 if (u->peer.cached && ft_type == NGX_HTTP_UPSTREAM_FT_ERROR0x00000002) {
3958 /* TODO: inform balancer instead */
3959 u->peer.tries++;
3960 }
3961
3962 switch (ft_type) {
3963
3964 case NGX_HTTP_UPSTREAM_FT_TIMEOUT0x00000004:
3965 status = NGX_HTTP_GATEWAY_TIME_OUT504;
3966 break;
3967
3968 case NGX_HTTP_UPSTREAM_FT_HTTP_5000x00000010:
3969 status = NGX_HTTP_INTERNAL_SERVER_ERROR500;
3970 break;
3971
3972 case NGX_HTTP_UPSTREAM_FT_HTTP_4030x00000100:
3973 status = NGX_HTTP_FORBIDDEN403;
3974 break;
3975
3976 case NGX_HTTP_UPSTREAM_FT_HTTP_4040x00000200:
3977 status = NGX_HTTP_NOT_FOUND404;
3978 break;
3979
3980 /*
3981 * NGX_HTTP_UPSTREAM_FT_BUSY_LOCK and NGX_HTTP_UPSTREAM_FT_MAX_WAITING
3982 * never reach here
3983 */
3984
3985 default:
3986 status = NGX_HTTP_BAD_GATEWAY502;
3987 }
3988
3989 if (r->connection->error) {
3990 ngx_http_upstream_finalize_request(r, u,
3991 NGX_HTTP_CLIENT_CLOSED_REQUEST499);
3992 return;
3993 }
3994
3995 u->state->status = status;
3996
3997 timeout = u->conf->next_upstream_timeout;
3998
3999 if (u->request_sent
4000 && (r->method & (NGX_HTTP_POST0x0008|NGX_HTTP_LOCK0x1000|NGX_HTTP_PATCH0x4000)))
4001 {
4002 ft_type |= NGX_HTTP_UPSTREAM_FT_NON_IDEMPOTENT0x00002000;
4003 }
4004
4005 if (u->peer.tries == 0
4006 || ((u->conf->next_upstream & ft_type) != ft_type)
4007 || (u->request_sent && r->request_body_no_buffering)
4008 || (timeout && ngx_current_msec - u->peer.start_time >= timeout))
4009 {
4010#if (NGX_HTTP_CACHE1)
4011
4012 if (u->cache_status == NGX_HTTP_CACHE_EXPIRED3
4013 && (u->conf->cache_use_stale & ft_type))
4014 {
4015 ngx_int_t rc;
4016
4017 rc = u->reinit_request(r);
4018
4019 if (rc == NGX_OK0) {
4020 u->cache_status = NGX_HTTP_CACHE_STALE4;
4021 rc = ngx_http_upstream_cache_send(r, u);
4022 }
4023
4024 ngx_http_upstream_finalize_request(r, u, rc);
4025 return;
4026 }
4027#endif
4028
4029 ngx_http_upstream_finalize_request(r, u, status);
4030 return;
4031 }
4032
4033 if (u->peer.connection) {
4034 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
4035 "close http upstream connection: %d",
4036 u->peer.connection->fd);
4037#if (NGX_HTTP_SSL)
4038
4039 if (u->peer.connection->ssl) {
4040 u->peer.connection->ssl->no_wait_shutdown = 1;
4041 u->peer.connection->ssl->no_send_shutdown = 1;
4042
4043 (void) ngx_ssl_shutdown(u->peer.connection);
4044 }
4045#endif
4046
4047 if (u->peer.connection->pool) {
4048 ngx_destroy_pool(u->peer.connection->pool);
4049 }
4050
4051 ngx_close_connection(u->peer.connection);
4052 u->peer.connection = NULL((void*)0);
4053 }
4054
4055 ngx_http_upstream_connect(r, u);
4056}
4057
4058
4059static void
4060ngx_http_upstream_cleanup(void *data)
4061{
4062 ngx_http_request_t *r = data;
4063
4064 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
4065 "cleanup http upstream request: \"%V\"", &r->uri);
4066
4067 ngx_http_upstream_finalize_request(r, r->upstream, NGX_DONE-4);
4068}
4069
4070
4071static void
4072ngx_http_upstream_finalize_request(ngx_http_request_t *r,
4073 ngx_http_upstream_t *u, ngx_int_t rc)
4074{
4075 ngx_uint_t flush;
4076
4077 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
4078 "finalize http upstream request: %i", rc);
4079
4080 if (u->cleanup == NULL((void*)0)) {
1
Taking false branch
4081 /* the request was already finalized */
4082 ngx_http_finalize_request(r, NGX_DONE-4);
4083 return;
4084 }
4085
4086 *u->cleanup = NULL((void*)0);
4087 u->cleanup = NULL((void*)0);
4088
4089 if (u->resolved && u->resolved->ctx) {
4090 ngx_resolve_name_done(u->resolved->ctx);
4091 u->resolved->ctx = NULL((void*)0);
4092 }
4093
4094 if (u->state && u->state->response_time) {
4095 u->state->response_time = ngx_current_msec - u->state->response_time;
4096
4097 if (u->pipe && u->pipe->read_length) {
4098 u->state->response_length = u->pipe->read_length;
4099 }
4100 }
4101
4102 u->finalize_request(r, rc);
4103
4104 if (u->peer.free && u->peer.sockaddr) {
4105 u->peer.free(&u->peer, u->peer.data, 0);
4106 u->peer.sockaddr = NULL((void*)0);
4107 }
4108
4109 if (u->peer.connection) {
2
Taking false branch
4110
4111#if (NGX_HTTP_SSL)
4112
4113 /* TODO: do not shutdown persistent connection */
4114
4115 if (u->peer.connection->ssl) {
4116
4117 /*
4118 * We send the "close notify" shutdown alert to the upstream only
4119 * and do not wait its "close notify" shutdown alert.
4120 * It is acceptable according to the TLS standard.
4121 */
4122
4123 u->peer.connection->ssl->no_wait_shutdown = 1;
4124
4125 (void) ngx_ssl_shutdown(u->peer.connection);
4126 }
4127#endif
4128
4129 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
4130 "close http upstream connection: %d",
4131 u->peer.connection->fd);
4132
4133 if (u->peer.connection->pool) {
4134 ngx_destroy_pool(u->peer.connection->pool);
4135 }
4136
4137 ngx_close_connection(u->peer.connection);
4138 }
4139
4140 u->peer.connection = NULL((void*)0);
4141
4142 if (u->pipe && u->pipe->temp_file) {
3
Assuming pointer value is null
4143 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
4144 "http upstream temp fd: %d",
4145 u->pipe->temp_file->file.fd);
4146 }
4147
4148 if (u->store && u->pipe && u->pipe->temp_file
4149 && u->pipe->temp_file->file.fd != NGX_INVALID_FILE-1)
4150 {
4151 if (ngx_delete_file(u->pipe->temp_file->file.name.data)unlink((const char *) u->pipe->temp_file->file.name.
data)
4152 == NGX_FILE_ERROR-1)
4153 {
4154 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, (*__errno_location ()), "unlink()"
" \"%s\" failed", u->pipe->temp_file->file.name.data
)
4155 ngx_delete_file_n " \"%s\" failed",if ((r->connection->log)->log_level >= 3) ngx_log_error_core
(3, r->connection->log, (*__errno_location ()), "unlink()"
" \"%s\" failed", u->pipe->temp_file->file.name.data
)
4156 u->pipe->temp_file->file.name.data)if ((r->connection->log)->log_level >= 3) ngx_log_error_core
(3, r->connection->log, (*__errno_location ()), "unlink()"
" \"%s\" failed", u->pipe->temp_file->file.name.data
)
;
4157 }
4158 }
4159
4160#if (NGX_HTTP_CACHE1)
4161
4162 if (r->cache) {
4
Taking true branch
4163
4164 if (u->cacheable) {
5
Taking false branch
4165
4166 if (rc == NGX_HTTP_BAD_GATEWAY502 || rc == NGX_HTTP_GATEWAY_TIME_OUT504) {
4167 time_t valid;
4168
4169 valid = ngx_http_file_cache_valid(u->conf->cache_valid, rc);
4170
4171 if (valid) {
4172 r->cache->valid_sec = ngx_time()ngx_cached_time->sec + valid;
4173 r->cache->error = rc;
4174 }
4175 }
4176 }
4177
4178 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')
4179 }
4180
4181#endif
4182
4183 if (r->subrequest_in_memory
4184 && u->headers_in.status_n >= NGX_HTTP_SPECIAL_RESPONSE300)
4185 {
4186 u->buffer.last = u->buffer.pos;
4187 }
4188
4189 if (rc == NGX_DECLINED-5) {
4190 return;
4191 }
4192
4193 r->connection->log->action = "sending to client";
4194
4195 if (!u->header_sent
4196 || rc == NGX_HTTP_REQUEST_TIME_OUT408
4197 || rc == NGX_HTTP_CLIENT_CLOSED_REQUEST499
4198 || (u->pipe && u->pipe->downstream_error))
4199 {
4200 ngx_http_finalize_request(r, rc);
4201 return;
4202 }
4203
4204 flush = 0;
4205
4206 if (rc >= NGX_HTTP_SPECIAL_RESPONSE300) {
4207 rc = NGX_ERROR-1;
4208 flush = 1;
4209 }
4210
4211 if (r->header_only) {
4212 ngx_http_finalize_request(r, rc);
4213 return;
4214 }
4215
4216 if (rc == 0) {
4217 rc = ngx_http_send_special(r, NGX_HTTP_LAST1);
4218
4219 } else if (flush) {
4220 r->keepalive = 0;
4221 rc = ngx_http_send_special(r, NGX_HTTP_FLUSH2);
4222 }
4223
4224 ngx_http_finalize_request(r, rc);
4225}
4226
4227
4228static ngx_int_t
4229ngx_http_upstream_process_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
4230 ngx_uint_t offset)
4231{
4232 ngx_table_elt_t **ph;
4233
4234 ph = (ngx_table_elt_t **) ((char *) &r->upstream->headers_in + offset);
4235
4236 if (*ph == NULL((void*)0)) {
4237 *ph = h;
4238 }
4239
4240 return NGX_OK0;
4241}
4242
4243
4244static ngx_int_t
4245ngx_http_upstream_ignore_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
4246 ngx_uint_t offset)
4247{
4248 return NGX_OK0;
4249}
4250
4251
4252static ngx_int_t
4253ngx_http_upstream_process_content_length(ngx_http_request_t *r,
4254 ngx_table_elt_t *h, ngx_uint_t offset)
4255{
4256 ngx_http_upstream_t *u;
4257
4258 u = r->upstream;
4259
4260 u->headers_in.content_length = h;
4261 u->headers_in.content_length_n = ngx_atoof(h->value.data, h->value.len);
4262
4263 return NGX_OK0;
4264}
4265
4266
4267static ngx_int_t
4268ngx_http_upstream_process_last_modified(ngx_http_request_t *r,
4269 ngx_table_elt_t *h, ngx_uint_t offset)
4270{
4271 ngx_http_upstream_t *u;
4272
4273 u = r->upstream;
4274
4275 u->headers_in.last_modified = h;
4276
4277#if (NGX_HTTP_CACHE1)
4278
4279 if (u->cacheable) {
4280 u->headers_in.last_modified_time = ngx_parse_http_time(h->value.data,
4281 h->value.len);
4282 }
4283
4284#endif
4285
4286 return NGX_OK0;
4287}
4288
4289
4290static ngx_int_t
4291ngx_http_upstream_process_set_cookie(ngx_http_request_t *r, ngx_table_elt_t *h,
4292 ngx_uint_t offset)
4293{
4294 ngx_array_t *pa;
4295 ngx_table_elt_t **ph;
4296 ngx_http_upstream_t *u;
4297
4298 u = r->upstream;
4299 pa = &u->headers_in.cookies;
4300
4301 if (pa->elts == NULL((void*)0)) {
4302 if (ngx_array_init(pa, r->pool, 1, sizeof(ngx_table_elt_t *)) != NGX_OK0)
4303 {
4304 return NGX_ERROR-1;
4305 }
4306 }
4307
4308 ph = ngx_array_push(pa);
4309 if (ph == NULL((void*)0)) {
4310 return NGX_ERROR-1;
4311 }
4312
4313 *ph = h;
4314
4315#if (NGX_HTTP_CACHE1)
4316 if (!(u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_SET_COOKIE0x00000020)) {
4317 u->cacheable = 0;
4318 }
4319#endif
4320
4321 return NGX_OK0;
4322}
4323
4324
4325static ngx_int_t
4326ngx_http_upstream_process_cache_control(ngx_http_request_t *r,
4327 ngx_table_elt_t *h, ngx_uint_t offset)
4328{
4329 ngx_array_t *pa;
4330 ngx_table_elt_t **ph;
4331 ngx_http_upstream_t *u;
4332
4333 u = r->upstream;
4334 pa = &u->headers_in.cache_control;
4335
4336 if (pa->elts == NULL((void*)0)) {
4337 if (ngx_array_init(pa, r->pool, 2, sizeof(ngx_table_elt_t *)) != NGX_OK0)
4338 {
4339 return NGX_ERROR-1;
4340 }
4341 }
4342
4343 ph = ngx_array_push(pa);
4344 if (ph == NULL((void*)0)) {
4345 return NGX_ERROR-1;
4346 }
4347
4348 *ph = h;
4349
4350#if (NGX_HTTP_CACHE1)
4351 {
4352 u_char *p, *start, *last;
4353 ngx_int_t n;
4354
4355 if (u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_CACHE_CONTROL0x00000010) {
4356 return NGX_OK0;
4357 }
4358
4359 if (r->cache == NULL((void*)0)) {
4360 return NGX_OK0;
4361 }
4362
4363 if (r->cache->valid_sec != 0 && u->headers_in.x_accel_expires != NULL((void*)0)) {
4364 return NGX_OK0;
4365 }
4366
4367 start = h->value.data;
4368 last = start + h->value.len;
4369
4370 if (ngx_strlcasestrn(start, last, (u_char *) "no-cache", 8 - 1) != NULL((void*)0)
4371 || ngx_strlcasestrn(start, last, (u_char *) "no-store", 8 - 1) != NULL((void*)0)
4372 || ngx_strlcasestrn(start, last, (u_char *) "private", 7 - 1) != NULL((void*)0))
4373 {
4374 u->cacheable = 0;
4375 return NGX_OK0;
4376 }
4377
4378 p = ngx_strlcasestrn(start, last, (u_char *) "s-maxage=", 9 - 1);
4379 offset = 9;
4380
4381 if (p == NULL((void*)0)) {
4382 p = ngx_strlcasestrn(start, last, (u_char *) "max-age=", 8 - 1);
4383 offset = 8;
4384 }
4385
4386 if (p == NULL((void*)0)) {
4387 return NGX_OK0;
4388 }
4389
4390 n = 0;
4391
4392 for (p += offset; p < last; p++) {
4393 if (*p == ',' || *p == ';' || *p == ' ') {
4394 break;
4395 }
4396
4397 if (*p >= '0' && *p <= '9') {
4398 n = n * 10 + *p - '0';
4399 continue;
4400 }
4401
4402 u->cacheable = 0;
4403 return NGX_OK0;
4404 }
4405
4406 if (n == 0) {
4407 u->cacheable = 0;
4408 return NGX_OK0;
4409 }
4410
4411 r->cache->valid_sec = ngx_time()ngx_cached_time->sec + n;
4412 }
4413#endif
4414
4415 return NGX_OK0;
4416}
4417
4418
4419static ngx_int_t
4420ngx_http_upstream_process_expires(ngx_http_request_t *r, ngx_table_elt_t *h,
4421 ngx_uint_t offset)
4422{
4423 ngx_http_upstream_t *u;
4424
4425 u = r->upstream;
4426 u->headers_in.expires = h;
4427
4428#if (NGX_HTTP_CACHE1)
4429 {
4430 time_t expires;
4431
4432 if (u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_EXPIRES0x00000008) {
4433 return NGX_OK0;
4434 }
4435
4436 if (r->cache == NULL((void*)0)) {
4437 return NGX_OK0;
4438 }
4439
4440 if (r->cache->valid_sec != 0) {
4441 return NGX_OK0;
4442 }
4443
4444 expires = ngx_parse_http_time(h->value.data, h->value.len);
4445
4446 if (expires == NGX_ERROR-1 || expires < ngx_time()ngx_cached_time->sec) {
4447 u->cacheable = 0;
4448 return NGX_OK0;
4449 }
4450
4451 r->cache->valid_sec = expires;
4452 }
4453#endif
4454
4455 return NGX_OK0;
4456}
4457
4458
4459static ngx_int_t
4460ngx_http_upstream_process_accel_expires(ngx_http_request_t *r,
4461 ngx_table_elt_t *h, ngx_uint_t offset)
4462{
4463 ngx_http_upstream_t *u;
4464
4465 u = r->upstream;
4466 u->headers_in.x_accel_expires = h;
4467
4468#if (NGX_HTTP_CACHE1)
4469 {
4470 u_char *p;
4471 size_t len;
4472 ngx_int_t n;
4473
4474 if (u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_XA_EXPIRES0x00000004) {
4475 return NGX_OK0;
4476 }
4477
4478 if (r->cache == NULL((void*)0)) {
4479 return NGX_OK0;
4480 }
4481
4482 len = h->value.len;
4483 p = h->value.data;
4484
4485 if (p[0] != '@') {
4486 n = ngx_atoi(p, len);
4487
4488 switch (n) {
4489 case 0:
4490 u->cacheable = 0;
4491 /* fall through */
4492
4493 case NGX_ERROR-1:
4494 return NGX_OK0;
4495
4496 default:
4497 r->cache->valid_sec = ngx_time()ngx_cached_time->sec + n;
4498 return NGX_OK0;
4499 }
4500 }
4501
4502 p++;
4503 len--;
4504
4505 n = ngx_atoi(p, len);
4506
4507 if (n != NGX_ERROR-1) {
4508 r->cache->valid_sec = n;
4509 }
4510 }
4511#endif
4512
4513 return NGX_OK0;
4514}
4515
4516
4517static ngx_int_t
4518ngx_http_upstream_process_limit_rate(ngx_http_request_t *r, ngx_table_elt_t *h,
4519 ngx_uint_t offset)
4520{
4521 ngx_int_t n;
4522 ngx_http_upstream_t *u;
4523
4524 u = r->upstream;
4525 u->headers_in.x_accel_limit_rate = h;
4526
4527 if (u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_XA_LIMIT_RATE0x00000040) {
4528 return NGX_OK0;
4529 }
4530
4531 n = ngx_atoi(h->value.data, h->value.len);
4532
4533 if (n != NGX_ERROR-1) {
4534 r->limit_rate = (size_t) n;
4535 }
4536
4537 return NGX_OK0;
4538}
4539
4540
4541static ngx_int_t
4542ngx_http_upstream_process_buffering(ngx_http_request_t *r, ngx_table_elt_t *h,
4543 ngx_uint_t offset)
4544{
4545 u_char c0, c1, c2;
4546 ngx_http_upstream_t *u;
4547
4548 u = r->upstream;
4549
4550 if (u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_XA_BUFFERING0x00000080) {
4551 return NGX_OK0;
4552 }
4553
4554 if (u->conf->change_buffering) {
4555
4556 if (h->value.len == 2) {
4557 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])
;
4558 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])
;
4559
4560 if (c0 == 'n' && c1 == 'o') {
4561 u->buffering = 0;
4562 }
4563
4564 } else if (h->value.len == 3) {
4565 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])
;
4566 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])
;
4567 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])
;
4568
4569 if (c0 == 'y' && c1 == 'e' && c2 == 's') {
4570 u->buffering = 1;
4571 }
4572 }
4573 }
4574
4575 return NGX_OK0;
4576}
4577
4578
4579static ngx_int_t
4580ngx_http_upstream_process_charset(ngx_http_request_t *r, ngx_table_elt_t *h,
4581 ngx_uint_t offset)
4582{
4583 if (r->upstream->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_XA_CHARSET0x00000100) {
4584 return NGX_OK0;
4585 }
4586
4587 r->headers_out.override_charset = &h->value;
4588
4589 return NGX_OK0;
4590}
4591
4592
4593static ngx_int_t
4594ngx_http_upstream_process_connection(ngx_http_request_t *r, ngx_table_elt_t *h,
4595 ngx_uint_t offset)
4596{
4597 r->upstream->headers_in.connection = h;
4598
4599 if (ngx_strlcasestrn(h->value.data, h->value.data + h->value.len,
4600 (u_char *) "close", 5 - 1)
4601 != NULL((void*)0))
4602 {
4603 r->upstream->headers_in.connection_close = 1;
4604 }
4605
4606 return NGX_OK0;
4607}
4608
4609
4610static ngx_int_t
4611ngx_http_upstream_process_transfer_encoding(ngx_http_request_t *r,
4612 ngx_table_elt_t *h, ngx_uint_t offset)
4613{
4614 r->upstream->headers_in.transfer_encoding = h;
4615
4616 if (ngx_strlcasestrn(h->value.data, h->value.data + h->value.len,
4617 (u_char *) "chunked", 7 - 1)
4618 != NULL((void*)0))
4619 {
4620 r->upstream->headers_in.chunked = 1;
4621 }
4622
4623 return NGX_OK0;
4624}
4625
4626
4627static ngx_int_t
4628ngx_http_upstream_process_vary(ngx_http_request_t *r,
4629 ngx_table_elt_t *h, ngx_uint_t offset)
4630{
4631 ngx_http_upstream_t *u;
4632
4633 u = r->upstream;
4634 u->headers_in.vary = h;
4635
4636#if (NGX_HTTP_CACHE1)
4637
4638 if (u->conf->ignore_headers & NGX_HTTP_UPSTREAM_IGN_VARY0x00000200) {
4639 return NGX_OK0;
4640 }
4641
4642 if (r->cache == NULL((void*)0)) {
4643 return NGX_OK0;
4644 }
4645
4646 if (h->value.len > NGX_HTTP_CACHE_VARY_LEN42
4647 || (h->value.len == 1 && h->value.data[0] == '*'))
4648 {
4649 u->cacheable = 0;
4650 }
4651
4652 r->cache->vary = h->value;
4653
4654#endif
4655
4656 return NGX_OK0;
4657}
4658
4659
4660static ngx_int_t
4661ngx_http_upstream_copy_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
4662 ngx_uint_t offset)
4663{
4664 ngx_table_elt_t *ho, **ph;
4665
4666 ho = ngx_list_push(&r->headers_out.headers);
4667 if (ho == NULL((void*)0)) {
4668 return NGX_ERROR-1;
4669 }
4670
4671 *ho = *h;
4672
4673 if (offset) {
4674 ph = (ngx_table_elt_t **) ((char *) &r->headers_out + offset);
4675 *ph = ho;
4676 }
4677
4678 return NGX_OK0;
4679}
4680
4681
4682static ngx_int_t
4683ngx_http_upstream_copy_multi_header_lines(ngx_http_request_t *r,
4684 ngx_table_elt_t *h, ngx_uint_t offset)
4685{
4686 ngx_array_t *pa;
4687 ngx_table_elt_t *ho, **ph;
4688
4689 pa = (ngx_array_t *) ((char *) &r->headers_out + offset);
4690
4691 if (pa->elts == NULL((void*)0)) {
4692 if (ngx_array_init(pa, r->pool, 2, sizeof(ngx_table_elt_t *)) != NGX_OK0)
4693 {
4694 return NGX_ERROR-1;
4695 }
4696 }
4697
4698 ph = ngx_array_push(pa);
4699 if (ph == NULL((void*)0)) {
4700 return NGX_ERROR-1;
4701 }
4702
4703 ho = ngx_list_push(&r->headers_out.headers);
4704 if (ho == NULL((void*)0)) {
4705 return NGX_ERROR-1;
4706 }
4707
4708 *ho = *h;
4709 *ph = ho;
4710
4711 return NGX_OK0;
4712}
4713
4714
4715static ngx_int_t
4716ngx_http_upstream_copy_content_type(ngx_http_request_t *r, ngx_table_elt_t *h,
4717 ngx_uint_t offset)
4718{
4719 u_char *p, *last;
4720
4721 r->headers_out.content_type_len = h->value.len;
4722 r->headers_out.content_type = h->value;
4723 r->headers_out.content_type_lowcase = NULL((void*)0);
4724
4725 for (p = h->value.data; *p; p++) {
4726
4727 if (*p != ';') {
4728 continue;
4729 }
4730
4731 last = p;
4732
4733 while (*++p == ' ') { /* void */ }
4734
4735 if (*p == '\0') {
4736 return NGX_OK0;
4737 }
4738
4739 if (ngx_strncasecmp(p, (u_char *) "charset=", 8) != 0) {
4740 continue;
4741 }
4742
4743 p += 8;
4744
4745 r->headers_out.content_type_len = last - h->value.data;
4746
4747 if (*p == '"') {
4748 p++;
4749 }
4750
4751 last = h->value.data + h->value.len;
4752
4753 if (*(last - 1) == '"') {
4754 last--;
4755 }
4756
4757 r->headers_out.charset.len = last - p;
4758 r->headers_out.charset.data = p;
4759
4760 return NGX_OK0;
4761 }
4762
4763 return NGX_OK0;
4764}
4765
4766
4767static ngx_int_t
4768ngx_http_upstream_copy_last_modified(ngx_http_request_t *r, ngx_table_elt_t *h,
4769 ngx_uint_t offset)
4770{
4771 ngx_table_elt_t *ho;
4772
4773 ho = ngx_list_push(&r->headers_out.headers);
4774 if (ho == NULL((void*)0)) {
4775 return NGX_ERROR-1;
4776 }
4777
4778 *ho = *h;
4779
4780 r->headers_out.last_modified = ho;
4781
4782#if (NGX_HTTP_CACHE1)
4783
4784 if (r->upstream->cacheable) {
4785 r->headers_out.last_modified_time =
4786 r->upstream->headers_in.last_modified_time;
4787 }
4788
4789#endif
4790
4791 return NGX_OK0;
4792}
4793
4794
4795static ngx_int_t
4796ngx_http_upstream_rewrite_location(ngx_http_request_t *r, ngx_table_elt_t *h,
4797 ngx_uint_t offset)
4798{
4799 ngx_int_t rc;
4800 ngx_table_elt_t *ho;
4801
4802 ho = ngx_list_push(&r->headers_out.headers);
4803 if (ho == NULL((void*)0)) {
4804 return NGX_ERROR-1;
4805 }
4806
4807 *ho = *h;
4808
4809 if (r->upstream->rewrite_redirect) {
4810 rc = r->upstream->rewrite_redirect(r, ho, 0);
4811
4812 if (rc == NGX_DECLINED-5) {
4813 return NGX_OK0;
4814 }
4815
4816 if (rc == NGX_OK0) {
4817 r->headers_out.location = ho;
4818
4819 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
4820 "rewritten location: \"%V\"", &ho->value);
4821 }
4822
4823 return rc;
4824 }
4825
4826 if (ho->value.data[0] != '/') {
4827 r->headers_out.location = ho;
4828 }
4829
4830 /*
4831 * we do not set r->headers_out.location here to avoid the handling
4832 * the local redirects without a host name by ngx_http_header_filter()
4833 */
4834
4835 return NGX_OK0;
4836}
4837
4838
4839static ngx_int_t
4840ngx_http_upstream_rewrite_refresh(ngx_http_request_t *r, ngx_table_elt_t *h,
4841 ngx_uint_t offset)
4842{
4843 u_char *p;
4844 ngx_int_t rc;
4845 ngx_table_elt_t *ho;
4846
4847 ho = ngx_list_push(&r->headers_out.headers);
4848 if (ho == NULL((void*)0)) {
4849 return NGX_ERROR-1;
4850 }
4851
4852 *ho = *h;
4853
4854 if (r->upstream->rewrite_redirect) {
4855
4856 p = ngx_strcasestrn(ho->value.data, "url=", 4 - 1);
4857
4858 if (p) {
4859 rc = r->upstream->rewrite_redirect(r, ho, p + 4 - ho->value.data);
4860
4861 } else {
4862 return NGX_OK0;
4863 }
4864
4865 if (rc == NGX_DECLINED-5) {
4866 return NGX_OK0;
4867 }
4868
4869 if (rc == NGX_OK0) {
4870 r->headers_out.refresh = ho;
4871
4872 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
4873 "rewritten refresh: \"%V\"", &ho->value);
4874 }
4875
4876 return rc;
4877 }
4878
4879 r->headers_out.refresh = ho;
4880
4881 return NGX_OK0;
4882}
4883
4884
4885static ngx_int_t
4886ngx_http_upstream_rewrite_set_cookie(ngx_http_request_t *r, ngx_table_elt_t *h,
4887 ngx_uint_t offset)
4888{
4889 ngx_int_t rc;
4890 ngx_table_elt_t *ho;
4891
4892 ho = ngx_list_push(&r->headers_out.headers);
4893 if (ho == NULL((void*)0)) {
4894 return NGX_ERROR-1;
4895 }
4896
4897 *ho = *h;
4898
4899 if (r->upstream->rewrite_cookie) {
4900 rc = r->upstream->rewrite_cookie(r, ho);
4901
4902 if (rc == NGX_DECLINED-5) {
4903 return NGX_OK0;
4904 }
4905
4906#if (NGX_DEBUG)
4907 if (rc == NGX_OK0) {
4908 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
4909 "rewritten cookie: \"%V\"", &ho->value);
4910 }
4911#endif
4912
4913 return rc;
4914 }
4915
4916 return NGX_OK0;
4917}
4918
4919
4920static ngx_int_t
4921ngx_http_upstream_copy_allow_ranges(ngx_http_request_t *r,
4922 ngx_table_elt_t *h, ngx_uint_t offset)
4923{
4924 ngx_table_elt_t *ho;
4925
4926 if (r->upstream->conf->force_ranges) {
4927 return NGX_OK0;
4928 }
4929
4930#if (NGX_HTTP_CACHE1)
4931
4932 if (r->cached) {
4933 r->allow_ranges = 1;
4934 return NGX_OK0;
4935 }
4936
4937 if (r->upstream->cacheable) {
4938 r->allow_ranges = 1;
4939 r->single_range = 1;
4940 return NGX_OK0;
4941 }
4942
4943#endif
4944
4945 ho = ngx_list_push(&r->headers_out.headers);
4946 if (ho == NULL((void*)0)) {
4947 return NGX_ERROR-1;
4948 }
4949
4950 *ho = *h;
4951
4952 r->headers_out.accept_ranges = ho;
4953
4954 return NGX_OK0;
4955}
4956
4957
4958#if (NGX_HTTP_GZIP1)
4959
4960static ngx_int_t
4961ngx_http_upstream_copy_content_encoding(ngx_http_request_t *r,
4962 ngx_table_elt_t *h, ngx_uint_t offset)
4963{
4964 ngx_table_elt_t *ho;
4965
4966 ho = ngx_list_push(&r->headers_out.headers);
4967 if (ho == NULL((void*)0)) {
4968 return NGX_ERROR-1;
4969 }
4970
4971 *ho = *h;
4972
4973 r->headers_out.content_encoding = ho;
4974
4975 return NGX_OK0;
4976}
4977
4978#endif
4979
4980
4981static ngx_int_t
4982ngx_http_upstream_add_variables(ngx_conf_t *cf)
4983{
4984 ngx_http_variable_t *var, *v;
4985
4986 for (v = ngx_http_upstream_vars; v->name.len; v++) {
4987 var = ngx_http_add_variable(cf, &v->name, v->flags);
4988 if (var == NULL((void*)0)) {
4989 return NGX_ERROR-1;
4990 }
4991
4992 var->get_handler = v->get_handler;
4993 var->data = v->data;
4994 }
4995
4996 return NGX_OK0;
4997}
4998
4999
5000static ngx_int_t
5001ngx_http_upstream_addr_variable(ngx_http_request_t *r,
5002 ngx_http_variable_value_t *v, uintptr_t data)
5003{
5004 u_char *p;
5005 size_t len;
5006 ngx_uint_t i;
5007 ngx_http_upstream_state_t *state;
5008
5009 v->valid = 1;
5010 v->no_cacheable = 0;
5011 v->not_found = 0;
5012
5013 if (r->upstream_states == NULL((void*)0) || r->upstream_states->nelts == 0) {
5014 v->not_found = 1;
5015 return NGX_OK0;
5016 }
5017
5018 len = 0;
5019 state = r->upstream_states->elts;
5020
5021 for (i = 0; i < r->upstream_states->nelts; i++) {
5022 if (state[i].peer) {
5023 len += state[i].peer->len + 2;
5024
5025 } else {
5026 len += 3;
5027 }
5028 }
5029
5030 p = ngx_pnalloc(r->pool, len);
5031 if (p == NULL((void*)0)) {
5032 return NGX_ERROR-1;
5033 }
5034
5035 v->data = p;
5036
5037 i = 0;
5038
5039 for ( ;; ) {
5040 if (state[i].peer) {
5041 p = ngx_cpymem(p, state[i].peer->data, state[i].peer->len)(((u_char *) memcpy(p, state[i].peer->data, state[i].peer->
len)) + (state[i].peer->len))
;
5042 }
5043
5044 if (++i == r->upstream_states->nelts) {
5045 break;
5046 }
5047
5048 if (state[i].peer) {
5049 *p++ = ',';
5050 *p++ = ' ';
5051
5052 } else {
5053 *p++ = ' ';
5054 *p++ = ':';
5055 *p++ = ' ';
5056
5057 if (++i == r->upstream_states->nelts) {
5058 break;
5059 }
5060
5061 continue;
5062 }
5063 }
5064
5065 v->len = p - v->data;
5066
5067 return NGX_OK0;
5068}
5069
5070
5071static ngx_int_t
5072ngx_http_upstream_status_variable(ngx_http_request_t *r,
5073 ngx_http_variable_value_t *v, uintptr_t data)
5074{
5075 u_char *p;
5076 size_t len;
5077 ngx_uint_t i;
5078 ngx_http_upstream_state_t *state;
5079
5080 v->valid = 1;
5081 v->no_cacheable = 0;
5082 v->not_found = 0;
5083
5084 if (r->upstream_states == NULL((void*)0) || r->upstream_states->nelts == 0) {
5085 v->not_found = 1;
5086 return NGX_OK0;
5087 }
5088
5089 len = r->upstream_states->nelts * (3 + 2);
5090
5091 p = ngx_pnalloc(r->pool, len);
5092 if (p == NULL((void*)0)) {
5093 return NGX_ERROR-1;
5094 }
5095
5096 v->data = p;
5097
5098 i = 0;
5099 state = r->upstream_states->elts;
5100
5101 for ( ;; ) {
5102 if (state[i].status) {
5103 p = ngx_sprintf(p, "%ui", state[i].status);
5104
5105 } else {
5106 *p++ = '-';
5107 }
5108
5109 if (++i == r->upstream_states->nelts) {
5110 break;
5111 }
5112
5113 if (state[i].peer) {
5114 *p++ = ',';
5115 *p++ = ' ';
5116
5117 } else {
5118 *p++ = ' ';
5119 *p++ = ':';
5120 *p++ = ' ';
5121
5122 if (++i == r->upstream_states->nelts) {
5123 break;
5124 }
5125
5126 continue;
5127 }
5128 }
5129
5130 v->len = p - v->data;
5131
5132 return NGX_OK0;
5133}
5134
5135
5136static ngx_int_t
5137ngx_http_upstream_response_time_variable(ngx_http_request_t *r,
5138 ngx_http_variable_value_t *v, uintptr_t data)
5139{
5140 u_char *p;
5141 size_t len;
5142 ngx_uint_t i;
5143 ngx_msec_int_t ms;
5144 ngx_http_upstream_state_t *state;
5145
5146 v->valid = 1;
5147 v->no_cacheable = 0;
5148 v->not_found = 0;
5149
5150 if (r->upstream_states == NULL((void*)0) || r->upstream_states->nelts == 0) {
5151 v->not_found = 1;
5152 return NGX_OK0;
5153 }
5154
5155 len = r->upstream_states->nelts * (NGX_TIME_T_LEN(sizeof("-9223372036854775808") - 1) + 4 + 2);
5156
5157 p = ngx_pnalloc(r->pool, len);
5158 if (p == NULL((void*)0)) {
5159 return NGX_ERROR-1;
5160 }
5161
5162 v->data = p;
5163
5164 i = 0;
5165 state = r->upstream_states->elts;
5166
5167 for ( ;; ) {
5168 if (state[i].status) {
5169
5170 if (data == 1 && state[i].header_time != (ngx_msec_t) -1) {
5171 ms = state[i].header_time;
5172
5173 } else if (data == 2 && state[i].connect_time != (ngx_msec_t) -1) {
5174 ms = state[i].connect_time;
5175
5176 } else {
5177 ms = state[i].response_time;
5178 }
5179
5180 ms = ngx_max(ms, 0)((ms < 0) ? (0) : (ms));
5181 p = ngx_sprintf(p, "%T.%03M", (time_t) ms / 1000, ms % 1000);
5182
5183 } else {
5184 *p++ = '-';
5185 }
5186
5187 if (++i == r->upstream_states->nelts) {
5188 break;
5189 }
5190
5191 if (state[i].peer) {
5192 *p++ = ',';
5193 *p++ = ' ';
5194
5195 } else {
5196 *p++ = ' ';
5197 *p++ = ':';
5198 *p++ = ' ';
5199
5200 if (++i == r->upstream_states->nelts) {
5201 break;
5202 }
5203
5204 continue;
5205 }
5206 }
5207
5208 v->len = p - v->data;
5209
5210 return NGX_OK0;
5211}
5212
5213
5214static ngx_int_t
5215ngx_http_upstream_response_length_variable(ngx_http_request_t *r,
5216 ngx_http_variable_value_t *v, uintptr_t data)
5217{
5218 u_char *p;
5219 size_t len;
5220 ngx_uint_t i;
5221 ngx_http_upstream_state_t *state;
5222
5223 v->valid = 1;
5224 v->no_cacheable = 0;
5225 v->not_found = 0;
5226
5227 if (r->upstream_states == NULL((void*)0) || r->upstream_states->nelts == 0) {
5228 v->not_found = 1;
5229 return NGX_OK0;
5230 }
5231
5232 len = r->upstream_states->nelts * (NGX_OFF_T_LEN(sizeof("-9223372036854775808") - 1) + 2);
5233
5234 p = ngx_pnalloc(r->pool, len);
5235 if (p == NULL((void*)0)) {
5236 return NGX_ERROR-1;
5237 }
5238
5239 v->data = p;
5240
5241 i = 0;
5242 state = r->upstream_states->elts;
5243
5244 for ( ;; ) {
5245 p = ngx_sprintf(p, "%O", state[i].response_length);
5246
5247 if (++i == r->upstream_states->nelts) {
5248 break;
5249 }
5250
5251 if (state[i].peer) {
5252 *p++ = ',';
5253 *p++ = ' ';
5254
5255 } else {
5256 *p++ = ' ';
5257 *p++ = ':';
5258 *p++ = ' ';
5259
5260 if (++i == r->upstream_states->nelts) {
5261 break;
5262 }
5263
5264 continue;
5265 }
5266 }
5267
5268 v->len = p - v->data;
5269
5270 return NGX_OK0;
5271}
5272
5273
5274ngx_int_t
5275ngx_http_upstream_header_variable(ngx_http_request_t *r,
5276 ngx_http_variable_value_t *v, uintptr_t data)
5277{
5278 if (r->upstream == NULL((void*)0)) {
5279 v->not_found = 1;
5280 return NGX_OK0;
5281 }
5282
5283 return ngx_http_variable_unknown_header(v, (ngx_str_t *) data,
5284 &r->upstream->headers_in.headers.part,
5285 sizeof("upstream_http_") - 1);
5286}
5287
5288
5289ngx_int_t
5290ngx_http_upstream_cookie_variable(ngx_http_request_t *r,
5291 ngx_http_variable_value_t *v, uintptr_t data)
5292{
5293 ngx_str_t *name = (ngx_str_t *) data;
5294
5295 ngx_str_t cookie, s;
5296
5297 if (r->upstream == NULL((void*)0)) {
5298 v->not_found = 1;
5299 return NGX_OK0;
5300 }
5301
5302 s.len = name->len - (sizeof("upstream_cookie_") - 1);
5303 s.data = name->data + sizeof("upstream_cookie_") - 1;
5304
5305 if (ngx_http_parse_set_cookie_lines(&r->upstream->headers_in.cookies,
5306 &s, &cookie)
5307 == NGX_DECLINED-5)
5308 {
5309 v->not_found = 1;
5310 return NGX_OK0;
5311 }
5312
5313 v->len = cookie.len;
5314 v->valid = 1;
5315 v->no_cacheable = 0;
5316 v->not_found = 0;
5317 v->data = cookie.data;
5318
5319 return NGX_OK0;
5320}
5321
5322
5323#if (NGX_HTTP_CACHE1)
5324
5325ngx_int_t
5326ngx_http_upstream_cache_status(ngx_http_request_t *r,
5327 ngx_http_variable_value_t *v, uintptr_t data)
5328{
5329 ngx_uint_t n;
5330
5331 if (r->upstream == NULL((void*)0) || r->upstream->cache_status == 0) {
5332 v->not_found = 1;
5333 return NGX_OK0;
5334 }
5335
5336 n = r->upstream->cache_status - 1;
5337
5338 v->valid = 1;
5339 v->no_cacheable = 0;
5340 v->not_found = 0;
5341 v->len = ngx_http_cache_status[n].len;
5342 v->data = ngx_http_cache_status[n].data;
5343
5344 return NGX_OK0;
5345}
5346
5347
5348static ngx_int_t
5349ngx_http_upstream_cache_last_modified(ngx_http_request_t *r,
5350 ngx_http_variable_value_t *v, uintptr_t data)
5351{
5352 u_char *p;
5353
5354 if (r->upstream == NULL((void*)0)
5355 || !r->upstream->conf->cache_revalidate
5356 || r->upstream->cache_status != NGX_HTTP_CACHE_EXPIRED3
5357 || r->cache->last_modified == -1)
5358 {
5359 v->not_found = 1;
5360 return NGX_OK0;
5361 }
5362
5363 p = ngx_pnalloc(r->pool, sizeof("Mon, 28 Sep 1970 06:00:00 GMT") - 1);
5364 if (p == NULL((void*)0)) {
5365 return NGX_ERROR-1;
5366 }
5367
5368 v->len = ngx_http_time(p, r->cache->last_modified) - p;
5369 v->valid = 1;
5370 v->no_cacheable = 0;
5371 v->not_found = 0;
5372 v->data = p;
5373
5374 return NGX_OK0;
5375}
5376
5377
5378static ngx_int_t
5379ngx_http_upstream_cache_etag(ngx_http_request_t *r,
5380 ngx_http_variable_value_t *v, uintptr_t data)
5381{
5382 if (r->upstream == NULL((void*)0)
5383 || !r->upstream->conf->cache_revalidate
5384 || r->upstream->cache_status != NGX_HTTP_CACHE_EXPIRED3
5385 || r->cache->etag.len == 0)
5386 {
5387 v->not_found = 1;
5388 return NGX_OK0;
5389 }
5390
5391 v->valid = 1;
5392 v->no_cacheable = 0;
5393 v->not_found = 0;
5394 v->len = r->cache->etag.len;
5395 v->data = r->cache->etag.data;
5396
5397 return NGX_OK0;
5398}
5399
5400#endif
5401
5402
5403static char *
5404ngx_http_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
5405{
5406 char *rv;
5407 void *mconf;
5408 ngx_str_t *value;
5409 ngx_url_t u;
5410 ngx_uint_t m;
5411 ngx_conf_t pcf;
5412 ngx_http_module_t *module;
5413 ngx_http_conf_ctx_t *ctx, *http_ctx;
5414 ngx_http_upstream_srv_conf_t *uscf;
5415
5416 ngx_memzero(&u, sizeof(ngx_url_t))(void) memset(&u, 0, sizeof(ngx_url_t));
5417
5418 value = cf->args->elts;
5419 u.host = value[1];
5420 u.no_resolve = 1;
5421 u.no_port = 1;
5422
5423 uscf = ngx_http_upstream_add(cf, &u, NGX_HTTP_UPSTREAM_CREATE0x0001
5424 |NGX_HTTP_UPSTREAM_WEIGHT0x0002
5425 |NGX_HTTP_UPSTREAM_MAX_FAILS0x0004
5426 |NGX_HTTP_UPSTREAM_FAIL_TIMEOUT0x0008
5427 |NGX_HTTP_UPSTREAM_DOWN0x0010
5428 |NGX_HTTP_UPSTREAM_BACKUP0x0020);
5429 if (uscf == NULL((void*)0)) {
5430 return NGX_CONF_ERROR(void *) -1;
5431 }
5432
5433
5434 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
5435 if (ctx == NULL((void*)0)) {
5436 return NGX_CONF_ERROR(void *) -1;
5437 }
5438
5439 http_ctx = cf->ctx;
5440 ctx->main_conf = http_ctx->main_conf;
5441
5442 /* the upstream{}'s srv_conf */
5443
5444 ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
5445 if (ctx->srv_conf == NULL((void*)0)) {
5446 return NGX_CONF_ERROR(void *) -1;
5447 }
5448
5449 ctx->srv_conf[ngx_http_upstream_module.ctx_index] = uscf;
5450
5451 uscf->srv_conf = ctx->srv_conf;
5452
5453
5454 /* the upstream{}'s loc_conf */
5455
5456 ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
5457 if (ctx->loc_conf == NULL((void*)0)) {
5458 return NGX_CONF_ERROR(void *) -1;
5459 }
5460
5461 for (m = 0; cf->cycle->modules[m]; m++) {
5462 if (cf->cycle->modules[m]->type != NGX_HTTP_MODULE0x50545448) {
5463 continue;
5464 }
5465
5466 module = cf->cycle->modules[m]->ctx;
5467
5468 if (module->create_srv_conf) {
5469 mconf = module->create_srv_conf(cf);
5470 if (mconf == NULL((void*)0)) {
5471 return NGX_CONF_ERROR(void *) -1;
5472 }
5473
5474 ctx->srv_conf[cf->cycle->modules[m]->ctx_index] = mconf;
5475 }
5476
5477 if (module->create_loc_conf) {
5478 mconf = module->create_loc_conf(cf);
5479 if (mconf == NULL((void*)0)) {
5480 return NGX_CONF_ERROR(void *) -1;
5481 }
5482
5483 ctx->loc_conf[cf->cycle->modules[m]->ctx_index] = mconf;
5484 }
5485 }
5486
5487 uscf->servers = ngx_array_create(cf->pool, 4,
5488 sizeof(ngx_http_upstream_server_t));
5489 if (uscf->servers == NULL((void*)0)) {
5490 return NGX_CONF_ERROR(void *) -1;
5491 }
5492
5493
5494 /* parse inside upstream{} */
5495
5496 pcf = *cf;
5497 cf->ctx = ctx;
5498 cf->cmd_type = NGX_HTTP_UPS_CONF0x10000000;
5499
5500 rv = ngx_conf_parse(cf, NULL((void*)0));
5501
5502 *cf = pcf;
5503
5504 if (rv != NGX_CONF_OK((void*)0)) {
5505 return rv;
5506 }
5507
5508 if (uscf->servers->nelts == 0) {
5509 ngx_conf_log_error(NGX_LOG_EMERG1, cf, 0,
5510 "no servers are inside upstream");
5511 return NGX_CONF_ERROR(void *) -1;
5512 }
5513
5514 return rv;
5515}
5516
5517
5518static char *
5519ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
5520{
5521 ngx_http_upstream_srv_conf_t *uscf = conf;
5522
5523 time_t fail_timeout;
5524 ngx_str_t *value, s;
5525 ngx_url_t u;
5526 ngx_int_t weight, max_fails;
5527 ngx_uint_t i;
5528 ngx_http_upstream_server_t *us;
5529
5530 us = ngx_array_push(uscf->servers);
5531 if (us == NULL((void*)0)) {
5532 return NGX_CONF_ERROR(void *) -1;
5533 }
5534
5535 ngx_memzero(us, sizeof(ngx_http_upstream_server_t))(void) memset(us, 0, sizeof(ngx_http_upstream_server_t));
5536
5537 value = cf->args->elts;
5538
5539 weight = 1;
5540 max_fails = 1;
5541 fail_timeout = 10;
5542
5543 for (i = 2; i < cf->args->nelts; i++) {
5544
5545 if (ngx_strncmp(value[i].data, "weight=", 7)(__extension__ (__builtin_constant_p (7) && ((__builtin_constant_p
((const char *) value[i].data) && strlen ((const char
*) value[i].data) < ((size_t) (7))) || (__builtin_constant_p
((const char *) "weight=") && strlen ((const char *)
"weight=") < ((size_t) (7)))) ? __extension__ ({ size_t __s1_len
, __s2_len; (__builtin_constant_p ((const char *) value[i].data
) && __builtin_constant_p ((const char *) "weight=") &&
(__s1_len = strlen ((const char *) value[i].data), __s2_len =
strlen ((const char *) "weight="), (!((size_t)(const void *)
(((const char *) value[i].data) + 1) - (size_t)(const void *)
((const char *) value[i].data) == 1) || __s1_len >= 4) &&
(!((size_t)(const void *)(((const char *) "weight=") + 1) - (
size_t)(const void *)((const char *) "weight=") == 1) || __s2_len
>= 4)) ? __builtin_strcmp ((const char *) value[i].data, (
const char *) "weight=") : (__builtin_constant_p ((const char
*) value[i].data) && ((size_t)(const void *)(((const
char *) value[i].data) + 1) - (size_t)(const void *)((const char
*) value[i].data) == 1) && (__s1_len = strlen ((const
char *) value[i].data), __s1_len < 4) ? (__builtin_constant_p
((const char *) "weight=") && ((size_t)(const void *
)(((const char *) "weight=") + 1) - (size_t)(const void *)((const
char *) "weight=") == 1) ? __builtin_strcmp ((const char *) value
[i].data, (const char *) "weight=") : (__extension__ ({ const
unsigned char *__s2 = (const unsigned char *) (const char *)
((const char *) "weight="); int __result = (((const unsigned
char *) (const char *) ((const char *) value[i].data))[0] - __s2
[0]); if (__s1_len > 0 && __result == 0) { __result
= (((const unsigned char *) (const char *) ((const char *) value
[i].data))[1] - __s2[1]); if (__s1_len > 1 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
(const char *) value[i].data))[2] - __s2[2]); if (__s1_len >
2 && __result == 0) __result = (((const unsigned char
*) (const char *) ((const char *) value[i].data))[3] - __s2[
3]); } } __result; }))) : (__builtin_constant_p ((const char *
) "weight=") && ((size_t)(const void *)(((const char *
) "weight=") + 1) - (size_t)(const void *)((const char *) "weight="
) == 1) && (__s2_len = strlen ((const char *) "weight="
), __s2_len < 4) ? (__builtin_constant_p ((const char *) value
[i].data) && ((size_t)(const void *)(((const char *) value
[i].data) + 1) - (size_t)(const void *)((const char *) value[
i].data) == 1) ? __builtin_strcmp ((const char *) value[i].data
, (const char *) "weight=") : (- (__extension__ ({ const unsigned
char *__s2 = (const unsigned char *) (const char *) ((const char
*) value[i].data); int __result = (((const unsigned char *) (
const char *) ((const char *) "weight="))[0] - __s2[0]); if (
__s2_len > 0 && __result == 0) { __result = (((const
unsigned char *) (const char *) ((const char *) "weight="))[
1] - __s2[1]); if (__s2_len > 1 && __result == 0) {
__result = (((const unsigned char *) (const char *) ((const char
*) "weight="))[2] - __s2[2]); if (__s2_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) ((const char *) "weight="))[3] - __s2[3]); } } __result; }
)))) : __builtin_strcmp ((const char *) value[i].data, (const
char *) "weight=")))); }) : strncmp ((const char *) value[i]
.data, (const char *) "weight=", 7)))
== 0) {
5546
5547 if (!(uscf->flags & NGX_HTTP_UPSTREAM_WEIGHT0x0002)) {
5548 goto not_supported;
5549 }
5550
5551 weight = ngx_atoi(&value[i].data[7], value[i].len - 7);
5552
5553 if (weight == NGX_ERROR-1 || weight == 0) {
5554 goto invalid;
5555 }
5556
5557 continue;
5558 }
5559
5560 if (ngx_strncmp(value[i].data, "max_fails=", 10)(__extension__ (__builtin_constant_p (10) && ((__builtin_constant_p
((const char *) value[i].data) && strlen ((const char
*) value[i].data) < ((size_t) (10))) || (__builtin_constant_p
((const char *) "max_fails=") && strlen ((const char
*) "max_fails=") < ((size_t) (10)))) ? __extension__ ({ size_t
__s1_len, __s2_len; (__builtin_constant_p ((const char *) value
[i].data) && __builtin_constant_p ((const char *) "max_fails="
) && (__s1_len = strlen ((const char *) value[i].data
), __s2_len = strlen ((const char *) "max_fails="), (!((size_t
)(const void *)(((const char *) value[i].data) + 1) - (size_t
)(const void *)((const char *) value[i].data) == 1) || __s1_len
>= 4) && (!((size_t)(const void *)(((const char *
) "max_fails=") + 1) - (size_t)(const void *)((const char *) "max_fails="
) == 1) || __s2_len >= 4)) ? __builtin_strcmp ((const char
*) value[i].data, (const char *) "max_fails=") : (__builtin_constant_p
((const char *) value[i].data) && ((size_t)(const void
*)(((const char *) value[i].data) + 1) - (size_t)(const void
*)((const char *) value[i].data) == 1) && (__s1_len =
strlen ((const char *) value[i].data), __s1_len < 4) ? (__builtin_constant_p
((const char *) "max_fails=") && ((size_t)(const void
*)(((const char *) "max_fails=") + 1) - (size_t)(const void *
)((const char *) "max_fails=") == 1) ? __builtin_strcmp ((const
char *) value[i].data, (const char *) "max_fails=") : (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) ((const char *) "max_fails="); int __result = (((const
unsigned char *) (const char *) ((const char *) value[i].data
))[0] - __s2[0]); if (__s1_len > 0 && __result == 0
) { __result = (((const unsigned char *) (const char *) ((const
char *) value[i].data))[1] - __s2[1]); if (__s1_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) ((const char *) value[i].data))[2] - __s2[2]); if (__s1_len
> 2 && __result == 0) __result = (((const unsigned
char *) (const char *) ((const char *) value[i].data))[3] - __s2
[3]); } } __result; }))) : (__builtin_constant_p ((const char
*) "max_fails=") && ((size_t)(const void *)(((const char
*) "max_fails=") + 1) - (size_t)(const void *)((const char *
) "max_fails=") == 1) && (__s2_len = strlen ((const char
*) "max_fails="), __s2_len < 4) ? (__builtin_constant_p (
(const char *) value[i].data) && ((size_t)(const void
*)(((const char *) value[i].data) + 1) - (size_t)(const void
*)((const char *) value[i].data) == 1) ? __builtin_strcmp ((
const char *) value[i].data, (const char *) "max_fails=") : (
- (__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) ((const char *) value[i].data); int __result
= (((const unsigned char *) (const char *) ((const char *) "max_fails="
))[0] - __s2[0]); if (__s2_len > 0 && __result == 0
) { __result = (((const unsigned char *) (const char *) ((const
char *) "max_fails="))[1] - __s2[1]); if (__s2_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) ((const char *) "max_fails="))[2] - __s2[2]); if (__s2_len
> 2 && __result == 0) __result = (((const unsigned
char *) (const char *) ((const char *) "max_fails="))[3] - __s2
[3]); } } __result; })))) : __builtin_strcmp ((const char *) value
[i].data, (const char *) "max_fails=")))); }) : strncmp ((const
char *) value[i].data, (const char *) "max_fails=", 10)))
== 0) {
5561
5562 if (!(uscf->flags & NGX_HTTP_UPSTREAM_MAX_FAILS0x0004)) {
5563 goto not_supported;
5564 }
5565
5566 max_fails = ngx_atoi(&value[i].data[10], value[i].len - 10);
5567
5568 if (max_fails == NGX_ERROR-1) {
5569 goto invalid;
5570 }
5571
5572 continue;
5573 }
5574
5575 if (ngx_strncmp(value[i].data, "fail_timeout=", 13)(__extension__ (__builtin_constant_p (13) && ((__builtin_constant_p
((const char *) value[i].data) && strlen ((const char
*) value[i].data) < ((size_t) (13))) || (__builtin_constant_p
((const char *) "fail_timeout=") && strlen ((const char
*) "fail_timeout=") < ((size_t) (13)))) ? __extension__ (
{ size_t __s1_len, __s2_len; (__builtin_constant_p ((const char
*) value[i].data) && __builtin_constant_p ((const char
*) "fail_timeout=") && (__s1_len = strlen ((const char
*) value[i].data), __s2_len = strlen ((const char *) "fail_timeout="
), (!((size_t)(const void *)(((const char *) value[i].data) +
1) - (size_t)(const void *)((const char *) value[i].data) ==
1) || __s1_len >= 4) && (!((size_t)(const void *)
(((const char *) "fail_timeout=") + 1) - (size_t)(const void *
)((const char *) "fail_timeout=") == 1) || __s2_len >= 4))
? __builtin_strcmp ((const char *) value[i].data, (const char
*) "fail_timeout=") : (__builtin_constant_p ((const char *) value
[i].data) && ((size_t)(const void *)(((const char *) value
[i].data) + 1) - (size_t)(const void *)((const char *) value[
i].data) == 1) && (__s1_len = strlen ((const char *) value
[i].data), __s1_len < 4) ? (__builtin_constant_p ((const char
*) "fail_timeout=") && ((size_t)(const void *)(((const
char *) "fail_timeout=") + 1) - (size_t)(const void *)((const
char *) "fail_timeout=") == 1) ? __builtin_strcmp ((const char
*) value[i].data, (const char *) "fail_timeout=") : (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) ((const char *) "fail_timeout="); int __result = (((
const unsigned char *) (const char *) ((const char *) value[i
].data))[0] - __s2[0]); if (__s1_len > 0 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
(const char *) value[i].data))[1] - __s2[1]); if (__s1_len >
1 && __result == 0) { __result = (((const unsigned char
*) (const char *) ((const char *) value[i].data))[2] - __s2[
2]); if (__s1_len > 2 && __result == 0) __result =
(((const unsigned char *) (const char *) ((const char *) value
[i].data))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p
((const char *) "fail_timeout=") && ((size_t)(const void
*)(((const char *) "fail_timeout=") + 1) - (size_t)(const void
*)((const char *) "fail_timeout=") == 1) && (__s2_len
= strlen ((const char *) "fail_timeout="), __s2_len < 4) ?
(__builtin_constant_p ((const char *) value[i].data) &&
((size_t)(const void *)(((const char *) value[i].data) + 1) -
(size_t)(const void *)((const char *) value[i].data) == 1) ?
__builtin_strcmp ((const char *) value[i].data, (const char *
) "fail_timeout=") : (- (__extension__ ({ const unsigned char
*__s2 = (const unsigned char *) (const char *) ((const char *
) value[i].data); int __result = (((const unsigned char *) (const
char *) ((const char *) "fail_timeout="))[0] - __s2[0]); if (
__s2_len > 0 && __result == 0) { __result = (((const
unsigned char *) (const char *) ((const char *) "fail_timeout="
))[1] - __s2[1]); if (__s2_len > 1 && __result == 0
) { __result = (((const unsigned char *) (const char *) ((const
char *) "fail_timeout="))[2] - __s2[2]); if (__s2_len > 2
&& __result == 0) __result = (((const unsigned char *
) (const char *) ((const char *) "fail_timeout="))[3] - __s2[
3]); } } __result; })))) : __builtin_strcmp ((const char *) value
[i].data, (const char *) "fail_timeout=")))); }) : strncmp ((
const char *) value[i].data, (const char *) "fail_timeout=", 13
)))
== 0) {
5576
5577 if (!(uscf->flags & NGX_HTTP_UPSTREAM_FAIL_TIMEOUT0x0008)) {
5578 goto not_supported;
5579 }
5580
5581 s.len = value[i].len - 13;
5582 s.data = &value[i].data[13];
5583
5584 fail_timeout = ngx_parse_time(&s, 1);
5585
5586 if (fail_timeout == (time_t) NGX_ERROR-1) {
5587 goto invalid;
5588 }
5589
5590 continue;
5591 }
5592
5593 if (ngx_strcmp(value[i].data, "backup")__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
((const char *) value[i].data) && __builtin_constant_p
((const char *) "backup") && (__s1_len = strlen ((const
char *) value[i].data), __s2_len = strlen ((const char *) "backup"
), (!((size_t)(const void *)(((const char *) value[i].data) +
1) - (size_t)(const void *)((const char *) value[i].data) ==
1) || __s1_len >= 4) && (!((size_t)(const void *)
(((const char *) "backup") + 1) - (size_t)(const void *)((const
char *) "backup") == 1) || __s2_len >= 4)) ? __builtin_strcmp
((const char *) value[i].data, (const char *) "backup") : (__builtin_constant_p
((const char *) value[i].data) && ((size_t)(const void
*)(((const char *) value[i].data) + 1) - (size_t)(const void
*)((const char *) value[i].data) == 1) && (__s1_len =
strlen ((const char *) value[i].data), __s1_len < 4) ? (__builtin_constant_p
((const char *) "backup") && ((size_t)(const void *)
(((const char *) "backup") + 1) - (size_t)(const void *)((const
char *) "backup") == 1) ? __builtin_strcmp ((const char *) value
[i].data, (const char *) "backup") : (__extension__ ({ const unsigned
char *__s2 = (const unsigned char *) (const char *) ((const char
*) "backup"); int __result = (((const unsigned char *) (const
char *) ((const char *) value[i].data))[0] - __s2[0]); if (__s1_len
> 0 && __result == 0) { __result = (((const unsigned
char *) (const char *) ((const char *) value[i].data))[1] - __s2
[1]); if (__s1_len > 1 && __result == 0) { __result
= (((const unsigned char *) (const char *) ((const char *) value
[i].data))[2] - __s2[2]); if (__s1_len > 2 && __result
== 0) __result = (((const unsigned char *) (const char *) ((
const char *) value[i].data))[3] - __s2[3]); } } __result; })
)) : (__builtin_constant_p ((const char *) "backup") &&
((size_t)(const void *)(((const char *) "backup") + 1) - (size_t
)(const void *)((const char *) "backup") == 1) && (__s2_len
= strlen ((const char *) "backup"), __s2_len < 4) ? (__builtin_constant_p
((const char *) value[i].data) && ((size_t)(const void
*)(((const char *) value[i].data) + 1) - (size_t)(const void
*)((const char *) value[i].data) == 1) ? __builtin_strcmp ((
const char *) value[i].data, (const char *) "backup") : (- (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) ((const char *) value[i].data); int __result = (((const
unsigned char *) (const char *) ((const char *) "backup"))[0
] - __s2[0]); if (__s2_len > 0 && __result == 0) {
__result = (((const unsigned char *) (const char *) ((const char
*) "backup"))[1] - __s2[1]); if (__s2_len > 1 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
(const char *) "backup"))[2] - __s2[2]); if (__s2_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) ((const char *) "backup"))[3] - __s2[3]); } } __result; }
)))) : __builtin_strcmp ((const char *) value[i].data, (const
char *) "backup")))); })
== 0) {
5594
5595 if (!(uscf->flags & NGX_HTTP_UPSTREAM_BACKUP0x0020)) {
5596 goto not_supported;
5597 }
5598
5599 us->backup = 1;
5600
5601 continue;
5602 }
5603
5604 if (ngx_strcmp(value[i].data, "down")__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
((const char *) value[i].data) && __builtin_constant_p
((const char *) "down") && (__s1_len = strlen ((const
char *) value[i].data), __s2_len = strlen ((const char *) "down"
), (!((size_t)(const void *)(((const char *) value[i].data) +
1) - (size_t)(const void *)((const char *) value[i].data) ==
1) || __s1_len >= 4) && (!((size_t)(const void *)
(((const char *) "down") + 1) - (size_t)(const void *)((const
char *) "down") == 1) || __s2_len >= 4)) ? __builtin_strcmp
((const char *) value[i].data, (const char *) "down") : (__builtin_constant_p
((const char *) value[i].data) && ((size_t)(const void
*)(((const char *) value[i].data) + 1) - (size_t)(const void
*)((const char *) value[i].data) == 1) && (__s1_len =
strlen ((const char *) value[i].data), __s1_len < 4) ? (__builtin_constant_p
((const char *) "down") && ((size_t)(const void *)((
(const char *) "down") + 1) - (size_t)(const void *)((const char
*) "down") == 1) ? __builtin_strcmp ((const char *) value[i]
.data, (const char *) "down") : (__extension__ ({ const unsigned
char *__s2 = (const unsigned char *) (const char *) ((const char
*) "down"); int __result = (((const unsigned char *) (const char
*) ((const char *) value[i].data))[0] - __s2[0]); if (__s1_len
> 0 && __result == 0) { __result = (((const unsigned
char *) (const char *) ((const char *) value[i].data))[1] - __s2
[1]); if (__s1_len > 1 && __result == 0) { __result
= (((const unsigned char *) (const char *) ((const char *) value
[i].data))[2] - __s2[2]); if (__s1_len > 2 && __result
== 0) __result = (((const unsigned char *) (const char *) ((
const char *) value[i].data))[3] - __s2[3]); } } __result; })
)) : (__builtin_constant_p ((const char *) "down") &&
((size_t)(const void *)(((const char *) "down") + 1) - (size_t
)(const void *)((const char *) "down") == 1) && (__s2_len
= strlen ((const char *) "down"), __s2_len < 4) ? (__builtin_constant_p
((const char *) value[i].data) && ((size_t)(const void
*)(((const char *) value[i].data) + 1) - (size_t)(const void
*)((const char *) value[i].data) == 1) ? __builtin_strcmp ((
const char *) value[i].data, (const char *) "down") : (- (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) ((const char *) value[i].data); int __result = (((const
unsigned char *) (const char *) ((const char *) "down"))[0] -
__s2[0]); if (__s2_len > 0 && __result == 0) { __result
= (((const unsigned char *) (const char *) ((const char *) "down"
))[1] - __s2[1]); if (__s2_len > 1 && __result == 0
) { __result = (((const unsigned char *) (const char *) ((const
char *) "down"))[2] - __s2[2]); if (__s2_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) ((const char *) "down"))[3] - __s2[3]); } } __result; }))
)) : __builtin_strcmp ((const char *) value[i].data, (const char
*) "down")))); })
== 0) {
5605
5606 if (!(uscf->flags & NGX_HTTP_UPSTREAM_DOWN0x0010)) {
5607 goto not_supported;
5608 }
5609
5610 us->down = 1;
5611
5612 continue;
5613 }
5614
5615 goto invalid;
5616 }
5617
5618 ngx_memzero(&u, sizeof(ngx_url_t))(void) memset(&u, 0, sizeof(ngx_url_t));
5619
5620 u.url = value[1];
5621 u.default_port = 80;
5622
5623 if (ngx_parse_url(cf->pool, &u) != NGX_OK0) {
5624 if (u.err) {
5625 ngx_conf_log_error(NGX_LOG_EMERG1, cf, 0,
5626 "%s in upstream \"%V\"", u.err, &u.url);
5627 }
5628
5629 return NGX_CONF_ERROR(void *) -1;
5630 }
5631
5632 us->name = u.url;
5633 us->addrs = u.addrs;
5634 us->naddrs = u.naddrs;
5635 us->weight = weight;
5636 us->max_fails = max_fails;
5637 us->fail_timeout = fail_timeout;
5638
5639 return NGX_CONF_OK((void*)0);
5640
5641invalid:
5642
5643 ngx_conf_log_error(NGX_LOG_EMERG1, cf, 0,
5644 "invalid parameter \"%V\"", &value[i]);
5645
5646 return NGX_CONF_ERROR(void *) -1;
5647
5648not_supported:
5649
5650 ngx_conf_log_error(NGX_LOG_EMERG1, cf, 0,
5651 "balancing method does not support parameter \"%V\"",
5652 &value[i]);
5653
5654 return NGX_CONF_ERROR(void *) -1;
5655}
5656
5657
5658ngx_http_upstream_srv_conf_t *
5659ngx_http_upstream_add(ngx_conf_t *cf, ngx_url_t *u, ngx_uint_t flags)
5660{
5661 ngx_uint_t i;
5662 ngx_http_upstream_server_t *us;
5663 ngx_http_upstream_srv_conf_t *uscf, **uscfp;
5664 ngx_http_upstream_main_conf_t *umcf;
5665
5666 if (!(flags & NGX_HTTP_UPSTREAM_CREATE0x0001)) {
5667
5668 if (ngx_parse_url(cf->pool, u) != NGX_OK0) {
5669 if (u->err) {
5670 ngx_conf_log_error(NGX_LOG_EMERG1, cf, 0,
5671 "%s in upstream \"%V\"", u->err, &u->url);
5672 }
5673
5674 return NULL((void*)0);
5675 }
5676 }
5677
5678 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]
;
5679
5680 uscfp = umcf->upstreams.elts;
5681
5682 for (i = 0; i < umcf->upstreams.nelts; i++) {
5683
5684 if (uscfp[i]->host.len != u->host.len
5685 || ngx_strncasecmp(uscfp[i]->host.data, u->host.data, u->host.len)
5686 != 0)
5687 {
5688 continue;
5689 }
5690
5691 if ((flags & NGX_HTTP_UPSTREAM_CREATE0x0001)
5692 && (uscfp[i]->flags & NGX_HTTP_UPSTREAM_CREATE0x0001))
5693 {
5694 ngx_conf_log_error(NGX_LOG_EMERG1, cf, 0,
5695 "duplicate upstream \"%V\"", &u->host);
5696 return NULL((void*)0);
5697 }
5698
5699 if ((uscfp[i]->flags & NGX_HTTP_UPSTREAM_CREATE0x0001) && !u->no_port) {
5700 ngx_conf_log_error(NGX_LOG_WARN5, cf, 0,
5701 "upstream \"%V\" may not have port %d",
5702 &u->host, u->port);
5703 return NULL((void*)0);
5704 }
5705
5706 if ((flags & NGX_HTTP_UPSTREAM_CREATE0x0001) && !uscfp[i]->no_port) {
5707 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)
5708 "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)
5709 &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)
5710 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)
;
5711 return NULL((void*)0);
5712 }
5713
5714 if (uscfp[i]->port && u->port
5715 && uscfp[i]->port != u->port)
5716 {
5717 continue;
5718 }
5719
5720 if (uscfp[i]->default_port && u->default_port
5721 && uscfp[i]->default_port != u->default_port)
5722 {
5723 continue;
5724 }
5725
5726 if (flags & NGX_HTTP_UPSTREAM_CREATE0x0001) {
5727 uscfp[i]->flags = flags;
5728 }
5729
5730 return uscfp[i];
5731 }
5732
5733 uscf = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_srv_conf_t));
5734 if (uscf == NULL((void*)0)) {
5735 return NULL((void*)0);
5736 }
5737
5738 uscf->flags = flags;
5739 uscf->host = u->host;
5740 uscf->file_name = cf->conf_file->file.name.data;
5741 uscf->line = cf->conf_file->line;
5742 uscf->port = u->port;
5743 uscf->default_port = u->default_port;
5744 uscf->no_port = u->no_port;
5745
5746 if (u->naddrs == 1 && (u->port || u->family == AF_UNIX1)) {
5747 uscf->servers = ngx_array_create(cf->pool, 1,
5748 sizeof(ngx_http_upstream_server_t));
5749 if (uscf->servers == NULL((void*)0)) {
5750 return NULL((void*)0);
5751 }
5752
5753 us = ngx_array_push(uscf->servers);
5754 if (us == NULL((void*)0)) {
5755 return NULL((void*)0);
5756 }
5757
5758 ngx_memzero(us, sizeof(ngx_http_upstream_server_t))(void) memset(us, 0, sizeof(ngx_http_upstream_server_t));
5759
5760 us->addrs = u->addrs;
5761 us->naddrs = 1;
5762 }
5763
5764 uscfp = ngx_array_push(&umcf->upstreams);
5765 if (uscfp == NULL((void*)0)) {
5766 return NULL((void*)0);
5767 }
5768
5769 *uscfp = uscf;
5770
5771 return uscf;
5772}
5773
5774
5775char *
5776ngx_http_upstream_bind_set_slot(ngx_conf_t *cf, ngx_command_t *cmd,
5777 void *conf)
5778{
5779 char *p = conf;
5780
5781 ngx_int_t rc;
5782 ngx_str_t *value;
5783 ngx_http_complex_value_t cv;
5784 ngx_http_upstream_local_t **plocal, *local;
5785 ngx_http_compile_complex_value_t ccv;
5786
5787 plocal = (ngx_http_upstream_local_t **) (p + cmd->offset);
5788
5789 if (*plocal != NGX_CONF_UNSET_PTR(void *) -1) {
5790 return "is duplicate";
5791 }
5792
5793 value = cf->args->elts;
5794
5795 if (cf->args->nelts == 2 && ngx_strcmp(value[1].data, "off")__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
((const char *) value[1].data) && __builtin_constant_p
((const char *) "off") && (__s1_len = strlen ((const
char *) value[1].data), __s2_len = strlen ((const char *) "off"
), (!((size_t)(const void *)(((const char *) value[1].data) +
1) - (size_t)(const void *)((const char *) value[1].data) ==
1) || __s1_len >= 4) && (!((size_t)(const void *)
(((const char *) "off") + 1) - (size_t)(const void *)((const char
*) "off") == 1) || __s2_len >= 4)) ? __builtin_strcmp ((const
char *) value[1].data, (const char *) "off") : (__builtin_constant_p
((const char *) value[1].data) && ((size_t)(const void
*)(((const char *) value[1].data) + 1) - (size_t)(const void
*)((const char *) value[1].data) == 1) && (__s1_len =
strlen ((const char *) value[1].data), __s1_len < 4) ? (__builtin_constant_p
((const char *) "off") && ((size_t)(const void *)(((
const char *) "off") + 1) - (size_t)(const void *)((const char
*) "off") == 1) ? __builtin_strcmp ((const char *) value[1].
data, (const char *) "off") : (__extension__ ({ const unsigned
char *__s2 = (const unsigned char *) (const char *) ((const char
*) "off"); int __result = (((const unsigned char *) (const char
*) ((const char *) value[1].data))[0] - __s2[0]); if (__s1_len
> 0 && __result == 0) { __result = (((const unsigned
char *) (const char *) ((const char *) value[1].data))[1] - __s2
[1]); if (__s1_len > 1 && __result == 0) { __result
= (((const unsigned char *) (const char *) ((const char *) value
[1].data))[2] - __s2[2]); if (__s1_len > 2 && __result
== 0) __result = (((const unsigned char *) (const char *) ((
const char *) value[1].data))[3] - __s2[3]); } } __result; })
)) : (__builtin_constant_p ((const char *) "off") && (
(size_t)(const void *)(((const char *) "off") + 1) - (size_t)
(const void *)((const char *) "off") == 1) && (__s2_len
= strlen ((const char *) "off"), __s2_len < 4) ? (__builtin_constant_p
((const char *) value[1].data) && ((size_t)(const void
*)(((const char *) value[1].data) + 1) - (size_t)(const void
*)((const char *) value[1].data) == 1) ? __builtin_strcmp ((
const char *) value[1].data, (const char *) "off") : (- (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) ((const char *) value[1].data); int __result = (((const
unsigned char *) (const char *) ((const char *) "off"))[0] -
__s2[0]); if (__s2_len > 0 && __result == 0) { __result
= (((const unsigned char *) (const char *) ((const char *) "off"
))[1] - __s2[1]); if (__s2_len > 1 && __result == 0
) { __result = (((const unsigned char *) (const char *) ((const
char *) "off"))[2] - __s2[2]); if (__s2_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) ((const char *) "off"))[3] - __s2[3]); } } __result; })))
) : __builtin_strcmp ((const char *) value[1].data, (const char
*) "off")))); })
== 0) {
5796 *plocal = NULL((void*)0);
5797 return NGX_CONF_OK((void*)0);
5798 }
5799
5800 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t))(void) memset(&ccv, 0, sizeof(ngx_http_compile_complex_value_t
))
;
5801
5802 ccv.cf = cf;
5803 ccv.value = &value[1];
5804 ccv.complex_value = &cv;
5805
5806 if (ngx_http_compile_complex_value(&ccv) != NGX_OK0) {
5807 return NGX_CONF_ERROR(void *) -1;
5808 }
5809
5810 local = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_local_t));
5811 if (local == NULL((void*)0)) {
5812 return NGX_CONF_ERROR(void *) -1;
5813 }
5814
5815 *plocal = local;
5816
5817 if (cv.lengths) {
5818 local->value = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t));
5819 if (local->value == NULL((void*)0)) {
5820 return NGX_CONF_ERROR(void *) -1;
5821 }
5822
5823 *local->value = cv;
5824
5825 } else {
5826 local->addr = ngx_palloc(cf->pool, sizeof(ngx_addr_t));
5827 if (local->addr == NULL((void*)0)) {
5828 return NGX_CONF_ERROR(void *) -1;
5829 }
5830
5831 rc = ngx_parse_addr(cf->pool, local->addr, value[1].data, value[1].len);
5832
5833 switch (rc) {
5834 case NGX_OK0:
5835 local->addr->name = value[1];
5836 break;
5837
5838 case NGX_DECLINED-5:
5839 ngx_conf_log_error(NGX_LOG_EMERG1, cf, 0,
5840 "invalid address \"%V\"", &value[1]);
5841 /* fall through */
5842
5843 default:
5844 return NGX_CONF_ERROR(void *) -1;
5845 }
5846 }
5847
5848 if (cf->args->nelts > 2) {
5849 if (ngx_strcmp(value[2].data, "transparent")__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
((const char *) value[2].data) && __builtin_constant_p
((const char *) "transparent") && (__s1_len = strlen
((const char *) value[2].data), __s2_len = strlen ((const char
*) "transparent"), (!((size_t)(const void *)(((const char *)
value[2].data) + 1) - (size_t)(const void *)((const char *) value
[2].data) == 1) || __s1_len >= 4) && (!((size_t)(const
void *)(((const char *) "transparent") + 1) - (size_t)(const
void *)((const char *) "transparent") == 1) || __s2_len >=
4)) ? __builtin_strcmp ((const char *) value[2].data, (const
char *) "transparent") : (__builtin_constant_p ((const char *
) value[2].data) && ((size_t)(const void *)(((const char
*) value[2].data) + 1) - (size_t)(const void *)((const char *
) value[2].data) == 1) && (__s1_len = strlen ((const char
*) value[2].data), __s1_len < 4) ? (__builtin_constant_p (
(const char *) "transparent") && ((size_t)(const void
*)(((const char *) "transparent") + 1) - (size_t)(const void
*)((const char *) "transparent") == 1) ? __builtin_strcmp ((
const char *) value[2].data, (const char *) "transparent") : (
__extension__ ({ const unsigned char *__s2 = (const unsigned char
*) (const char *) ((const char *) "transparent"); int __result
= (((const unsigned char *) (const char *) ((const char *) value
[2].data))[0] - __s2[0]); if (__s1_len > 0 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
(const char *) value[2].data))[1] - __s2[1]); if (__s1_len >
1 && __result == 0) { __result = (((const unsigned char
*) (const char *) ((const char *) value[2].data))[2] - __s2[
2]); if (__s1_len > 2 && __result == 0) __result =
(((const unsigned char *) (const char *) ((const char *) value
[2].data))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p
((const char *) "transparent") && ((size_t)(const void
*)(((const char *) "transparent") + 1) - (size_t)(const void
*)((const char *) "transparent") == 1) && (__s2_len =
strlen ((const char *) "transparent"), __s2_len < 4) ? (__builtin_constant_p
((const char *) value[2].data) && ((size_t)(const void
*)(((const char *) value[2].data) + 1) - (size_t)(const void
*)((const char *) value[2].data) == 1) ? __builtin_strcmp ((
const char *) value[2].data, (const char *) "transparent") : (
- (__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) ((const char *) value[2].data); int __result
= (((const unsigned char *) (const char *) ((const char *) "transparent"
))[0] - __s2[0]); if (__s2_len > 0 && __result == 0
) { __result = (((const unsigned char *) (const char *) ((const
char *) "transparent"))[1] - __s2[1]); if (__s2_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) ((const char *) "transparent"))[2] - __s2[2]); if (__s2_len
> 2 && __result == 0) __result = (((const unsigned
char *) (const char *) ((const char *) "transparent"))[3] - __s2
[3]); } } __result; })))) : __builtin_strcmp ((const char *) value
[2].data, (const char *) "transparent")))); })
== 0) {
5850#if (NGX_HAVE_TRANSPARENT_PROXY1)
5851 local->transparent = 1;
5852#else
5853 ngx_conf_log_error(NGX_LOG_EMERG1, cf, 0,
5854 "transparent proxying is not supported "
5855 "on this platform, ignored");
5856#endif
5857 } else {
5858 ngx_conf_log_error(NGX_LOG_EMERG1, cf, 0,
5859 "invalid parameter \"%V\"", &value[2]);
5860 return NGX_CONF_ERROR(void *) -1;
5861 }
5862 }
5863
5864 return NGX_CONF_OK((void*)0);
5865}
5866
5867
5868static ngx_int_t
5869ngx_http_upstream_set_local(ngx_http_request_t *r, ngx_http_upstream_t *u,
5870 ngx_http_upstream_local_t *local)
5871{
5872 ngx_int_t rc;
5873 ngx_str_t val;
5874 ngx_addr_t *addr;
5875
5876 if (local == NULL((void*)0)) {
5877 u->peer.local = NULL((void*)0);
5878 return NGX_OK0;
5879 }
5880
5881#if (NGX_HAVE_TRANSPARENT_PROXY1)
5882 u->peer.transparent = local->transparent;
5883#endif
5884
5885 if (local->value == NULL((void*)0)) {
5886 u->peer.local = local->addr;
5887 return NGX_OK0;
5888 }
5889
5890 if (ngx_http_complex_value(r, local->value, &val) != NGX_OK0) {
5891 return NGX_ERROR-1;
5892 }
5893
5894 if (val.len == 0) {
5895 return NGX_OK0;
5896 }
5897
5898 addr = ngx_palloc(r->pool, sizeof(ngx_addr_t));
5899 if (addr == NULL((void*)0)) {
5900 return NGX_ERROR-1;
5901 }
5902
5903 rc = ngx_parse_addr(r->pool, addr, val.data, val.len);
5904 if (rc == NGX_ERROR-1) {
5905 return NGX_ERROR-1;
5906 }
5907
5908 if (rc != NGX_OK0) {
5909 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)
5910 "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)
;
5911 return NGX_OK0;
5912 }
5913
5914 addr->name = val;
5915 u->peer.local = addr;
5916
5917 return NGX_OK0;
5918}
5919
5920
5921char *
5922ngx_http_upstream_param_set_slot(ngx_conf_t *cf, ngx_command_t *cmd,
5923 void *conf)
5924{
5925 char *p = conf;
5926
5927 ngx_str_t *value;
5928 ngx_array_t **a;
5929 ngx_http_upstream_param_t *param;
5930
5931 a = (ngx_array_t **) (p + cmd->offset);
5932
5933 if (*a == NULL((void*)0)) {
5934 *a = ngx_array_create(cf->pool, 4, sizeof(ngx_http_upstream_param_t));
5935 if (*a == NULL((void*)0)) {
5936 return NGX_CONF_ERROR(void *) -1;
5937 }
5938 }
5939
5940 param = ngx_array_push(*a);
5941 if (param == NULL((void*)0)) {
5942 return NGX_CONF_ERROR(void *) -1;
5943 }
5944
5945 value = cf->args->elts;
5946
5947 param->key = value[1];
5948 param->value = value[2];
5949 param->skip_empty = 0;
5950
5951 if (cf->args->nelts == 4) {
5952 if (ngx_strcmp(value[3].data, "if_not_empty")__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
((const char *) value[3].data) && __builtin_constant_p
((const char *) "if_not_empty") && (__s1_len = strlen
((const char *) value[3].data), __s2_len = strlen ((const char
*) "if_not_empty"), (!((size_t)(const void *)(((const char *
) value[3].data) + 1) - (size_t)(const void *)((const char *)
value[3].data) == 1) || __s1_len >= 4) && (!((size_t
)(const void *)(((const char *) "if_not_empty") + 1) - (size_t
)(const void *)((const char *) "if_not_empty") == 1) || __s2_len
>= 4)) ? __builtin_strcmp ((const char *) value[3].data, (
const char *) "if_not_empty") : (__builtin_constant_p ((const
char *) value[3].data) && ((size_t)(const void *)(((
const char *) value[3].data) + 1) - (size_t)(const void *)((const
char *) value[3].data) == 1) && (__s1_len = strlen (
(const char *) value[3].data), __s1_len < 4) ? (__builtin_constant_p
((const char *) "if_not_empty") && ((size_t)(const void
*)(((const char *) "if_not_empty") + 1) - (size_t)(const void
*)((const char *) "if_not_empty") == 1) ? __builtin_strcmp (
(const char *) value[3].data, (const char *) "if_not_empty") :
(__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) ((const char *) "if_not_empty"); int __result
= (((const unsigned char *) (const char *) ((const char *) value
[3].data))[0] - __s2[0]); if (__s1_len > 0 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
(const char *) value[3].data))[1] - __s2[1]); if (__s1_len >
1 && __result == 0) { __result = (((const unsigned char
*) (const char *) ((const char *) value[3].data))[2] - __s2[
2]); if (__s1_len > 2 && __result == 0) __result =
(((const unsigned char *) (const char *) ((const char *) value
[3].data))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p
((const char *) "if_not_empty") && ((size_t)(const void
*)(((const char *) "if_not_empty") + 1) - (size_t)(const void
*)((const char *) "if_not_empty") == 1) && (__s2_len
= strlen ((const char *) "if_not_empty"), __s2_len < 4) ?
(__builtin_constant_p ((const char *) value[3].data) &&
((size_t)(const void *)(((const char *) value[3].data) + 1) -
(size_t)(const void *)((const char *) value[3].data) == 1) ?
__builtin_strcmp ((const char *) value[3].data, (const char *
) "if_not_empty") : (- (__extension__ ({ const unsigned char *
__s2 = (const unsigned char *) (const char *) ((const char *)
value[3].data); int __result = (((const unsigned char *) (const
char *) ((const char *) "if_not_empty"))[0] - __s2[0]); if (
__s2_len > 0 && __result == 0) { __result = (((const
unsigned char *) (const char *) ((const char *) "if_not_empty"
))[1] - __s2[1]); if (__s2_len > 1 && __result == 0
) { __result = (((const unsigned char *) (const char *) ((const
char *) "if_not_empty"))[2] - __s2[2]); if (__s2_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) ((const char *) "if_not_empty"))[3] - __s2[3]); } } __result
; })))) : __builtin_strcmp ((const char *) value[3].data, (const
char *) "if_not_empty")))); })
!= 0) {
5953 ngx_conf_log_error(NGX_LOG_EMERG1, cf, 0,
5954 "invalid parameter \"%V\"", &value[3]);
5955 return NGX_CONF_ERROR(void *) -1;
5956 }
5957
5958 param->skip_empty = 1;
5959 }
5960
5961 return NGX_CONF_OK((void*)0);
5962}
5963
5964
5965ngx_int_t
5966ngx_http_upstream_hide_headers_hash(ngx_conf_t *cf,
5967 ngx_http_upstream_conf_t *conf, ngx_http_upstream_conf_t *prev,
5968 ngx_str_t *default_hide_headers, ngx_hash_init_t *hash)
5969{
5970 ngx_str_t *h;
5971 ngx_uint_t i, j;
5972 ngx_array_t hide_headers;
5973 ngx_hash_key_t *hk;
5974
5975 if (conf->hide_headers == NGX_CONF_UNSET_PTR(void *) -1
5976 && conf->pass_headers == NGX_CONF_UNSET_PTR(void *) -1)
5977 {
5978 conf->hide_headers = prev->hide_headers;
5979 conf->pass_headers = prev->pass_headers;
5980
5981 conf->hide_headers_hash = prev->hide_headers_hash;
5982
5983 if (conf->hide_headers_hash.buckets
5984#if (NGX_HTTP_CACHE1)
5985 && ((conf->cache == 0) == (prev->cache == 0))
5986#endif
5987 )
5988 {
5989 return NGX_OK0;
5990 }
5991
5992 } else {
5993 if (conf->hide_headers == NGX_CONF_UNSET_PTR(void *) -1) {
5994 conf->hide_headers = prev->hide_headers;
5995 }
5996
5997 if (conf->pass_headers == NGX_CONF_UNSET_PTR(void *) -1) {
5998 conf->pass_headers = prev->pass_headers;
5999 }
6000 }
6001
6002 if (ngx_array_init(&hide_headers, cf->temp_pool, 4, sizeof(ngx_hash_key_t))
6003 != NGX_OK0)
6004 {
6005 return NGX_ERROR-1;
6006 }
6007
6008 for (h = default_hide_headers; h->len; h++) {
6009 hk = ngx_array_push(&hide_headers);
6010 if (hk == NULL((void*)0)) {
6011 return NGX_ERROR-1;
6012 }
6013
6014 hk->key = *h;
6015 hk->key_hash = ngx_hash_key_lc(h->data, h->len);
6016 hk->value = (void *) 1;
6017 }
6018
6019 if (conf->hide_headers != NGX_CONF_UNSET_PTR(void *) -1) {
6020
6021 h = conf->hide_headers->elts;
6022
6023 for (i = 0; i < conf->hide_headers->nelts; i++) {
6024
6025 hk = hide_headers.elts;
6026
6027 for (j = 0; j < hide_headers.nelts; j++) {
6028 if (ngx_strcasecmp(h[i].data, hk[j].key.data) == 0) {
6029 goto exist;
6030 }
6031 }
6032
6033 hk = ngx_array_push(&hide_headers);
6034 if (hk == NULL((void*)0)) {
6035 return NGX_ERROR-1;
6036 }
6037
6038 hk->key = h[i];
6039 hk->key_hash = ngx_hash_key_lc(h[i].data, h[i].len);
6040 hk->value = (void *) 1;
6041
6042 exist:
6043
6044 continue;
6045 }
6046 }
6047
6048 if (conf->pass_headers != NGX_CONF_UNSET_PTR(void *) -1) {
6049
6050 h = conf->pass_headers->elts;
6051 hk = hide_headers.elts;
6052
6053 for (i = 0; i < conf->pass_headers->nelts; i++) {
6054 for (j = 0; j < hide_headers.nelts; j++) {
6055
6056 if (hk[j].key.data == NULL((void*)0)) {
6057 continue;
6058 }
6059
6060 if (ngx_strcasecmp(h[i].data, hk[j].key.data) == 0) {
6061 hk[j].key.data = NULL((void*)0);
6062 break;
6063 }
6064 }
6065 }
6066 }
6067
6068 hash->hash = &conf->hide_headers_hash;
6069 hash->key = ngx_hash_key_lc;
6070 hash->pool = cf->pool;
6071 hash->temp_pool = NULL((void*)0);
6072
6073 return ngx_hash_init(hash, hide_headers.elts, hide_headers.nelts);
6074}
6075
6076
6077static void *
6078ngx_http_upstream_create_main_conf(ngx_conf_t *cf)
6079{
6080 ngx_http_upstream_main_conf_t *umcf;
6081
6082 umcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_main_conf_t));
6083 if (umcf == NULL((void*)0)) {
6084 return NULL((void*)0);
6085 }
6086
6087 if (ngx_array_init(&umcf->upstreams, cf->pool, 4,
6088 sizeof(ngx_http_upstream_srv_conf_t *))
6089 != NGX_OK0)
6090 {
6091 return NULL((void*)0);
6092 }
6093
6094 return umcf;
6095}
6096
6097
6098static char *
6099ngx_http_upstream_init_main_conf(ngx_conf_t *cf, void *conf)
6100{
6101 ngx_http_upstream_main_conf_t *umcf = conf;
6102
6103 ngx_uint_t i;
6104 ngx_array_t headers_in;
6105 ngx_hash_key_t *hk;
6106 ngx_hash_init_t hash;
6107 ngx_http_upstream_init_pt init;
6108 ngx_http_upstream_header_t *header;
6109 ngx_http_upstream_srv_conf_t **uscfp;
6110
6111 uscfp = umcf->upstreams.elts;
6112
6113 for (i = 0; i < umcf->upstreams.nelts; i++) {
6114
6115 init = uscfp[i]->peer.init_upstream ? uscfp[i]->peer.init_upstream:
6116 ngx_http_upstream_init_round_robin;
6117
6118 if (init(cf, uscfp[i]) != NGX_OK0) {
6119 return NGX_CONF_ERROR(void *) -1;
6120 }
6121 }
6122
6123
6124 /* upstream_headers_in_hash */
6125
6126 if (ngx_array_init(&headers_in, cf->temp_pool, 32, sizeof(ngx_hash_key_t))
6127 != NGX_OK0)
6128 {
6129 return NGX_CONF_ERROR(void *) -1;
6130 }
6131
6132 for (header = ngx_http_upstream_headers_in; header->name.len; header++) {
6133 hk = ngx_array_push(&headers_in);
6134 if (hk == NULL((void*)0)) {
6135 return NGX_CONF_ERROR(void *) -1;
6136 }
6137
6138 hk->key = header->name;
6139 hk->key_hash = ngx_hash_key_lc(header->name.data, header->name.len);
6140 hk->value = header;
6141 }
6142
6143 hash.hash = &umcf->headers_in_hash;
6144 hash.key = ngx_hash_key_lc;
6145 hash.max_size = 512;
6146 hash.bucket_size = ngx_align(64, ngx_cacheline_size)(((64) + (ngx_cacheline_size - 1)) & ~(ngx_cacheline_size
- 1))
;
6147 hash.name = "upstream_headers_in_hash";
6148 hash.pool = cf->pool;
6149 hash.temp_pool = NULL((void*)0);
6150
6151 if (ngx_hash_init(&hash, headers_in.elts, headers_in.nelts) != NGX_OK0) {
6152 return NGX_CONF_ERROR(void *) -1;
6153 }
6154
6155 return NGX_CONF_OK((void*)0);
6156}