Mercurial > hg > nginx
comparison src/http/modules/ngx_http_event_proxy_handler.c @ 69:e43f406e4525
nginx-0.0.1-2003-03-20-19:09:44 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Thu, 20 Mar 2003 16:09:44 +0000 |
parents | 5a7d1aaa1618 |
children | e320bf51c4e3 |
comparison
equal
deleted
inserted
replaced
68:d549fdc17d7e | 69:e43f406e4525 |
---|---|
12 #include <ngx_http_core_module.h> | 12 #include <ngx_http_core_module.h> |
13 #include <ngx_http_output_filter.h> | 13 #include <ngx_http_output_filter.h> |
14 #include <ngx_http_event_proxy_handler.h> | 14 #include <ngx_http_event_proxy_handler.h> |
15 | 15 |
16 | 16 |
17 static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_request_t *r); | |
18 static int ngx_http_proxy_connect(ngx_http_proxy_ctx_t *p, | |
19 struct sockaddr_in *addr, | |
20 char *addr_text); | |
21 static int ngx_http_proxy_send_request(ngx_event_t *ev); | |
22 | |
23 static int ngx_http_proxy_init_response(ngx_event_t *ev); | |
24 static int ngx_http_proxy_read_response_header(ngx_event_t *ev); | |
25 static int ngx_http_proxy_process_status_line(ngx_http_request_t *r, | |
26 ngx_http_proxy_ctx_t *p); | |
27 | |
28 static int ngx_http_proxy_read_response_body(ngx_event_t *ev); | |
29 static int ngx_http_proxy_write_to_client(ngx_event_t *ev); | |
30 | |
31 static int ngx_read_http_proxy_status_line(ngx_http_proxy_ctx_t *ctx); | |
32 | |
33 | |
17 static ngx_command_t ngx_http_proxy_commands[] = { | 34 static ngx_command_t ngx_http_proxy_commands[] = { |
18 | 35 |
19 {ngx_string("proxy_large_header"), | 36 {ngx_string("proxy_large_header"), |
20 NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | 37 NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
21 ngx_conf_set_flag_slot, | 38 ngx_conf_set_flag_slot, |
25 {ngx_null_string, 0, NULL, 0, 0} | 42 {ngx_null_string, 0, NULL, 0, 0} |
26 }; | 43 }; |
27 | 44 |
28 | 45 |
29 static ngx_http_module_t ngx_http_proxy_module_ctx = { | 46 static ngx_http_module_t ngx_http_proxy_module_ctx = { |
30 NGX_HTTP_MODULE, | |
31 | |
32 NULL, /* create server config */ | 47 NULL, /* create server config */ |
33 NULL, /* init server config */ | 48 NULL, /* init server config */ |
49 | |
34 NULL, /* create location config */ | 50 NULL, /* create location config */ |
35 NULL, /* merge location config */ | 51 NULL, /* merge location config */ |
36 | 52 |
37 NULL, /* translate handler */ | 53 NULL /* init filters */ |
38 | |
39 NULL, /* output header filter */ | |
40 NULL, /* next output header filter */ | |
41 NULL, /* output body filter */ | |
42 NULL /* next output body filter */ | |
43 }; | 54 }; |
44 | 55 |
45 | 56 |
46 ngx_module_t ngx_http_proxy_module = { | 57 ngx_module_t ngx_http_proxy_module = { |
47 0, /* module index */ | 58 0, /* module index */ |
50 NGX_HTTP_MODULE_TYPE, /* module type */ | 61 NGX_HTTP_MODULE_TYPE, /* module type */ |
51 NULL /* init module */ | 62 NULL /* init module */ |
52 }; | 63 }; |
53 | 64 |
54 | 65 |
55 | 66 static ngx_str_t http_methods[] = { |
56 static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_request_t *r); | 67 ngx_string("GET "), |
57 static int ngx_http_proxy_connect(ngx_http_request_t *r, | 68 ngx_string("HEAD "), |
58 struct sockaddr_in *addr, | 69 ngx_string("POST ") |
59 char *addr_text); | 70 }; |
60 static int ngx_http_proxy_send_request(ngx_event_t *ev); | 71 |
61 | 72 |
62 static int ngx_http_proxy_init_response(ngx_event_t *ev); | 73 static char http_version[] = " HTTP/1.0" CRLF; |
63 static int ngx_http_proxy_read_response_header(ngx_event_t *ev); | 74 static char host_header[] = "Host: "; |
64 static int ngx_http_proxy_process_status_line(ngx_http_request_t *r, | 75 static char conn_close_header[] = "Connection: close" CRLF; |
65 ngx_http_proxy_ctx_t *p); | |
66 | |
67 static int ngx_http_proxy_read_response_body(ngx_event_t *ev); | |
68 static int ngx_http_proxy_write_to_client(ngx_event_t *ev); | |
69 | |
70 static int ngx_read_http_proxy_status_line(ngx_http_proxy_ctx_t *ctx); | |
71 | |
72 | |
73 static char conn_close[] = "Connection: close" CRLF; | |
74 | 76 |
75 | 77 |
76 /* AF_INET only */ | 78 /* AF_INET only */ |
77 | 79 |
78 | 80 |
79 int ngx_http_proxy_handler(ngx_http_request_t *r) | 81 int ngx_http_proxy_handler(ngx_http_request_t *r) |
80 { | 82 { |
81 struct sockaddr_in addr; | 83 struct sockaddr_in addr; |
82 ngx_chain_t *chain; | 84 ngx_chain_t *chain; |
83 ngx_http_proxy_ctx_t *p; | 85 ngx_http_proxy_ctx_t *p; |
86 ngx_http_log_ctx_t *hcx; | |
87 ngx_http_proxy_log_ctx_t *lcx; | |
84 | 88 |
85 p = (ngx_http_proxy_ctx_t *) | 89 p = (ngx_http_proxy_ctx_t *) |
86 ngx_http_get_module_ctx(r, ngx_http_proxy_module_ctx); | 90 ngx_http_get_module_ctx(r, ngx_http_proxy_module); |
87 | 91 |
88 if (p == NULL) { | 92 if (p == NULL) { |
89 ngx_http_create_ctx(r, p, ngx_http_proxy_module_ctx, | 93 ngx_http_create_ctx(r, p, ngx_http_proxy_module, |
90 sizeof(ngx_http_proxy_ctx_t), | 94 sizeof(ngx_http_proxy_ctx_t), |
91 NGX_HTTP_INTERNAL_SERVER_ERROR); | 95 NGX_HTTP_INTERNAL_SERVER_ERROR); |
92 } | 96 } |
97 | |
98 p->request = r; | |
99 | |
100 ngx_test_null(p->log, ngx_palloc(r->pool, sizeof(ngx_log_t)), | |
101 NGX_HTTP_INTERNAL_SERVER_ERROR); | |
102 ngx_memcpy(p->log, r->connection->log, sizeof(ngx_log_t)); | |
103 ngx_test_null(lcx, ngx_pcalloc(r->pool, sizeof(ngx_http_proxy_log_ctx_t)), | |
104 NGX_HTTP_INTERNAL_SERVER_ERROR); | |
105 | |
106 p->log->data = lcx; | |
107 hcx = r->connection->log->data; | |
108 lcx->client = hcx->client; | |
109 | |
110 /* | |
111 if (!resolved) { | |
112 return ngx_dns_resolve(name, handler, p, r->pool, p->log); | |
113 } | |
114 */ | |
93 | 115 |
94 chain = ngx_http_proxy_create_request(r); | 116 chain = ngx_http_proxy_create_request(r); |
95 if (chain == NULL) { | 117 if (chain == NULL) { |
96 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 118 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
97 } | 119 } |
98 | 120 |
121 /* TODO: duplicate hunks and chain if there is backend farm */ | |
99 p->out = chain; | 122 p->out = chain; |
100 | 123 |
101 ngx_memzero(&addr, sizeof(struct sockaddr_in)); | 124 ngx_memzero(&addr, sizeof(struct sockaddr_in)); |
102 addr.sin_family = AF_INET; | 125 addr.sin_family = AF_INET; |
126 #if 0 | |
103 addr.sin_addr.s_addr = inet_addr("127.0.0.1"); | 127 addr.sin_addr.s_addr = inet_addr("127.0.0.1"); |
128 #else | |
129 addr.sin_addr.s_addr = inet_addr("192.168.10.2"); | |
130 #endif | |
104 addr.sin_port = htons(9000); | 131 addr.sin_port = htons(9000); |
105 | 132 |
106 return ngx_http_proxy_connect(r, &addr, "connecting to 127.0.0.1:9000"); | 133 return ngx_http_proxy_connect(p, &addr, "connecting to 127.0.0.1:9000"); |
107 } | 134 } |
108 | 135 |
109 | 136 |
110 static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_request_t *r) | 137 static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_request_t *r) |
111 { | 138 { |
123 len = r->request_line.len + 2 + 2; | 150 len = r->request_line.len + 2 + 2; |
124 | 151 |
125 /* TODO: Host length */ | 152 /* TODO: Host length */ |
126 | 153 |
127 /* "Connection: close\r\n" */ | 154 /* "Connection: close\r\n" */ |
128 len += sizeof(conn_close) - 1; | 155 len += sizeof(conn_close_header) - 1; |
129 | 156 |
130 header = (ngx_table_elt_t *) r->headers_in.headers->elts; | 157 header = (ngx_table_elt_t *) r->headers_in.headers->elts; |
131 for (i = 0; i < r->headers_in.headers->nelts; i++) { | 158 for (i = 0; i < r->headers_in.headers->nelts; i++) { |
132 if (&header[i] == r->headers_in.host) { | 159 if (&header[i] == r->headers_in.host) { |
133 continue; | 160 continue; |
144 /* STUB */ len++; | 171 /* STUB */ len++; |
145 | 172 |
146 ngx_test_null(hunk, ngx_create_temp_hunk(r->pool, len, 0, 0), NULL); | 173 ngx_test_null(hunk, ngx_create_temp_hunk(r->pool, len, 0, 0), NULL); |
147 ngx_add_hunk_to_chain(chain, hunk, r->pool, NULL); | 174 ngx_add_hunk_to_chain(chain, hunk, r->pool, NULL); |
148 | 175 |
149 /* STUB: "method p->url HTTP/1.0" */ | 176 #if 0 |
177 | |
178 /* the request line */ | |
179 | |
180 ngx_memcpy(hunk->last, http_methods[p->method - 1].data, | |
181 http_methods[p->method - 1].len); | |
182 hunk->last += http_methods[p->method - 1].len; | |
183 | |
184 ngx_memcpy(hunk->last, p->uri_start.data, p->uri_start.len); | |
185 hunk->last += p->uri_start.len; | |
186 | |
187 ngx_memcpy(hunk->last, p->uri_rest.data, p->uri_rest.len); | |
188 hunk->last += p->uri_rest.len; | |
189 | |
190 if (r->args) { | |
191 *(hunk->last++) = '?'; | |
192 ngx_memcpy(hunk->last, r->uri_args.data, r->uri_args.len); | |
193 hunk->last += r->uri_args.len; | |
194 } | |
195 | |
196 ngx_memcpy(hunk->last, http_version, sizeof(http_version) - 1); | |
197 hunk->last += sizeof(http_version) - 1; | |
198 | |
199 /* the 'Host' header */ | |
200 | |
201 ngx_memcpy(hunk->last, host_header, sizeof(host_header) - 1); | |
202 hunk->last += sizeof(host_header) - 1; | |
203 | |
204 ngx_memcpy(hunk->last, p->host.data, p->host.len); | |
205 hunk->last += p->host.len; | |
206 | |
207 *(hunk->last++) = CR; *(hunk->last++) = LF; | |
208 | |
209 /* the 'Connection: close' header */ | |
210 | |
211 ngx_memcpy(hunk->last, conn_close_header, sizeof(conn_close_header) - 1); | |
212 hunk->last += sizeof(conn_close_header) - 1; | |
213 | |
214 #else | |
150 | 215 |
151 ngx_memcpy(hunk->last, r->request_line.data, r->request_line.len); | 216 ngx_memcpy(hunk->last, r->request_line.data, r->request_line.len); |
152 hunk->last += r->request_line.len; | 217 hunk->last += r->request_line.len; |
153 *(hunk->last++) = CR; *(hunk->last++) = LF; | 218 *(hunk->last++) = CR; *(hunk->last++) = LF; |
154 | 219 |
155 /* TODO: Host header */ | 220 ngx_memcpy(hunk->last, conn_close_header, sizeof(conn_close_header) - 1); |
156 | 221 hunk->last += sizeof(conn_close_header) - 1; |
157 ngx_memcpy(hunk->last, conn_close, sizeof(conn_close) - 1); | 222 |
158 hunk->last += sizeof(conn_close) - 1; | 223 #endif |
159 | 224 |
160 for (i = 0; i < r->headers_in.headers->nelts; i++) { | 225 for (i = 0; i < r->headers_in.headers->nelts; i++) { |
161 if (&header[i] == r->headers_in.host) { | 226 if (&header[i] == r->headers_in.host) { |
162 continue; | 227 continue; |
163 } | 228 } |
188 | 253 |
189 return chain; | 254 return chain; |
190 } | 255 } |
191 | 256 |
192 | 257 |
193 static int ngx_http_proxy_connect(ngx_http_request_t *r, | 258 #if 0 |
259 | |
260 client_read() | |
261 if (!ev->write) { | |
262 if error close upstream ? | |
263 else block it | |
264 } | |
265 | |
266 | |
267 static int ngx_http_proxy_process_upstream(ngx_event_t *ev) | |
268 { | |
269 again = 0; | |
270 | |
271 do { | |
272 | |
273 if (p->state_write_upstream_handler == | |
274 ngx_http_proxy_connect_to_upstream) { | |
275 if (!get_cached_connection()) | |
276 get_next_upstream(p); | |
277 } | |
278 | |
279 if (ev->write) { | |
280 | |
281 /* ngx_http_proxy_connect_to_upstream() | |
282 ngx_http_proxy_send_request() */ | |
283 | |
284 rc = p->state_write_upstream_handler(p); | |
285 | |
286 } else { | |
287 | |
288 /* ngx_http_proxy_read_response() */ | |
289 | |
290 rc = p->state_read_upstream_handler(p); | |
291 } | |
292 | |
293 if (rc == NGX_BUSY || rc == NGX_AGAIN || rc == NGX_OK) { | |
294 return rc; | |
295 } | |
296 | |
297 if (rc == NGX_ERROR) { | |
298 return ngx_http_proxy_finalize_request(p, | |
299 NGX_HTTP_INTERNAL_SERVER_ERROR); | |
300 } | |
301 | |
302 /* This NGX_HTTP_INTERNAL_SERVER_ERROR is sent by an upstream */ | |
303 | |
304 if (rc == NGX_HTTP_BAD_GATEWAY || rc == NGX_HTTP_GATEWAY_TIME_OUT | |
305 || (rc == NGX_HTTP_INTERNAL_SERVER_ERROR && lcf->retry_500) | |
306 { | |
307 ngx_http_close_connection(ev); | |
308 | |
309 if (p->upstream->amount > 1) { | |
310 /* Here is the race condition on SMP machine | |
311 when the upstreams are shared between threads or processes | |
312 but it's not serious */ | |
313 p->upstream->upstreams[p->cur_upstream].fails++; | |
314 } | |
315 | |
316 p->upstreams--; | |
317 | |
318 if (p->upstreams == 0) { | |
319 return ngx_http_proxy_finalize_request(p, rc); | |
320 } | |
321 | |
322 p->cur_upstream++; | |
323 if (p->cur_upstream > p->upstream->amount) { | |
324 p->cur_upstream = 0; | |
325 } | |
326 | |
327 p->state_read_upstream_handler = ignore; | |
328 p->state_write_upstream_handler = | |
329 ngx_http_proxy_connect_to_upstream; | |
330 again = 1; | |
331 } | |
332 | |
333 if (rc == NGX_HTTP_INTERNAL_SERVER_ERROR) { | |
334 ??? | |
335 } | |
336 | |
337 } while (again); | |
338 | |
339 return NGX_BUSY; | |
340 } | |
341 | |
342 | |
343 static int ngx_http_proxy_connect(ngx_http_proxy_ctx_t *p) | |
344 { | |
345 ngx_socket_t s; | |
346 ngx_connection_t *c; | |
347 ngx_http_log_ctx_t *lcx; | |
348 | |
349 lcx = p->log->data; | |
350 lcx->action = "connecting to an upstream"; | |
351 lcx->upstream = p->upstream.data; | |
352 p->log->handler = ngx_http_proxy_log_error; | |
353 | |
354 s = ngx_socket(AF_INET, SOCK_STREAM, IPPROTO_IP, 0); | |
355 if (s == -1) { | |
356 ngx_log_error(NGX_LOG_ALERT, p->log, ngx_socket_errno, | |
357 ngx_socket_n " failed"); | |
358 return NGX_ERROR; | |
359 } | |
360 | |
361 if (lcf->rcvbuf) { | |
362 if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, | |
363 (const void *) &rcvbuf, sizeof(int)) == -1) { | |
364 ngx_log_error(NGX_LOG_ALERT, p->log, ngx_socket_errno, | |
365 "setsockopt(SO_RCVBUF) failed"); | |
366 | |
367 if (ngx_close_socket(s) == -1) { | |
368 ngx_log_error(NGX_LOG_ALERT, p->log, ngx_socket_errno, | |
369 ngx_close_socket_n " failed"); | |
370 } | |
371 | |
372 return NGX_ERROR; | |
373 } | |
374 } | |
375 | |
376 if (ngx_nonblocking(s) == -1) { | |
377 ngx_log_error(NGX_LOG_ALERT, p->log, ngx_socket_errno, | |
378 ngx_nonblocking_n " failed"); | |
379 | |
380 if (ngx_close_socket(s) == -1) { | |
381 ngx_log_error(NGX_LOG_ALERT, p->log, ngx_socket_errno, | |
382 ngx_close_socket_n " failed"); | |
383 } | |
384 | |
385 return NGX_ERROR; | |
386 } | |
387 | |
388 rc = connect(s, (struct sockaddr *) p->addr, sizeof(struct sockaddr_in)); | |
389 | |
390 if (rc == -1) { | |
391 err = ngx_socket_errno; | |
392 if (err != NGX_EINPROGRESS) { | |
393 ngx_log_error(NGX_LOG_CRIT, p->log, err, "connect() failed"); | |
394 | |
395 if (ngx_close_socket(s) == -1) { | |
396 ngx_log_error(NGX_LOG_ALERT, p->log, ngx_socket_errno, | |
397 ngx_close_socket_n " failed"); | |
398 } | |
399 | |
400 return NGX_HTTP_BAD_GATEWAY; | |
401 } | |
402 } | |
403 | |
404 c = &ngx_connections[s]; | |
405 rev = &ngx_read_events[s]; | |
406 wev = &ngx_write_events[s]; | |
407 | |
408 ngx_memzero(rev, sizeof(ngx_event_t)); | |
409 ngx_memzero(wev, sizeof(ngx_event_t)); | |
410 ngx_memzero(c, sizeof(ngx_connection_t)); | |
411 | |
412 rev->index = wev->index = NGX_INVALID_INDEX; | |
413 | |
414 rev->data = wev->data = c; | |
415 c->read = rev; | |
416 c->write = wev; | |
417 | |
418 rev->first = wev->first = 1; | |
419 | |
420 c->data = p->request; | |
421 p->connection = c; | |
422 | |
423 c->fd = s; | |
424 | |
425 rev->log = wev->log = c->log = p->log; | |
426 | |
427 ngx_test_null(c->pool, ngx_create_pool(lcf->conn_pool_size, p->log), | |
428 NGX_ERROR); | |
429 | |
430 } | |
431 | |
432 #if 0 | |
433 connect_upstream() | |
434 get next upstream | |
435 init connect to upstream | |
436 if error return error | |
437 if ok send_request(); | |
438 if inprogress p->state_handler = send_request, return busy | |
439 | |
440 send_request() | |
441 if timeout inc fail counter | |
442 p->state_handler = connect_upstream, return 504 | |
443 #endif | |
444 | |
445 #endif | |
446 | |
447 | |
448 static int ngx_http_proxy_connect(ngx_http_proxy_ctx_t *p, | |
194 struct sockaddr_in *addr, | 449 struct sockaddr_in *addr, |
195 char *addr_text) | 450 char *addr_text) |
196 { | 451 { |
197 int rc, event; | 452 int rc, event; |
198 ngx_err_t err; | 453 ngx_err_t err; |
199 ngx_socket_t s; | 454 ngx_socket_t s; |
200 ngx_event_t *rev, *wev; | 455 ngx_event_t *rev, *wev; |
201 ngx_connection_t *c, *pc; | 456 ngx_connection_t *c, *pc; |
202 ngx_http_log_ctx_t *ctx; | 457 ngx_http_log_ctx_t *ctx; |
203 | 458 |
204 c = r->connection; | 459 c = p->request->connection; |
205 ctx = c->log->data; | 460 ctx = c->log->data; |
206 ctx->action = addr_text; | 461 ctx->action = addr_text; |
207 | 462 |
208 s = ngx_socket(AF_INET, SOCK_STREAM, IPPROTO_IP, 0); | 463 s = ngx_socket(AF_INET, SOCK_STREAM, IPPROTO_IP, 0); |
209 if (s == -1) { | 464 if (s == -1) { |
251 if (ngx_close_socket(s) == -1) { | 506 if (ngx_close_socket(s) == -1) { |
252 ngx_log_error(NGX_LOG_ALERT, c->log, ngx_socket_errno, | 507 ngx_log_error(NGX_LOG_ALERT, c->log, ngx_socket_errno, |
253 ngx_close_socket_n " failed"); | 508 ngx_close_socket_n " failed"); |
254 } | 509 } |
255 | 510 |
256 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 511 return NGX_HTTP_BAD_GATEWAY; |
257 } | 512 } |
258 } | 513 } |
259 | 514 |
260 pc = &ngx_connections[s]; | 515 pc = &ngx_connections[s]; |
261 rev = &ngx_read_events[s]; | 516 rev = &ngx_read_events[s]; |
263 | 518 |
264 ngx_memzero(rev, sizeof(ngx_event_t)); | 519 ngx_memzero(rev, sizeof(ngx_event_t)); |
265 ngx_memzero(wev, sizeof(ngx_event_t)); | 520 ngx_memzero(wev, sizeof(ngx_event_t)); |
266 ngx_memzero(pc, sizeof(ngx_connection_t)); | 521 ngx_memzero(pc, sizeof(ngx_connection_t)); |
267 | 522 |
523 rev->index = wev->index = NGX_INVALID_INDEX; | |
524 | |
268 rev->data = wev->data = pc; | 525 rev->data = wev->data = pc; |
269 pc->read = rev; | 526 pc->read = rev; |
270 pc->write = wev; | 527 pc->write = wev; |
271 | 528 |
272 pc->data = r; | 529 pc->data = p->request;; |
530 p->connection = pc; | |
273 | 531 |
274 pc->fd = s; | 532 pc->fd = s; |
275 pc->servers = c->servers; | 533 pc->servers = c->servers; |
276 | 534 |
277 pc->log = rev->log = wev->log = c->log; | 535 ngx_test_null(pc->log, ngx_palloc(c->pool, sizeof(ngx_log_t)), NGX_OK); |
536 ngx_memcpy(pc->log, c->log, sizeof(ngx_log_t)); | |
537 rev->log = wev->log = pc->log; | |
278 | 538 |
279 ngx_test_null(pc->pool, | 539 ngx_test_null(pc->pool, |
280 ngx_create_pool(/* STUB */ 1024 /**/, pc->log), | 540 ngx_create_pool(/* STUB */ 1024 /**/, pc->log), |
281 NGX_HTTP_INTERNAL_SERVER_ERROR); | 541 NGX_HTTP_INTERNAL_SERVER_ERROR); |
282 | 542 |
283 wev->event_handler = ngx_http_proxy_send_request; | 543 wev->event_handler = ngx_http_proxy_send_request; |
284 rev->event_handler = ngx_http_proxy_init_response; | 544 rev->event_handler = ngx_http_proxy_init_response; |
545 rev->close_handler = wev->close_handler = ngx_event_close_connection; | |
546 | |
285 | 547 |
286 #if (USE_KQUEUE) | 548 #if (USE_KQUEUE) |
287 | 549 |
288 if (ngx_add_event(rev, NGX_READ_EVENT, NGX_CLEAR_EVENT) != NGX_OK) { | 550 if (ngx_add_event(rev, NGX_READ_EVENT, NGX_CLEAR_EVENT) != NGX_OK) { |
289 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 551 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
312 | 574 |
313 #endif /* USE_KQUEUE */ | 575 #endif /* USE_KQUEUE */ |
314 | 576 |
315 /* TODO: aio, iocp */ | 577 /* TODO: aio, iocp */ |
316 | 578 |
579 /* The connection has been established */ | |
580 if (rc == 0) { | |
581 wev->write = 1; | |
582 wev->ready = 1; | |
583 | |
584 return ngx_http_proxy_send_request(wev); | |
585 } | |
586 | |
317 /* The connection is in a progress */ | 587 /* The connection is in a progress */ |
318 if (rc == -1) { | 588 |
319 /* TODO: oneshot */ | 589 /* TODO: oneshot */ |
320 if (ngx_add_event(wev, NGX_WRITE_EVENT, NGX_ONESHOT_EVENT) != NGX_OK) { | 590 if (ngx_add_event(wev, NGX_WRITE_EVENT, NGX_ONESHOT_EVENT) != NGX_OK) { |
321 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 591 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
322 } | 592 } |
323 } | 593 |
324 | 594 wev->timer_set = 1; |
325 wev->write = 1; | 595 ngx_add_timer(wev, /* STUB: lcf->connect_timeout */ 10000); |
326 wev->ready = 1; | 596 |
327 | 597 return NGX_BUSY; |
328 return ngx_http_proxy_send_request(wev); | |
329 } | 598 } |
330 | 599 |
331 | 600 |
332 static int ngx_http_proxy_send_request(ngx_event_t *ev) | 601 static int ngx_http_proxy_send_request(ngx_event_t *ev) |
333 { | 602 { |
337 ngx_http_proxy_ctx_t *p; | 606 ngx_http_proxy_ctx_t *p; |
338 | 607 |
339 c = (ngx_connection_t *) ev->data; | 608 c = (ngx_connection_t *) ev->data; |
340 r = (ngx_http_request_t *) c->data; | 609 r = (ngx_http_request_t *) c->data; |
341 p = (ngx_http_proxy_ctx_t *) | 610 p = (ngx_http_proxy_ctx_t *) |
342 ngx_http_get_module_ctx(r, ngx_http_proxy_module_ctx); | 611 ngx_http_get_module_ctx(r, ngx_http_proxy_module); |
612 | |
613 if (ev->timedout) { | |
614 return ngx_http_proxy_error(r, p, NGX_HTTP_GATEWAY_TIME_OUT); | |
615 } | |
343 | 616 |
344 chain = ngx_write_chain(c, p->out, 0); | 617 chain = ngx_write_chain(c, p->out, 0); |
345 if (chain == (ngx_chain_t *) -1) { | 618 if (chain == (ngx_chain_t *) -1) { |
346 return NGX_ERROR; | 619 return NGX_ERROR; |
347 } | 620 } |
348 | 621 |
349 p->out = chain; | 622 p->out = chain; |
350 | 623 |
351 return NGX_WAITING; | 624 return NGX_BUSY; |
352 } | 625 } |
353 | 626 |
354 | 627 |
355 static int ngx_http_proxy_init_response(ngx_event_t *ev) | 628 static int ngx_http_proxy_init_response(ngx_event_t *ev) |
356 { | 629 { |
366 if (ev->timedout) { | 639 if (ev->timedout) { |
367 return ngx_http_proxy_error(r, p, NGX_HTTP_GATEWAY_TIME_OUT); | 640 return ngx_http_proxy_error(r, p, NGX_HTTP_GATEWAY_TIME_OUT); |
368 } | 641 } |
369 | 642 |
370 p = (ngx_http_proxy_ctx_t *) | 643 p = (ngx_http_proxy_ctx_t *) |
371 ngx_http_get_module_ctx(r, ngx_http_proxy_module_ctx); | 644 ngx_http_get_module_ctx(r, ngx_http_proxy_module); |
372 | 645 |
373 ngx_test_null(p->header_in, | 646 ngx_test_null(p->header_in, |
374 ngx_create_temp_hunk(r->pool, | 647 ngx_create_temp_hunk(r->pool, |
375 /* STUB */ 1024 /**/, 0, 0), | 648 /* STUB */ 1024 /**/, 0, 0), |
376 ngx_http_proxy_error(r, p, NGX_HTTP_INTERNAL_SERVER_ERROR)); | 649 ngx_http_proxy_error(r, p, NGX_HTTP_INTERNAL_SERVER_ERROR)); |
405 ngx_http_proxy_loc_conf_t *lcf; | 678 ngx_http_proxy_loc_conf_t *lcf; |
406 | 679 |
407 c = (ngx_connection_t *) ev->data; | 680 c = (ngx_connection_t *) ev->data; |
408 r = (ngx_http_request_t *) c->data; | 681 r = (ngx_http_request_t *) c->data; |
409 p = (ngx_http_proxy_ctx_t *) | 682 p = (ngx_http_proxy_ctx_t *) |
410 ngx_http_get_module_ctx(r, ngx_http_proxy_module); | 683 ngx_http_get_module_ctx(r, ngx_http_proxy_module); |
411 | 684 |
412 if (ev->timedout) { | 685 if (ev->timedout) { |
413 return ngx_http_proxy_error(r, p, NGX_HTTP_GATEWAY_TIME_OUT); | 686 return ngx_http_proxy_error(r, p, NGX_HTTP_GATEWAY_TIME_OUT); |
414 } | 687 } |
415 | 688 |
514 ev->event_handler = ngx_http_proxy_read_response_body; | 787 ev->event_handler = ngx_http_proxy_read_response_body; |
515 if (p->header_in->end - p->header_in->last == 0) { | 788 if (p->header_in->end - p->header_in->last == 0) { |
516 return ngx_http_proxy_read_response_body(ev); | 789 return ngx_http_proxy_read_response_body(ev); |
517 } | 790 } |
518 | 791 |
519 return NGX_WAITING; | 792 return NGX_BUSY; |
520 } | 793 } |
521 | 794 |
522 | 795 |
523 static int ngx_http_proxy_process_status_line(ngx_http_request_t *r, | 796 static int ngx_http_proxy_process_status_line(ngx_http_request_t *r, |
524 ngx_http_proxy_ctx_t *p) | 797 ngx_http_proxy_ctx_t *p) |
573 } | 846 } |
574 | 847 |
575 c = (ngx_connection_t *) ev->data; | 848 c = (ngx_connection_t *) ev->data; |
576 r = (ngx_http_request_t *) c->data; | 849 r = (ngx_http_request_t *) c->data; |
577 p = (ngx_http_proxy_ctx_t *) | 850 p = (ngx_http_proxy_ctx_t *) |
578 ngx_http_get_module_ctx(r, ngx_http_proxy_module_ctx); | 851 ngx_http_get_module_ctx(r, ngx_http_proxy_module); |
579 | 852 |
580 if (p->hunks.nelts > 0) { | 853 if (p->hunks.nelts > 0) { |
581 h = ((ngx_hunk_t **) p->hunks.elts)[p->hunks.nelts - 1]; | 854 h = ((ngx_hunk_t **) p->hunks.elts)[p->hunks.nelts - 1]; |
582 left = h->end - h->last; | 855 left = h->end - h->last; |
583 | 856 |
629 n = ngx_event_recv(c, buf, size); | 902 n = ngx_event_recv(c, buf, size); |
630 | 903 |
631 ngx_log_debug(c->log, "READ:%d" _ n); | 904 ngx_log_debug(c->log, "READ:%d" _ n); |
632 | 905 |
633 if (n == NGX_AGAIN) { | 906 if (n == NGX_AGAIN) { |
634 return NGX_WAITING; | 907 return NGX_BUSY; |
635 } | 908 } |
636 | 909 |
637 if (n == NGX_ERROR) { | 910 if (n == NGX_ERROR) { |
638 return NGX_ERROR; | 911 return NGX_ERROR; |
639 } | 912 } |
658 p->hunk_n = 0; | 931 p->hunk_n = 0; |
659 c->write->event_handler = ngx_http_proxy_write_to_client; | 932 c->write->event_handler = ngx_http_proxy_write_to_client; |
660 return ngx_http_proxy_write_to_client(c->write); | 933 return ngx_http_proxy_write_to_client(c->write); |
661 } | 934 } |
662 | 935 |
663 /* STUB */ return NGX_WAITING; | 936 /* STUB */ return NGX_BUSY; |
664 } | 937 } |
665 | 938 |
666 | 939 |
667 static int ngx_http_proxy_write_to_client(ngx_event_t *ev) | 940 static int ngx_http_proxy_write_to_client(ngx_event_t *ev) |
668 { | 941 { |
673 ngx_http_proxy_ctx_t *p; | 946 ngx_http_proxy_ctx_t *p; |
674 | 947 |
675 c = (ngx_connection_t *) ev->data; | 948 c = (ngx_connection_t *) ev->data; |
676 r = (ngx_http_request_t *) c->data; | 949 r = (ngx_http_request_t *) c->data; |
677 p = (ngx_http_proxy_ctx_t *) | 950 p = (ngx_http_proxy_ctx_t *) |
678 ngx_http_get_module_ctx(r, ngx_http_proxy_module_ctx); | 951 ngx_http_get_module_ctx(r, ngx_http_proxy_module); |
679 | 952 |
680 do { | 953 do { |
681 h = ((ngx_hunk_t **) p->hunks.elts)[p->hunk_n]; | 954 h = ((ngx_hunk_t **) p->hunks.elts)[p->hunk_n]; |
682 | 955 |
683 rc = ngx_http_output_filter(r, h); | 956 rc = ngx_http_output_filter(r, h); |
702 { | 975 { |
703 ngx_event_close_connection(p->connection->read); | 976 ngx_event_close_connection(p->connection->read); |
704 | 977 |
705 return ngx_http_error(r, error); | 978 return ngx_http_error(r, error); |
706 } | 979 } |
980 | |
981 | |
982 static size_t ngx_http_proxy_log_error(void *data, char *buf, size_t len) | |
983 { | |
984 ngx_http_proxy_log_ctx_t *lcx = (ngx_http_proxy_log_ctx_t *) data; | |
985 | |
986 return ngx_snprintf(buf, len, | |
987 " while %s, upstream: %s, client: %s, URL: %s", | |
988 lcx->action, lcx->upstream, lcx->client, lcx->url); | |
989 } | |
990 | |
707 | 991 |
708 | 992 |
709 static int ngx_read_http_proxy_status_line(ngx_http_proxy_ctx_t *ctx) | 993 static int ngx_read_http_proxy_status_line(ngx_http_proxy_ctx_t *ctx) |
710 { | 994 { |
711 char ch; | 995 char ch; |
862 } else { | 1146 } else { |
863 ctx->state = state; | 1147 ctx->state = state; |
864 return NGX_AGAIN; | 1148 return NGX_AGAIN; |
865 } | 1149 } |
866 } | 1150 } |
1151 | |
1152 | |
1153 #if 0 | |
1154 | |
1155 static char *ngx_http_proxy_set_pass(ngx_conf_t *cf, ngx_command_t *cmd, | |
1156 char *conf) | |
1157 { | |
1158 ngx_http_proxy_conf_t *lcf = (ngx_http_proxy_conf_t *) conf; | |
1159 char *url; | |
1160 ngx_str_t *value; | |
1161 ngx_http_proxy_pass_t *pass; | |
1162 | |
1163 value = (ngx_str_t *) cf->args->elts; | |
1164 url = value[1].data; | |
1165 | |
1166 ngx_test_null(pass, ngx_push_array(lcf->proxy_pass), NGX_CONF_ERROR); | |
1167 | |
1168 if (ngx_strncasecmp(url, "http://", 7) == 0) { | |
1169 "invalid prefix in URL %s", url; | |
1170 } | |
1171 | |
1172 err = ngx_http_proxy_parse_upstream(url, u); | |
1173 | |
1174 if (err) { | |
1175 "%s %s", err, url; | |
1176 } | |
1177 | |
1178 h = ngx_gethostbyname(cmd->pool, u->host); | |
1179 | |
1180 return NULL; | |
1181 } | |
1182 | |
1183 #endif | |
1184 | |
1185 | |
1186 static char *ngx_http_proxy_parse_upstream(ngx_str_t *url, | |
1187 ngx_http_proxy_upstream_url_t *u) | |
1188 { | |
1189 size_t i; | |
1190 | |
1191 if (url->data[0] == ':' || url->data[0] == '/') { | |
1192 return "invalid upstream URL"; | |
1193 } | |
1194 | |
1195 u->host.data = url->data; | |
1196 u->host_header.data = url->data; | |
1197 | |
1198 for (i = 1; i < url->len; i++) { | |
1199 if (url->data[i] == ':') { | |
1200 u->port_name.data = &url->data[i]; | |
1201 u->host.len = i; | |
1202 } | |
1203 | |
1204 if (url->data[i] == '/') { | |
1205 u->uri.data = &url->data[i]; | |
1206 u->uri.len = url->len - i; | |
1207 u->host_header.len = i; | |
1208 | |
1209 if (u->host.len == 0) { | |
1210 u->host.len = i; | |
1211 } | |
1212 | |
1213 if (u->port_name.data == NULL) { | |
1214 return NULL; | |
1215 } | |
1216 | |
1217 u->port_name.len = &url->data[i] - u->port_name.data; | |
1218 | |
1219 if (u->port_name.len > 0) { | |
1220 u->port = ngx_atoi(u->port_name.data, u->port_name.len); | |
1221 if (u->port > 0) { | |
1222 return NULL; | |
1223 } | |
1224 } | |
1225 | |
1226 return "invalid port in upstream URL"; | |
1227 } | |
1228 } | |
1229 | |
1230 if (u->host.len == 0) { | |
1231 u->host.len = i; | |
1232 } | |
1233 | |
1234 u->host_header.len = i; | |
1235 | |
1236 u->uri.data = "/"; | |
1237 u->uri.len = 1; | |
1238 | |
1239 if (u->port_name.data == NULL) { | |
1240 return NULL; | |
1241 } | |
1242 | |
1243 u->port_name.len = &url->data[i] - u->port_name.data; | |
1244 | |
1245 if (u->port_name.len > 0) { | |
1246 u->port = ngx_atoi(u->port_name.data, u->port_name.len); | |
1247 if (u->port > 0) { | |
1248 return NULL; | |
1249 } | |
1250 } | |
1251 | |
1252 return "invalid port in upstream URL"; | |
1253 } |