blob: 7a012c88d0b0d57aa9e49fe8d696032c2797b841 [file] [log] [blame]
Igor Sysoev04410502003-08-01 14:56:33 +00001
2#include <ngx_config.h>
3#include <ngx_core.h>
Igor Sysoev04410502003-08-01 14:56:33 +00004#include <ngx_http.h>
5#include <ngx_http_proxy_handler.h>
6
7
Igor Sysoeve6779222003-10-03 15:50:53 +00008static int ngx_http_proxy_handler(ngx_http_request_t *r);
Igor Sysoev6414b962003-10-24 16:10:38 +00009
Igor Sysoev78329332003-11-10 17:17:31 +000010static char *ngx_http_proxy_log_proxy_state(ngx_http_request_t *r, char *buf,
11 uintptr_t data);
12static char *ngx_http_proxy_log_cache_state(ngx_http_request_t *r, char *buf,
13 uintptr_t data);
14static char *ngx_http_proxy_log_reason(ngx_http_request_t *r, char *buf,
15 uintptr_t data);
16
17static int ngx_http_proxy_pre_conf(ngx_conf_t *cf);
Igor Sysoevae5c59c2003-08-14 06:00:28 +000018static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf);
Igor Sysoevdc9dd432003-10-22 16:38:26 +000019static char *ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf,
20 void *parent, void *child);
Igor Sysoevae5c59c2003-08-14 06:00:28 +000021
Igor Sysoevd404c972003-10-16 20:19:16 +000022static char *ngx_http_proxy_set_pass(ngx_conf_t *cf, ngx_command_t *cmd,
23 void *conf);
24static char *ngx_http_proxy_parse_upstream(ngx_str_t *url,
Igor Sysoeva1512b12003-11-03 17:33:31 +000025 ngx_http_proxy_upstream_conf_t *u);
Igor Sysoevd404c972003-10-16 20:19:16 +000026
Igor Sysoevae5c59c2003-08-14 06:00:28 +000027
Igor Sysoev68ee8f12003-10-30 08:51:06 +000028static ngx_conf_bitmask_t next_upstream_masks[] = {
29 { ngx_string("error"), NGX_HTTP_PROXY_FT_ERROR },
30 { ngx_string("timeout"), NGX_HTTP_PROXY_FT_TIMEOUT },
Igor Sysoev65977492003-11-02 22:56:18 +000031 { ngx_string("invalid_header"), NGX_HTTP_PROXY_FT_INVALID_HEADER },
Igor Sysoev68ee8f12003-10-30 08:51:06 +000032 { ngx_string("http_500"), NGX_HTTP_PROXY_FT_HTTP_500 },
Igor Sysoev65977492003-11-02 22:56:18 +000033 { ngx_string("http_404"), NGX_HTTP_PROXY_FT_HTTP_404 },
34 { ngx_null_string, 0 }
35};
36
37
38static ngx_conf_bitmask_t use_stale_masks[] = {
39 { ngx_string("error"), NGX_HTTP_PROXY_FT_ERROR },
40 { ngx_string("timeout"), NGX_HTTP_PROXY_FT_TIMEOUT },
41 { ngx_string("invalid_header"), NGX_HTTP_PROXY_FT_INVALID_HEADER },
42 { ngx_string("http_500"), NGX_HTTP_PROXY_FT_HTTP_500 },
43 { ngx_string("busy_lock"), NGX_HTTP_PROXY_FT_BUSY_LOCK },
44 { ngx_string("max_waiting"), NGX_HTTP_PROXY_FT_MAX_WAITING },
Igor Sysoev68ee8f12003-10-30 08:51:06 +000045 { ngx_null_string, 0 }
46};
Igor Sysoevd404c972003-10-16 20:19:16 +000047
Igor Sysoevcf80a702003-11-03 22:20:44 +000048
49static ngx_conf_num_bounds_t ngx_http_proxy_lm_factor_bounds = {
50 ngx_conf_check_num_bounds, 0, 100
51};
52
53
Igor Sysoev68ee8f12003-10-30 08:51:06 +000054static ngx_command_t ngx_http_proxy_commands[] = {
Igor Sysoevd404c972003-10-16 20:19:16 +000055
Igor Sysoev68ee8f12003-10-30 08:51:06 +000056 { ngx_string("proxy_pass"),
57 NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
58 ngx_http_proxy_set_pass,
59 NGX_HTTP_LOC_CONF_OFFSET,
60 0,
61 NULL },
Igor Sysoev10fc9ef2003-10-27 08:53:49 +000062
Igor Sysoev68ee8f12003-10-30 08:51:06 +000063 { ngx_string("proxy_request_buffer_size"),
64 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
65 ngx_conf_set_size_slot,
66 NGX_HTTP_LOC_CONF_OFFSET,
67 offsetof(ngx_http_proxy_loc_conf_t, request_buffer_size),
68 NULL },
Igor Sysoevdc9dd432003-10-22 16:38:26 +000069
Igor Sysoev68ee8f12003-10-30 08:51:06 +000070 { ngx_string("proxy_connect_timeout"),
71 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
72 ngx_conf_set_msec_slot,
73 NGX_HTTP_LOC_CONF_OFFSET,
74 offsetof(ngx_http_proxy_loc_conf_t, connect_timeout),
75 NULL },
Igor Sysoevdc9dd432003-10-22 16:38:26 +000076
Igor Sysoev68ee8f12003-10-30 08:51:06 +000077 { ngx_string("proxy_send_timeout"),
78 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
79 ngx_conf_set_msec_slot,
80 NGX_HTTP_LOC_CONF_OFFSET,
81 offsetof(ngx_http_proxy_loc_conf_t, send_timeout),
82 NULL },
Igor Sysoevdc9dd432003-10-22 16:38:26 +000083
Igor Sysoev68ee8f12003-10-30 08:51:06 +000084 { ngx_string("proxy_header_buffer_size"),
85 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
86 ngx_conf_set_size_slot,
87 NGX_HTTP_LOC_CONF_OFFSET,
88 offsetof(ngx_http_proxy_loc_conf_t, header_buffer_size),
89 NULL },
Igor Sysoevdc9dd432003-10-22 16:38:26 +000090
Igor Sysoev68ee8f12003-10-30 08:51:06 +000091 { ngx_string("proxy_read_timeout"),
92 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
93 ngx_conf_set_msec_slot,
94 NGX_HTTP_LOC_CONF_OFFSET,
95 offsetof(ngx_http_proxy_loc_conf_t, read_timeout),
96 NULL },
Igor Sysoevdc9dd432003-10-22 16:38:26 +000097
Igor Sysoev68ee8f12003-10-30 08:51:06 +000098 { ngx_string("proxy_buffers"),
99 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
100 ngx_conf_set_bufs_slot,
101 NGX_HTTP_LOC_CONF_OFFSET,
102 offsetof(ngx_http_proxy_loc_conf_t, bufs),
103 NULL },
Igor Sysoevdc9dd432003-10-22 16:38:26 +0000104
Igor Sysoev68ee8f12003-10-30 08:51:06 +0000105 { ngx_string("proxy_busy_buffers_size"),
106 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
107 ngx_conf_set_size_slot,
108 NGX_HTTP_LOC_CONF_OFFSET,
109 offsetof(ngx_http_proxy_loc_conf_t, busy_buffers_size),
110 NULL },
Igor Sysoevdc9dd432003-10-22 16:38:26 +0000111
Igor Sysoev65977492003-11-02 22:56:18 +0000112 { ngx_string("proxy_cache_path"),
113 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234,
114 ngx_conf_set_path_slot,
115 NGX_HTTP_LOC_CONF_OFFSET,
116 offsetof(ngx_http_proxy_loc_conf_t, cache_path),
Igor Sysoev1b138ed2003-11-18 21:34:08 +0000117 ngx_garbage_collector_http_cache_handler },
Igor Sysoev65977492003-11-02 22:56:18 +0000118
Igor Sysoev68ee8f12003-10-30 08:51:06 +0000119 { ngx_string("proxy_temp_path"),
120 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234,
121 ngx_conf_set_path_slot,
122 NGX_HTTP_LOC_CONF_OFFSET,
123 offsetof(ngx_http_proxy_loc_conf_t, temp_path),
Igor Sysoev1b138ed2003-11-18 21:34:08 +0000124 ngx_garbage_collector_temp_handler },
Igor Sysoevdc9dd432003-10-22 16:38:26 +0000125
Igor Sysoev68ee8f12003-10-30 08:51:06 +0000126 { ngx_string("proxy_temp_file_write_size"),
127 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
128 ngx_conf_set_size_slot,
129 NGX_HTTP_LOC_CONF_OFFSET,
130 offsetof(ngx_http_proxy_loc_conf_t, temp_file_write_size),
131 NULL },
Igor Sysoevab0c4f52003-10-28 15:45:41 +0000132
Igor Sysoev65977492003-11-02 22:56:18 +0000133 { ngx_string("proxy_cache"),
134 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
135 ngx_conf_set_flag_slot,
136 NGX_HTTP_LOC_CONF_OFFSET,
137 offsetof(ngx_http_proxy_loc_conf_t, cache),
138 NULL },
139
Igor Sysoevcf80a702003-11-03 22:20:44 +0000140
Igor Sysoev9cc1ace2003-11-04 22:12:39 +0000141 { ngx_string("proxy_busy_lock"),
Igor Sysoev74e95c22003-11-09 20:03:38 +0000142 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE13,
Igor Sysoev9cc1ace2003-11-04 22:12:39 +0000143 ngx_http_set_busy_lock_slot,
144 NGX_HTTP_LOC_CONF_OFFSET,
145 offsetof(ngx_http_proxy_loc_conf_t, busy_lock),
146 NULL },
147
148
Igor Sysoev68ee8f12003-10-30 08:51:06 +0000149 { ngx_string("proxy_pass_server"),
150 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
151 ngx_conf_set_flag_slot,
152 NGX_HTTP_LOC_CONF_OFFSET,
153 offsetof(ngx_http_proxy_loc_conf_t, pass_server),
154 NULL },
155
Igor Sysoevcf80a702003-11-03 22:20:44 +0000156 { ngx_string("proxy_pass_x_accel_expires"),
157 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
158 ngx_conf_set_flag_slot,
159 NGX_HTTP_LOC_CONF_OFFSET,
160 offsetof(ngx_http_proxy_loc_conf_t, pass_x_accel_expires),
161 NULL },
162
163 { ngx_string("proxy_ignore_expires"),
164 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
165 ngx_conf_set_flag_slot,
166 NGX_HTTP_LOC_CONF_OFFSET,
167 offsetof(ngx_http_proxy_loc_conf_t, ignore_expires),
168 NULL },
169
170 { ngx_string("proxy_lm_factor"),
171 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
172 ngx_conf_set_num_slot,
173 NGX_HTTP_LOC_CONF_OFFSET,
174 offsetof(ngx_http_proxy_loc_conf_t, lm_factor),
175 &ngx_http_proxy_lm_factor_bounds },
176
177 { ngx_string("proxy_default_expires"),
178 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
179 ngx_conf_set_sec_slot,
180 NGX_HTTP_LOC_CONF_OFFSET,
181 offsetof(ngx_http_proxy_loc_conf_t, default_expires),
182 NULL },
183
184
Igor Sysoev68ee8f12003-10-30 08:51:06 +0000185 { ngx_string("proxy_next_upstream"),
186 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_ANY,
187 ngx_conf_set_bitmask_slot,
188 NGX_HTTP_LOC_CONF_OFFSET,
189 offsetof(ngx_http_proxy_loc_conf_t, next_upstream),
190 &next_upstream_masks },
191
Igor Sysoev65977492003-11-02 22:56:18 +0000192 { ngx_string("proxy_use_stale"),
193 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_ANY,
194 ngx_conf_set_bitmask_slot,
195 NGX_HTTP_LOC_CONF_OFFSET,
196 offsetof(ngx_http_proxy_loc_conf_t, use_stale),
197 &use_stale_masks },
198
Igor Sysoev68ee8f12003-10-30 08:51:06 +0000199 ngx_null_command
Igor Sysoev04410502003-08-01 14:56:33 +0000200};
201
202
203ngx_http_module_t ngx_http_proxy_module_ctx = {
Igor Sysoev78329332003-11-10 17:17:31 +0000204 ngx_http_proxy_pre_conf, /* pre conf */
205
Igor Sysoev04410502003-08-01 14:56:33 +0000206 NULL, /* create main configuration */
207 NULL, /* init main configuration */
208
209 NULL, /* create server configuration */
210 NULL, /* merge server configuration */
211
Igor Sysoevae5c59c2003-08-14 06:00:28 +0000212 ngx_http_proxy_create_loc_conf, /* create location configration */
Igor Sysoevdc9dd432003-10-22 16:38:26 +0000213 ngx_http_proxy_merge_loc_conf /* merge location configration */
Igor Sysoev04410502003-08-01 14:56:33 +0000214};
215
216
217ngx_module_t ngx_http_proxy_module = {
218 NGX_MODULE,
219 &ngx_http_proxy_module_ctx, /* module context */
220 ngx_http_proxy_commands, /* module directives */
221 NGX_HTTP_MODULE, /* module type */
Igor Sysoevd404c972003-10-16 20:19:16 +0000222 NULL, /* init module */
Igor Sysoev04410502003-08-01 14:56:33 +0000223 NULL /* init child */
224};
225
226
Igor Sysoev78329332003-11-10 17:17:31 +0000227
228static ngx_http_log_op_name_t ngx_http_proxy_log_fmt_ops[] = {
229 { ngx_string("proxy"), /* STUB */ 100,
230 ngx_http_proxy_log_proxy_state },
231 { ngx_string("proxy_cache_state"), sizeof("BYPASS") - 1,
232 ngx_http_proxy_log_cache_state },
233 { ngx_string("proxy_reason"), sizeof("BPS") - 1,
234 ngx_http_proxy_log_reason },
235 { ngx_null_string, 0, NULL }
236};
237
238
239
Igor Sysoev65977492003-11-02 22:56:18 +0000240ngx_http_header_t ngx_http_proxy_headers_in[] = {
Igor Sysoeve6779222003-10-03 15:50:53 +0000241 { ngx_string("Date"), offsetof(ngx_http_proxy_headers_in_t, date) },
242 { ngx_string("Server"), offsetof(ngx_http_proxy_headers_in_t, server) },
Igor Sysoeva1512b12003-11-03 17:33:31 +0000243
244 { ngx_string("Expires"), offsetof(ngx_http_proxy_headers_in_t, expires) },
245 { ngx_string("Cache-Control"),
246 offsetof(ngx_http_proxy_headers_in_t, cache_control) },
247 { ngx_string("X-Accel-Expires"),
248 offsetof(ngx_http_proxy_headers_in_t, x_accel_expires) },
249
Igor Sysoeve6779222003-10-03 15:50:53 +0000250 { ngx_string("Connection"),
251 offsetof(ngx_http_proxy_headers_in_t, connection) },
252 { ngx_string("Content-Type"),
253 offsetof(ngx_http_proxy_headers_in_t, content_type) },
254 { ngx_string("Content-Length"),
255 offsetof(ngx_http_proxy_headers_in_t, content_length) },
256 { ngx_string("Last-Modified"),
257 offsetof(ngx_http_proxy_headers_in_t, last_modified) },
Igor Sysoev1b138ed2003-11-18 21:34:08 +0000258 { ngx_string("Location"),
259 offsetof(ngx_http_proxy_headers_in_t, location) },
Igor Sysoev931a4002003-10-07 15:30:05 +0000260 { ngx_string("Accept-Ranges"),
261 offsetof(ngx_http_proxy_headers_in_t, accept_ranges) },
Igor Sysoeve6779222003-10-03 15:50:53 +0000262
263 { ngx_null_string, 0 }
264};
265
266
Igor Sysoev74e95c22003-11-09 20:03:38 +0000267static ngx_str_t cache_states[] = {
268 ngx_string("PASS"),
269 ngx_string("BYPASS"),
270 ngx_string("AUTH"),
271 ngx_string("PGNC"),
272 ngx_string("MISS"),
273 ngx_string("EXPR"),
274 ngx_string("AGED"),
275 ngx_string("HIT")
276};
277
278
Igor Sysoev78329332003-11-10 17:17:31 +0000279static ngx_str_t cache_reasons[] = {
Igor Sysoev74e95c22003-11-09 20:03:38 +0000280 ngx_string("BPS"),
281 ngx_string("XAE"),
282 ngx_string("CTL"),
283 ngx_string("EXP"),
284 ngx_string("MVD"),
285 ngx_string("LMF"),
286 ngx_string("PDE")
287};
288
289
Igor Sysoeve6779222003-10-03 15:50:53 +0000290static int ngx_http_proxy_handler(ngx_http_request_t *r)
Igor Sysoev04410502003-08-01 14:56:33 +0000291{
Igor Sysoeva1512b12003-11-03 17:33:31 +0000292 ngx_http_proxy_ctx_t *p;
Igor Sysoev04410502003-08-01 14:56:33 +0000293
294 ngx_http_create_ctx(r, p, ngx_http_proxy_module,
295 sizeof(ngx_http_proxy_ctx_t),
296 NGX_HTTP_INTERNAL_SERVER_ERROR);
297
Igor Sysoevae5c59c2003-08-14 06:00:28 +0000298 p->lcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
Igor Sysoev65977492003-11-02 22:56:18 +0000299 p->request = r;
300
301 /* TODO: we currently support reverse proxy only */
302 p->accel = 1;
303
Igor Sysoevcf80a702003-11-03 22:20:44 +0000304 ngx_init_array(p->states, r->pool, p->lcf->peers->number,
305 sizeof(ngx_http_proxy_state_t),
306 NGX_HTTP_INTERNAL_SERVER_ERROR);
307
308 if (!(p->state = ngx_push_array(&p->states))) {
309 return NGX_HTTP_INTERNAL_SERVER_ERROR;
310 }
311
Igor Sysoev9cc1ace2003-11-04 22:12:39 +0000312 ngx_memzero(p->state, sizeof(ngx_http_proxy_state_t));
313
Igor Sysoevcf80a702003-11-03 22:20:44 +0000314
Igor Sysoeve8732b02003-11-05 17:03:41 +0000315 if (!p->lcf->cache
316 || (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD))
317 {
Igor Sysoev74e95c22003-11-09 20:03:38 +0000318 p->state->cache_state = NGX_HTTP_PROXY_CACHE_PASS;
Igor Sysoevcf80a702003-11-03 22:20:44 +0000319
320 } else if (r->bypass_cache) {
Igor Sysoev74e95c22003-11-09 20:03:38 +0000321 p->state->cache_state = NGX_HTTP_PROXY_CACHE_BYPASS;
Igor Sysoevcf80a702003-11-03 22:20:44 +0000322
323 } else if (r->headers_in.authorization) {
Igor Sysoev74e95c22003-11-09 20:03:38 +0000324 p->state->cache_state = NGX_HTTP_PROXY_CACHE_AUTH;
Igor Sysoevcf80a702003-11-03 22:20:44 +0000325
326 } else if (r->no_cache) {
Igor Sysoev74e95c22003-11-09 20:03:38 +0000327 p->state->cache_state = NGX_HTTP_PROXY_CACHE_PGNC;
Igor Sysoevcf80a702003-11-03 22:20:44 +0000328 p->cachable = 1;
329
330 } else {
331 p->cachable = 1;
332 }
333
334
Igor Sysoev74e95c22003-11-09 20:03:38 +0000335 if (p->state->cache_state != 0) {
Igor Sysoev65977492003-11-02 22:56:18 +0000336 return ngx_http_proxy_request_upstream(p);
337 }
338
Igor Sysoev74e95c22003-11-09 20:03:38 +0000339 return ngx_http_proxy_get_cached_response(p);
340}
Igor Sysoev65977492003-11-02 22:56:18 +0000341
Igor Sysoev74e95c22003-11-09 20:03:38 +0000342
Igor Sysoev222a2ad2003-11-18 16:49:00 +0000343void ngx_http_proxy_check_broken_connection(ngx_event_t *wev)
344{
345 ngx_connection_t *c;
346 ngx_http_request_t *r;
347 ngx_http_proxy_ctx_t *p;
348
349 ngx_log_debug(wev->log, "http proxy check client");
350
351 c = wev->data;
352 r = c->data;
353 p = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
354
355#if (HAVE_KQUEUE)
356 if (wev->kq_eof) {
357 wev->eof = 1;
358
359 if (wev->kq_errno) {
360 wev->error = 1;
361 }
362
363 if (!p->cachable && p->upstream->peer.connection) {
364 ngx_log_error(NGX_LOG_INFO, wev->log, wev->kq_errno,
365 "client closed prematurely connection, "
366 "so upstream connection is closed too");
367 ngx_http_proxy_finalize_request(p, NGX_HTTP_CLIENT_CLOSED_REQUEST);
368 return;
369 }
370
371 ngx_log_error(NGX_LOG_INFO, wev->log, wev->kq_errno,
372 "client closed prematurely connection");
373
374 if (p->upstream == NULL || p->upstream->peer.connection == NULL) {
375 ngx_http_proxy_finalize_request(p, NGX_HTTP_CLIENT_CLOSED_REQUEST);
376 }
377 }
378#endif
379}
380
381
Igor Sysoev74e95c22003-11-09 20:03:38 +0000382void ngx_http_proxy_busy_lock_handler(ngx_event_t *rev)
383{
384 ngx_connection_t *c;
385 ngx_http_request_t *r;
386 ngx_http_proxy_ctx_t *p;
387
388 ngx_log_debug(rev->log, "busy lock");
389
390 c = rev->data;
391 r = c->data;
392 p = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
393 p->action = "waiting upstream in busy lock";
394
Igor Sysoev222a2ad2003-11-18 16:49:00 +0000395 if (p->request->connection->write->eof) {
396 ngx_http_busy_unlock(p->lcf->busy_lock, &p->busy_lock);
397 ngx_http_proxy_finalize_request(p, NGX_HTTP_CLIENT_CLOSED_REQUEST);
398 return;
399 }
400
Igor Sysoev74e95c22003-11-09 20:03:38 +0000401 if (rev->timedout) {
402 rev->timedout = 0;
403 p->busy_lock.time++;
404 p->state->bl_time = p->busy_lock.time;
405 if (p->state->cache_state < NGX_HTTP_PROXY_CACHE_MISS) {
406 ngx_http_proxy_upstream_busy_lock(p);
407
408 } else {
409 ngx_http_proxy_cache_busy_lock(p);
410 }
411
412 return;
Igor Sysoeve8732b02003-11-05 17:03:41 +0000413 }
414
Igor Sysoev74e95c22003-11-09 20:03:38 +0000415 ngx_log_debug(rev->log, "client sent while busy lock");
Igor Sysoev9cc1ace2003-11-04 22:12:39 +0000416
Igor Sysoev74e95c22003-11-09 20:03:38 +0000417 /*
418 * TODO: kevent() notify about error, otherwise we need to
Igor Sysoev222a2ad2003-11-18 16:49:00 +0000419 * call ngx_peek(): recv(MSG_PEEK) to get errno. THINK about aio
Igor Sysoev74e95c22003-11-09 20:03:38 +0000420 * if there's no error we need to disable event.
421 */
422
Igor Sysoev222a2ad2003-11-18 16:49:00 +0000423#if 0
Igor Sysoev74e95c22003-11-09 20:03:38 +0000424#if (HAVE_KQUEUE)
425
426 if ((ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) && rev->kq_eof) {
Igor Sysoev222a2ad2003-11-18 16:49:00 +0000427 ngx_http_busy_unlock(p->lcf->busy_lock, &p->busy_lock);
Igor Sysoev74e95c22003-11-09 20:03:38 +0000428
429 ngx_del_timer(rev);
430
431 ngx_log_error(NGX_LOG_ERR, c->log, rev->kq_errno,
432 "client() closed connection");
433
434 if (ngx_del_event(rev, NGX_READ_EVENT, NGX_CLOSE_EVENT) == NGX_ERROR) {
435 ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
436 return;
437 }
438
Igor Sysoev222a2ad2003-11-18 16:49:00 +0000439 ngx_http_proxy_finalize_request(p, NGX_HTTP_CLIENT_CLOSED_REQUEST);
Igor Sysoev74e95c22003-11-09 20:03:38 +0000440 return;
Igor Sysoev65977492003-11-02 22:56:18 +0000441 }
442
Igor Sysoev74e95c22003-11-09 20:03:38 +0000443#endif
Igor Sysoev222a2ad2003-11-18 16:49:00 +0000444#endif
Igor Sysoev65977492003-11-02 22:56:18 +0000445
Igor Sysoevfe0f5cc2003-10-31 16:05:33 +0000446}
447
448
Igor Sysoeva1512b12003-11-03 17:33:31 +0000449void ngx_http_proxy_finalize_request(ngx_http_proxy_ctx_t *p, int rc)
Igor Sysoev931a4002003-10-07 15:30:05 +0000450{
Igor Sysoev2b0c76c2003-10-27 21:01:00 +0000451 ngx_log_debug(p->request->connection->log,
452 "finalize http proxy request");
453
Igor Sysoev74e95c22003-11-09 20:03:38 +0000454 if (p->upstream && p->upstream->peer.connection) {
Igor Sysoeve8732b02003-11-05 17:03:41 +0000455 ngx_http_proxy_close_connection(p);
Igor Sysoev931a4002003-10-07 15:30:05 +0000456 }
457
Igor Sysoev9760a132003-10-21 07:47:21 +0000458 if (p->header_sent
459 && (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE))
460 {
Igor Sysoev931a4002003-10-07 15:30:05 +0000461 rc = 0;
462 }
463
Igor Sysoev74e95c22003-11-09 20:03:38 +0000464 if (p->saved_ctx) {
465 p->request->connection->log->data = p->saved_ctx;
466 p->request->connection->log->handler = p->saved_handler;
467 }
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000468
Igor Sysoev931a4002003-10-07 15:30:05 +0000469 ngx_http_finalize_request(p->request, rc);
Igor Sysoev931a4002003-10-07 15:30:05 +0000470}
471
472
Igor Sysoeve8732b02003-11-05 17:03:41 +0000473void ngx_http_proxy_close_connection(ngx_http_proxy_ctx_t *p)
Igor Sysoeve6779222003-10-03 15:50:53 +0000474{
Igor Sysoeve8732b02003-11-05 17:03:41 +0000475 ngx_connection_t *c;
476
477 c = p->upstream->peer.connection;
478 p->upstream->peer.connection = NULL;
479
480 if (p->lcf->busy_lock) {
Igor Sysoev74e95c22003-11-09 20:03:38 +0000481 p->lcf->busy_lock->busy--;
Igor Sysoeve8732b02003-11-05 17:03:41 +0000482 }
483
Igor Sysoev65977492003-11-02 22:56:18 +0000484 ngx_log_debug(c->log, "proxy close connection: %d" _ c->fd);
Igor Sysoeve6779222003-10-03 15:50:53 +0000485
486 if (c->fd == -1) {
Igor Sysoev931a4002003-10-07 15:30:05 +0000487#if 0
Igor Sysoeve6779222003-10-03 15:50:53 +0000488 ngx_log_error(NGX_LOG_ALERT, c->log, 0, "connection already closed");
Igor Sysoev931a4002003-10-07 15:30:05 +0000489#endif
Igor Sysoeve6779222003-10-03 15:50:53 +0000490 return;
491 }
492
493 if (c->read->timer_set) {
494 ngx_del_timer(c->read);
Igor Sysoeve6779222003-10-03 15:50:53 +0000495 }
496
497 if (c->write->timer_set) {
498 ngx_del_timer(c->write);
Igor Sysoeve6779222003-10-03 15:50:53 +0000499 }
500
Igor Sysoevfd3e3742003-10-08 04:34:07 +0000501 /* TODO: move connection to the connection pool */
502
Igor Sysoeve6779222003-10-03 15:50:53 +0000503 if (ngx_del_conn) {
504 ngx_del_conn(c);
505
506 } else {
507 if (c->read->active) {
508 ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT);
509 }
510
511 if (c->write->active) {
512 ngx_del_event(c->write, NGX_WRITE_EVENT, NGX_CLOSE_EVENT);
513 }
514 }
515
516 if (ngx_close_socket(c->fd) == -1) {
517 ngx_log_error(NGX_LOG_ALERT, c->log, ngx_socket_errno,
518 ngx_close_socket_n " failed");
519 }
520
521 c->fd = -1;
Igor Sysoev87a01ea2003-10-02 05:39:37 +0000522}
523
Igor Sysoev04410502003-08-01 14:56:33 +0000524
Igor Sysoeva1512b12003-11-03 17:33:31 +0000525size_t ngx_http_proxy_log_error(void *data, char *buf, size_t len)
Igor Sysoev04410502003-08-01 14:56:33 +0000526{
527 ngx_http_proxy_ctx_t *p = data;
528
Igor Sysoeva1512b12003-11-03 17:33:31 +0000529 ngx_http_request_t *r;
530 ngx_peer_connection_t *peer;
531
532 r = p->request;
533 peer = &p->upstream->peer;
534
Igor Sysoev04410502003-08-01 14:56:33 +0000535 return ngx_snprintf(buf, len,
Igor Sysoeva1512b12003-11-03 17:33:31 +0000536 " while %s, client: %s, URL: %s, upstream: %s%s%s%s%s",
537 p->action,
538 r->connection->addr_text.data,
539 r->unparsed_uri.data,
540 peer->peers->peers[peer->cur_peer].addr_port_text.data,
541 p->lcf->upstream->uri.data,
542 r->uri.data + p->lcf->upstream->location->len,
543 r->args.len ? "?" : "",
544 r->args.len ? r->args.data : "");
Igor Sysoev04410502003-08-01 14:56:33 +0000545}
Igor Sysoevae5c59c2003-08-14 06:00:28 +0000546
547
Igor Sysoev78329332003-11-10 17:17:31 +0000548static char *ngx_http_proxy_log_proxy_state(ngx_http_request_t *r, char *buf,
549 uintptr_t data)
550{
551 ngx_http_proxy_ctx_t *p;
552
Igor Sysoevd59a0472003-11-10 21:09:22 +0000553 p = ngx_http_get_module_err_ctx(r, ngx_http_proxy_module);
Igor Sysoev78329332003-11-10 17:17:31 +0000554
555 if (p == NULL) {
556 *buf = '-';
557 return buf + 1;
558 }
559
560 if (p->state->cache_state == 0) {
561 *buf++ = '-';
562
563 } else {
564 buf = ngx_cpymem(buf, cache_states[p->state->cache_state - 1].data,
565 cache_states[p->state->cache_state - 1].len);
566 }
567
568 *buf++ = '/';
569
Igor Sysoevd59a0472003-11-10 21:09:22 +0000570 *buf++ = '_';
Igor Sysoev78329332003-11-10 17:17:31 +0000571
572 *buf++ = '/';
573
Igor Sysoevd59a0472003-11-10 21:09:22 +0000574 *buf++ = '_';
575
576 *buf++ = '/';
577
578 *buf++ = '_';
Igor Sysoev78329332003-11-10 17:17:31 +0000579
580 *buf++ = ' ';
581
582 if (p->state->status == 0) {
583 *buf++ = '-';
584
585 } else {
586 buf += ngx_snprintf(buf, 4, "%d", p->state->status);
587 }
588
589 *buf++ = '/';
590
591 if (p->state->reason == 0) {
592 *buf++ = '-';
593
594 } else {
595 buf = ngx_cpymem(buf, cache_reasons[p->state->reason - 1].data,
596 cache_reasons[p->state->reason - 1].len);
597 }
598
599 *buf++ = '/';
600
601 if (p->state->reason >= NGX_HTTP_PROXY_CACHE_XAE) {
602 *buf++ = '-';
603
604 } else {
605 buf += ngx_snprintf(buf, NGX_TIME_LEN, TIME_FMT, p->state->expires);
606 }
607
Igor Sysoevd59a0472003-11-10 21:09:22 +0000608 *buf++ = ' ';
609 *buf++ = '_';
610
Igor Sysoev78329332003-11-10 17:17:31 +0000611 return buf;
612}
613
614
615static char *ngx_http_proxy_log_cache_state(ngx_http_request_t *r, char *buf,
616 uintptr_t data)
617{
618 ngx_http_proxy_ctx_t *p;
619
Igor Sysoevd59a0472003-11-10 21:09:22 +0000620 p = ngx_http_get_module_err_ctx(r, ngx_http_proxy_module);
Igor Sysoev78329332003-11-10 17:17:31 +0000621
622 if (p == NULL || p->state->cache_state == 0) {
623 *buf = '-';
624 return buf + 1;
625 }
626
627 return ngx_cpymem(buf, cache_states[p->state->cache_state - 1].data,
628 cache_states[p->state->cache_state - 1].len);
629}
630
631
632static char *ngx_http_proxy_log_reason(ngx_http_request_t *r, char *buf,
633 uintptr_t data)
634{
635 ngx_http_proxy_ctx_t *p;
636
Igor Sysoevd59a0472003-11-10 21:09:22 +0000637 p = ngx_http_get_module_err_ctx(r, ngx_http_proxy_module);
Igor Sysoev78329332003-11-10 17:17:31 +0000638
639 if (p == NULL || p->state->reason == 0) {
640 *buf = '-';
641 return buf + 1;
642 }
643
644 return ngx_cpymem(buf, cache_reasons[p->state->reason - 1].data,
645 cache_reasons[p->state->reason - 1].len);
646}
647
648
649static int ngx_http_proxy_pre_conf(ngx_conf_t *cf)
650{
651 ngx_http_log_op_name_t *op;
652
653 for (op = ngx_http_proxy_log_fmt_ops; op->name.len; op++) { /* void */ }
654 op->op = NULL;
655
656 op = ngx_http_log_fmt_ops;
657
658 for (op = ngx_http_log_fmt_ops; op->op; op++) {
659 if (op->name.len == 0) {
660 op = (ngx_http_log_op_name_t *) op->op;
661 }
662 }
663
664 op->op = (ngx_http_log_op_pt) ngx_http_proxy_log_fmt_ops;
665
666 return NGX_OK;
667}
668
669
Igor Sysoevae5c59c2003-08-14 06:00:28 +0000670static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
671{
672 ngx_http_proxy_loc_conf_t *conf;
673
674 ngx_test_null(conf,
675 ngx_pcalloc(cf->pool, sizeof(ngx_http_proxy_loc_conf_t)),
676 NGX_CONF_ERROR);
677
Igor Sysoevdc9dd432003-10-22 16:38:26 +0000678 /* set by ngx_pcalloc():
Igor Sysoevae5c59c2003-08-14 06:00:28 +0000679
Igor Sysoevdc9dd432003-10-22 16:38:26 +0000680 conf->bufs.num = 0;
Igor Sysoevae5c59c2003-08-14 06:00:28 +0000681
Igor Sysoevdc9dd432003-10-22 16:38:26 +0000682 conf->path = NULL;
Igor Sysoev931a4002003-10-07 15:30:05 +0000683
Igor Sysoev68ee8f12003-10-30 08:51:06 +0000684 conf->next_upstream = 0;
Igor Sysoev65977492003-11-02 22:56:18 +0000685 conf->use_stale = 0;
Igor Sysoev68ee8f12003-10-30 08:51:06 +0000686
Igor Sysoevdc9dd432003-10-22 16:38:26 +0000687 conf->upstreams = NULL;
688 conf->peers = NULL;
Igor Sysoev9760a132003-10-21 07:47:21 +0000689
Igor Sysoev65977492003-11-02 22:56:18 +0000690 conf->cache_path = NULL;
691 conf->temp_path = NULL;
692
Igor Sysoev9cc1ace2003-11-04 22:12:39 +0000693 conf->busy_lock = NULL;
694
Igor Sysoevdc9dd432003-10-22 16:38:26 +0000695 */
Igor Sysoev9760a132003-10-21 07:47:21 +0000696
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000697 conf->request_buffer_size = NGX_CONF_UNSET;
Igor Sysoevdc9dd432003-10-22 16:38:26 +0000698 conf->connect_timeout = NGX_CONF_UNSET;
699 conf->send_timeout = NGX_CONF_UNSET;
700 conf->header_buffer_size = NGX_CONF_UNSET;
701 conf->read_timeout = NGX_CONF_UNSET;
702 conf->busy_buffers_size = NGX_CONF_UNSET;
Igor Sysoev9760a132003-10-21 07:47:21 +0000703
Igor Sysoevdc9dd432003-10-22 16:38:26 +0000704 /*
705 * "proxy_max_temp_file_size" is hardcoded to 1G for reverse proxy,
706 * it should be configurable in the generic proxy
707 */
708 conf->max_temp_file_size = 1024 * 1024 * 1024;
Igor Sysoev9760a132003-10-21 07:47:21 +0000709
Igor Sysoevdc9dd432003-10-22 16:38:26 +0000710 conf->temp_file_write_size = NGX_CONF_UNSET;
Igor Sysoev931a4002003-10-07 15:30:05 +0000711
Igor Sysoevdc9dd432003-10-22 16:38:26 +0000712 /* "proxy_cyclic_temp_file" is disabled */
713 conf->cyclic_temp_file = 0;
Igor Sysoevae5c59c2003-08-14 06:00:28 +0000714
Igor Sysoev65977492003-11-02 22:56:18 +0000715 conf->cache = NGX_CONF_UNSET;
716
Igor Sysoevab0c4f52003-10-28 15:45:41 +0000717 conf->pass_server = NGX_CONF_UNSET;
Igor Sysoevcf80a702003-11-03 22:20:44 +0000718 conf->pass_x_accel_expires = NGX_CONF_UNSET;
719 conf->ignore_expires = NGX_CONF_UNSET;
720 conf->lm_factor = NGX_CONF_UNSET;
721 conf->default_expires = NGX_CONF_UNSET;
Igor Sysoevab0c4f52003-10-28 15:45:41 +0000722
Igor Sysoevae5c59c2003-08-14 06:00:28 +0000723 return conf;
724}
Igor Sysoevd404c972003-10-16 20:19:16 +0000725
726
Igor Sysoevdc9dd432003-10-22 16:38:26 +0000727static char *ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf,
728 void *parent, void *child)
729{
730 ngx_http_proxy_loc_conf_t *prev = parent;
731 ngx_http_proxy_loc_conf_t *conf = child;
732
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000733 ngx_conf_merge_size_value(conf->request_buffer_size,
734 prev->request_buffer_size, 8192);
Igor Sysoevdc9dd432003-10-22 16:38:26 +0000735 ngx_conf_merge_msec_value(conf->connect_timeout,
736 prev->connect_timeout, 60000);
737 ngx_conf_merge_msec_value(conf->send_timeout, prev->send_timeout, 30000);
738 ngx_conf_merge_size_value(conf->header_buffer_size,
739 prev->header_buffer_size, 4096);
740 ngx_conf_merge_msec_value(conf->read_timeout, prev->read_timeout, 30000);
741 ngx_conf_merge_bufs_value(conf->bufs, prev->bufs, 8, 4096);
742 ngx_conf_merge_size_value(conf->busy_buffers_size,
743 prev->busy_buffers_size, 8192);
744
745#if 0
746 if (conf->max_temp_file_size > conf->bufs.size) {
747 return "\"proxy_max_temp_file\" must be greater "
748 "than one of the \"proxy_buffers\"";
749 }
750#endif
751
752 ngx_conf_merge_size_value(conf->temp_file_write_size,
753 prev->temp_file_write_size, 16384);
754
Igor Sysoev68ee8f12003-10-30 08:51:06 +0000755 ngx_conf_merge_bitmask_value(conf->next_upstream, prev->next_upstream,
Igor Sysoev65977492003-11-02 22:56:18 +0000756 (NGX_CONF_BITMASK_SET
757 |NGX_HTTP_PROXY_FT_ERROR
758 |NGX_HTTP_PROXY_FT_TIMEOUT));
759
760 ngx_conf_merge_bitmask_value(conf->use_stale, prev->use_stale,
761 NGX_CONF_BITMASK_SET);
762
763 ngx_conf_merge_path_value(conf->cache_path, prev->cache_path,
764 "cache", 1, 2, 0, cf->pool);
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000765
Igor Sysoevdc9dd432003-10-22 16:38:26 +0000766 ngx_conf_merge_path_value(conf->temp_path, prev->temp_path,
767 "temp", 1, 2, 0, cf->pool);
768
Igor Sysoev65977492003-11-02 22:56:18 +0000769 ngx_conf_merge_value(conf->cache, prev->cache, 0);
770
Igor Sysoev9cc1ace2003-11-04 22:12:39 +0000771
772 /* conf->cache must be merged */
773
774 if (conf->busy_lock == NULL) {
775 conf->busy_lock = prev->busy_lock;
776 }
777
Igor Sysoev74e95c22003-11-09 20:03:38 +0000778 if (conf->busy_lock && conf->cache && conf->busy_lock->md5 == NULL) {
Igor Sysoev9cc1ace2003-11-04 22:12:39 +0000779
Igor Sysoev74e95c22003-11-09 20:03:38 +0000780 /* ngx_calloc_shared() */
781 conf->busy_lock->md5_mask =
782 ngx_pcalloc(cf->pool, (conf->busy_lock->max_busy + 7) / 8);
783 if (conf->busy_lock->md5_mask == NULL) {
Igor Sysoeve8732b02003-11-05 17:03:41 +0000784 return NGX_CONF_ERROR;
785 }
786
Igor Sysoev9cc1ace2003-11-04 22:12:39 +0000787 /* 16 bytes are 128 bits of the md5 */
788
789 /* ngx_alloc_shared() */
Igor Sysoev74e95c22003-11-09 20:03:38 +0000790 conf->busy_lock->md5 = ngx_palloc(cf->pool,
791 16 * conf->busy_lock->max_busy);
792 if (conf->busy_lock->md5 == NULL) {
Igor Sysoev9cc1ace2003-11-04 22:12:39 +0000793 return NGX_CONF_ERROR;
794 }
795 }
796
797
Igor Sysoevab0c4f52003-10-28 15:45:41 +0000798 ngx_conf_merge_value(conf->pass_server, prev->pass_server, 0);
Igor Sysoevcf80a702003-11-03 22:20:44 +0000799 ngx_conf_merge_value(conf->pass_x_accel_expires,
800 prev->pass_x_accel_expires, 0);
801 ngx_conf_merge_value(conf->ignore_expires, prev->ignore_expires, 0);
802 ngx_conf_merge_value(conf->lm_factor, prev->lm_factor, 0);
803 ngx_conf_merge_sec_value(conf->default_expires, prev->default_expires, 0);
Igor Sysoevab0c4f52003-10-28 15:45:41 +0000804
Igor Sysoevdc9dd432003-10-22 16:38:26 +0000805 return NULL;
806}
807
808
809
Igor Sysoevd404c972003-10-16 20:19:16 +0000810static char *ngx_http_proxy_set_pass(ngx_conf_t *cf, ngx_command_t *cmd,
811 void *conf)
812{
813 ngx_http_proxy_loc_conf_t *lcf = conf;
814
815 int i, len;
816 char *err, *host;
817 ngx_str_t *value;
818 struct hostent *h;
819 u_int32_t addr;
820 ngx_http_conf_ctx_t *ctx;
821 ngx_http_core_loc_conf_t *clcf;
822
823
824 value = cf->args->elts;
825
826 if (ngx_strncasecmp(value[1].data, "http://", 7) != 0) {
827 return "invalid URL prefix";
828 }
829
830 ngx_test_null(lcf->upstream,
Igor Sysoeva1512b12003-11-03 17:33:31 +0000831 ngx_pcalloc(cf->pool, sizeof(ngx_http_proxy_upstream_conf_t)),
Igor Sysoevd404c972003-10-16 20:19:16 +0000832 NGX_CONF_ERROR);
833
Igor Sysoev65977492003-11-02 22:56:18 +0000834 lcf->upstream->url.len = value[1].len;
835 if (!(lcf->upstream->url.data = ngx_palloc(cf->pool, value[1].len + 1))) {
836 return NGX_CONF_ERROR;
837 }
838 ngx_cpystrn(lcf->upstream->url.data, value[1].data, value[1].len + 1);
839
Igor Sysoevd404c972003-10-16 20:19:16 +0000840 value[1].data += 7;
841 value[1].len -= 7;
842
843 err = ngx_http_proxy_parse_upstream(&value[1], lcf->upstream);
844
845 if (err) {
846 return err;
847 }
848
849 ngx_test_null(host, ngx_palloc(cf->pool, lcf->upstream->host.len + 1),
850 NGX_CONF_ERROR);
851 ngx_cpystrn(host, lcf->upstream->host.data, lcf->upstream->host.len + 1);
852
853 addr = inet_addr(host);
854
855 if (addr == INADDR_NONE) {
856 h = gethostbyname(host);
857
858 if (h == NULL || h->h_addr_list[0] == NULL) {
859 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "host %s not found", host);
860 return NGX_CONF_ERROR;
861 }
862
863 for (i = 0; h->h_addr_list[i] != NULL; i++) { /* void */ }
864
865 /* MP: ngx_shared_palloc() */
866
867 ngx_test_null(lcf->peers,
868 ngx_pcalloc(cf->pool,
869 sizeof(ngx_peers_t)
870 + sizeof(ngx_peer_t) * (i - 1)),
871 NGX_CONF_ERROR);
872
873 lcf->peers->number = i;
874
875 for (i = 0; h->h_addr_list[i] != NULL; i++) {
876 lcf->peers->peers[i].host.data = host;
877 lcf->peers->peers[i].host.len = lcf->upstream->host.len;
878 lcf->peers->peers[i].addr = *(u_int32_t *)(h->h_addr_list[i]);
879 lcf->peers->peers[i].port = lcf->upstream->port;
880
881 len = INET_ADDRSTRLEN + lcf->upstream->port_text.len + 1;
882 ngx_test_null(lcf->peers->peers[i].addr_port_text.data,
883 ngx_palloc(cf->pool, len),
884 NGX_CONF_ERROR);
885
886 len = ngx_inet_ntop(AF_INET,
887 (char *) &lcf->peers->peers[i].addr,
888 lcf->peers->peers[i].addr_port_text.data,
889 len);
890
891 lcf->peers->peers[i].addr_port_text.data[len++] = ':';
892
893 ngx_cpystrn(lcf->peers->peers[i].addr_port_text.data + len,
894 lcf->upstream->port_text.data,
895 lcf->upstream->port_text.len + 1);
896
897 lcf->peers->peers[i].addr_port_text.len =
898 len + lcf->upstream->port_text.len + 1;
899 }
900
901 } else {
902
903 /* MP: ngx_shared_palloc() */
904
905 ngx_test_null(lcf->peers, ngx_pcalloc(cf->pool, sizeof(ngx_peers_t)),
906 NGX_CONF_ERROR);
907
908 lcf->peers->number = 1;
909
910 lcf->peers->peers[0].host.data = host;
911 lcf->peers->peers[0].host.len = lcf->upstream->host.len;
912 lcf->peers->peers[0].addr = addr;
913 lcf->peers->peers[0].port = lcf->upstream->port;
914
915 len = lcf->upstream->host.len + lcf->upstream->port_text.len + 1;
916
917 ngx_test_null(lcf->peers->peers[0].addr_port_text.data,
918 ngx_palloc(cf->pool, len + 1),
919 NGX_CONF_ERROR);
920
921 len = lcf->upstream->host.len;
922
923 ngx_memcpy(lcf->peers->peers[0].addr_port_text.data,
924 lcf->upstream->host.data, len);
925
926 lcf->peers->peers[0].addr_port_text.data[len++] = ':';
927
928 ngx_cpystrn(lcf->peers->peers[0].addr_port_text.data + len,
929 lcf->upstream->port_text.data,
930 lcf->upstream->port_text.len + 1);
931 }
932
933 ctx = cf->ctx;
934 clcf = ctx->loc_conf[ngx_http_core_module.ctx_index];
935 lcf->upstream->location = &clcf->name;
936 clcf->handler = ngx_http_proxy_handler;
Igor Sysoev1b138ed2003-11-18 21:34:08 +0000937 clcf->auto_redirect = 1;
Igor Sysoevd404c972003-10-16 20:19:16 +0000938
939 return NULL;
940}
941
Igor Sysoevdc9dd432003-10-22 16:38:26 +0000942
Igor Sysoevd404c972003-10-16 20:19:16 +0000943static char *ngx_http_proxy_parse_upstream(ngx_str_t *url,
Igor Sysoeva1512b12003-11-03 17:33:31 +0000944 ngx_http_proxy_upstream_conf_t *u)
Igor Sysoevd404c972003-10-16 20:19:16 +0000945{
946 size_t i;
947
948 if (url->data[0] == ':' || url->data[0] == '/') {
949 return "invalid upstream URL";
950 }
951
952 u->host.data = url->data;
953 u->host_header.data = url->data;
954
955 for (i = 1; i < url->len; i++) {
956 if (url->data[i] == ':') {
957 u->port_text.data = &url->data[i] + 1;
958 u->host.len = i;
959 }
960
961 if (url->data[i] == '/') {
962 u->uri.data = &url->data[i];
963 u->uri.len = url->len - i;
964 u->host_header.len = i;
965
966 if (u->host.len == 0) {
967 u->host.len = i;
968 }
969
970 if (u->port_text.data == NULL) {
971 u->port = htons(80);
972 u->port_text.len = 2;
973 u->port_text.data = "80";
974 return NULL;
975 }
976
977 u->port_text.len = &url->data[i] - u->port_text.data;
978
979 if (u->port_text.len > 0) {
980 u->port = ngx_atoi(u->port_text.data, u->port_text.len);
981 if (u->port > 0) {
982 u->port = htons((u_short) u->port);
983 return NULL;
984 }
985 }
986
987 return "invalid port in upstream URL";
988 }
989 }
990
991 if (u->host.len == 0) {
992 u->host.len = i;
993 }
994
995 u->host_header.len = i;
996
997 u->uri.data = "/";
998 u->uri.len = 1;
999
1000 if (u->port_text.data == NULL) {
1001 u->port = htons(80);
1002 u->port_text.len = 2;
1003 u->port_text.data = "80";
1004 return NULL;
1005 }
1006
1007 u->port_text.len = &url->data[i] - u->port_text.data;
1008
1009 if (u->port_text.len > 0) {
1010 u->port = ngx_atoi(u->port_text.data, u->port_text.len);
1011 if (u->port > 0) {
1012 u->port = htons((u_short) u->port);
1013 return NULL;
1014 }
1015 }
1016
1017 return "invalid port in upstream URL";
1018}