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 }