comparison src/http/modules/proxy/ngx_http_proxy_handler.c @ 137:2a615b036870

nginx-0.0.1-2003-10-03-19:50:53 import
author Igor Sysoev <igor@sysoev.ru>
date Fri, 03 Oct 2003 15:50:53 +0000
parents da00cde00e8a
children 3b168e12bd2d
comparison
equal deleted inserted replaced
136:da00cde00e8a 137:2a615b036870
6 #include <ngx_http.h> 6 #include <ngx_http.h>
7 #include <ngx_http_proxy_handler.h> 7 #include <ngx_http_proxy_handler.h>
8 8
9 9
10 10
11 static void ngx_http_proxy_send_request(ngx_event_t *wev); 11 static int ngx_http_proxy_handler(ngx_http_request_t *r);
12 static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_proxy_ctx_t *p);
13 static void ngx_http_proxy_send_request_handler(ngx_event_t *wev);
14 static void ngx_http_proxy_send_request(ngx_http_proxy_ctx_t *p);
15 static void ngx_http_proxy_process_upstream_status_line(ngx_event_t *rev);
16 static void ngx_http_proxy_process_upstream_headers(ngx_event_t *rev);
17 static ssize_t ngx_http_proxy_read_upstream_header(ngx_http_proxy_ctx_t *);
18 static int ngx_http_proxy_parse_status_line(ngx_http_proxy_ctx_t *p);
12 static void ngx_http_proxy_close_connection(ngx_connection_t *c); 19 static void ngx_http_proxy_close_connection(ngx_connection_t *c);
13 static ngx_chain_t *ngx_http_proxy_copy_request_hunks(ngx_http_proxy_ctx_t *p); 20
21 static int ngx_http_proxy_init(ngx_cycle_t *cycle);
14 static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf); 22 static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf);
15 23
16 24
17 static ngx_command_t ngx_http_proxy_commands[] = { 25 static ngx_command_t ngx_http_proxy_commands[] = {
18 ngx_null_command 26 ngx_null_command
38 ngx_module_t ngx_http_proxy_module = { 46 ngx_module_t ngx_http_proxy_module = {
39 NGX_MODULE, 47 NGX_MODULE,
40 &ngx_http_proxy_module_ctx, /* module context */ 48 &ngx_http_proxy_module_ctx, /* module context */
41 ngx_http_proxy_commands, /* module directives */ 49 ngx_http_proxy_commands, /* module directives */
42 NGX_HTTP_MODULE, /* module type */ 50 NGX_HTTP_MODULE, /* module type */
43 NULL, /* init module */ 51 ngx_http_proxy_init, /* init module */
44 NULL /* init child */ 52 NULL /* init child */
45 }; 53 };
46 54
47 55
56 static ngx_str_t http_methods[] = {
57 ngx_string("GET "),
58 ngx_string("HEAD "),
59 ngx_string("POST ")
60 };
61
62
48 #if 0 63 #if 0
49 static 64 static char *header_errors[] = {
65 "upstream sent too long status line",
66 "upstream sent invalid header",
67 "upstream sent too long header line"
68 };
50 #endif 69 #endif
51 70
52 int ngx_http_proxy_handler(ngx_http_request_t *r) 71
72 static ngx_http_header_t headers_in[] = {
73 { ngx_string("Date"), offsetof(ngx_http_proxy_headers_in_t, date) },
74 { ngx_string("Server"), offsetof(ngx_http_proxy_headers_in_t, server) },
75 { ngx_string("Connection"),
76 offsetof(ngx_http_proxy_headers_in_t, connection) },
77 { ngx_string("Content-Type"),
78 offsetof(ngx_http_proxy_headers_in_t, content_type) },
79 { ngx_string("Content-Length"),
80 offsetof(ngx_http_proxy_headers_in_t, content_length) },
81 { ngx_string("Last-Modified"),
82 offsetof(ngx_http_proxy_headers_in_t, last_modified) },
83
84 { ngx_null_string, 0 }
85 };
86
87
88 static char http_version[] = " HTTP/1.0" CRLF;
89 static char host_header[] = "Host: ";
90 static char conn_close_header[] = "Connection: close" CRLF;
91
92
93
94 static int ngx_http_proxy_translate_handler(ngx_http_request_t *r)
95 {
96 r->handler = ngx_http_proxy_handler;
97 return NGX_OK;
98 }
99
100
101 static int ngx_http_proxy_handler(ngx_http_request_t *r)
53 { 102 {
54 int rc; 103 int rc;
55 ngx_http_proxy_ctx_t *p; 104 ngx_http_proxy_ctx_t *p;
56 ngx_http_proxy_loc_conf_t *lcf; 105 ngx_http_proxy_loc_conf_t *lcf;
57 106
58 ngx_http_create_ctx(r, p, ngx_http_proxy_module, 107 ngx_http_create_ctx(r, p, ngx_http_proxy_module,
59 sizeof(ngx_http_proxy_ctx_t), 108 sizeof(ngx_http_proxy_ctx_t),
60 NGX_HTTP_INTERNAL_SERVER_ERROR); 109 NGX_HTTP_INTERNAL_SERVER_ERROR);
61 110
62 p->lcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module); 111 p->lcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
63
64 #if 0
65 create_request;
66 #endif
67
68 p->action = "connecting to upstream";
69 p->request = r;
70 p->upstream.peers = p->lcf->peers; 112 p->upstream.peers = p->lcf->peers;
71 p->upstream.tries = p->lcf->peers->number; 113 p->upstream.tries = p->lcf->peers->number;
72 114
115 p->request = r;
116 p->method = r->method;
117 p->uri.data = "/";
118 p->uri.len = 1;
119 p->location_len = 1;
120
121 p->host_header = p->upstream.peers->peers[0].host;
122
123 ngx_test_null(p->request_hunks, ngx_http_proxy_create_request(p),
124 NGX_HTTP_INTERNAL_SERVER_ERROR);
125
126 p->action = "connecting to upstream";
127
73 /* TODO: log->data would be changed, how to restore log->data ? */ 128 /* TODO: log->data would be changed, how to restore log->data ? */
74 p->upstream.log = r->connection->log; 129 p->upstream.log = r->connection->log;
75 130
76 for ( ;; ) { 131 ngx_http_proxy_send_request(p);
77 rc = ngx_event_connect_peer(&p->upstream); 132
78 133 return NGX_OK;
79 if (rc == NGX_ERROR) { 134 }
80 return NGX_HTTP_INTERNAL_SERVER_ERROR; 135
81 } 136
82 137 static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_proxy_ctx_t *p)
83 if (rc == NGX_CONNECT_ERROR) { 138 {
84 ngx_event_connect_peer_failed(&p->upstream); 139 int i;
85 140 size_t len;
86 if (p->upstream.tries == 0) { 141 ngx_hunk_t *h;
87 return NGX_HTTP_BAD_GATEWAY; 142 ngx_chain_t *chain;
88 } 143 ngx_table_elt_t *header;
89 } 144 ngx_http_request_t *r;
90 145
91 p->upstream.connection->data = p; 146 r = p->request;
92 p->upstream.connection->write->event_handler = 147
93 ngx_http_proxy_send_request; 148 len = http_methods[p->method - 1].len
94 p->upstream.connection->read->event_handler = /* STUB */ NULL; 149 + p->uri.len
95 150 + r->uri.len - p->location_len
96 if (p->upstream.tries > 1) { 151 + 1 + r->args.len /* 1 is for "?" */
97 ngx_test_null(p->work_request_hunks, 152 + sizeof(http_version) - 1
98 ngx_http_proxy_copy_request_hunks(p), 153 + sizeof(host_header) - 1 + p->host_header.len + 2
99 NGX_HTTP_INTERNAL_SERVER_ERROR); 154 /* 2 is for "\r\n" */
100 } else { 155 + sizeof(conn_close_header) - 1
101 p->work_request_hunks = p->request_hunks; 156 + 2; /* 2 is for "\r\n" at the header end */
102 } 157
103 158 header = (ngx_table_elt_t *) r->headers_in.headers->elts;
104 if (rc == NGX_OK) { 159 for (i = 0; i < r->headers_in.headers->nelts; i++) {
105 ngx_http_proxy_send_request(p->upstream.connection->write); 160
106 return NGX_OK; 161 if (&header[i] == r->headers_in.host) {
107 } 162 continue;
108 163 }
109 /* rc == NGX_AGAIN */ 164
110 165 if (&header[i] == r->headers_in.connection) {
111 /* timer */ 166 continue;
112 167 }
113 /* TODO */ return NGX_OK; 168
114 } 169 /* 2 is for ": " and 2 is for "\r\n" */
115 } 170 len += header[i].key.len + 2 + header[i].value.len + 2;
116 171 }
117 172
118 static void ngx_http_proxy_send_request(ngx_event_t *wev) 173 /* STUB */ len++;
119 { 174
120 int rc; 175 ngx_test_null(h, ngx_create_temp_hunk(r->pool, len, 0, 0), NULL);
121 ngx_chain_t *chain; 176 ngx_add_hunk_to_chain(chain, h, r->pool, NULL);
177
178
179 /* the request line */
180
181 h->last = ngx_cpymem(h->last, http_methods[p->method - 1].data,
182 http_methods[p->method - 1].len);
183
184 h->last = ngx_cpymem(h->last, p->uri.data, p->uri.len);
185
186 h->last = ngx_cpymem(h->last,
187 r->uri.data + p->location_len,
188 r->uri.len - p->location_len);
189
190 if (r->args.len > 0) {
191 *(h->last++) = '?';
192 h->last = ngx_cpymem(h->last, r->args.data, r->args.len);
193 }
194
195 h->last = ngx_cpymem(h->last, http_version, sizeof(http_version) - 1);
196
197
198 /* the "Host" header */
199
200 h->last = ngx_cpymem(h->last, host_header, sizeof(host_header) - 1);
201 h->last = ngx_cpymem(h->last, p->host_header.data, p->host_header.len);
202 *(h->last++) = CR; *(h->last++) = LF;
203
204
205 /* the "Connection: close" header */
206
207 h->last = ngx_cpymem(h->last, conn_close_header,
208 sizeof(conn_close_header) - 1);
209
210
211 for (i = 0; i < r->headers_in.headers->nelts; i++) {
212
213 if (&header[i] == r->headers_in.host) {
214 continue;
215 }
216
217 if (&header[i] == r->headers_in.connection) {
218 continue;
219 }
220
221 /* TODO: delete "Keep-Alive" header */
222
223 h->last = ngx_cpymem(h->last, header[i].key.data, header[i].key.len);
224
225 *(h->last++) = ':'; *(h->last++) = ' ';
226
227 h->last = ngx_cpymem(h->last, header[i].value.data,
228 header[i].value.len);
229
230 *(h->last++) = CR; *(h->last++) = LF;
231
232 ngx_log_debug(r->connection->log, "proxy: '%s: %s'" _
233 header[i].key.data _ header[i].value.data);
234 }
235
236 /* add "\r\n" at the header end */
237 *(h->last++) = CR; *(h->last++) = LF;
238
239 /* STUB */ *(h->last++) = '\0';
240 ngx_log_debug(r->connection->log, "PROXY:\n'%s'" _ h->pos);
241
242 return chain;
243 }
244
245
246 static void ngx_http_proxy_send_request_handler(ngx_event_t *wev)
247 {
122 ngx_connection_t *c; 248 ngx_connection_t *c;
123 ngx_http_proxy_ctx_t *p; 249 ngx_http_proxy_ctx_t *p;
124 250
125 c = wev->data; 251 c = wev->data;
126 p = c->data; 252 p = c->data;
127 253
254 ngx_http_proxy_send_request(p);
255
256 return;
257 }
258
259
260 static void ngx_http_proxy_send_request(ngx_http_proxy_ctx_t *p)
261 {
262 int rc;
263 ngx_chain_t *chain, *ce, *te, **le;
264 ngx_connection_t *c;
265
266 c = p->upstream.connection;
267
128 for ( ;; ) { 268 for ( ;; ) {
129 chain = ngx_write_chain(c, p->request_hunks); 269 if (c) {
130 270 chain = ngx_write_chain(c, p->work_request_hunks);
131 if (chain == (ngx_chain_t *) -1) { 271
272 if (chain != NGX_CHAIN_ERROR) {
273 p->work_request_hunks = chain;
274
275 if (c->write->timer_set) {
276 ngx_del_timer(c->write);
277 }
278
279 if (chain) {
280 ngx_add_timer(c->write, p->lcf->send_timeout);
281 c->write->timer_set = 1;
282
283 } else {
284 c->write->timer_set = 0;
285 /* TODO: del event */
286 }
287
288 return;
289 }
290
132 ngx_http_proxy_close_connection(c); 291 ngx_http_proxy_close_connection(c);
133 292 }
134 for ( ;; ) { 293
135 rc = ngx_event_connect_peer(&p->upstream); 294 for ( ;; ) {
136 295 rc = ngx_event_connect_peer(&p->upstream);
137 if (rc == NGX_ERROR) { 296
297 if (rc == NGX_ERROR) {
298 ngx_http_finalize_request(p->request,
299 NGX_HTTP_INTERNAL_SERVER_ERROR);
300 return;
301 }
302
303 if (rc == NGX_CONNECT_ERROR) {
304 ngx_event_connect_peer_failed(&p->upstream);
305
306 if (p->upstream.tries == 0) {
307 ngx_http_finalize_request(p->request,
308 NGX_HTTP_BAD_GATEWAY);
309 return;
310 }
311
312 continue;
313 }
314
315 p->upstream.connection->data = p;
316 p->upstream.connection->write->event_handler =
317 ngx_http_proxy_send_request_handler;
318 p->upstream.connection->read->event_handler =
319 ngx_http_proxy_process_upstream_status_line;
320
321 c = p->upstream.connection;
322 c->pool = p->request->pool;
323 c->read->log = c->write->log = c->log = p->request->connection->log;
324
325 if (p->upstream.tries > 1) {
326 #if (NGX_SUPPRESS_WARN)
327 le = NULL;
328 #endif
329 p->work_request_hunks =
330 ngx_alloc_chain_entry(p->request->pool);
331 if (p->work_request_hunks == NULL) {
332 ngx_http_proxy_close_connection(c);
138 ngx_http_finalize_request(p->request, 333 ngx_http_finalize_request(p->request,
139 NGX_HTTP_INTERNAL_SERVER_ERROR); 334 NGX_HTTP_INTERNAL_SERVER_ERROR);
140 return; 335 return;
141 } 336 }
142 337
143 if (rc == NGX_CONNECT_ERROR) { 338 te = p->work_request_hunks;
144 ngx_event_connect_peer_failed(&p->upstream); 339
145 340 for (ce = p->request_hunks; ce; ce = ce->next) {
146 if (p->upstream.tries == 0) { 341 te->hunk = ce->hunk;
342 *le = te;
343 le = &te->next;
344 ce->hunk->pos = ce->hunk->start;
345
346 te = ngx_alloc_chain_entry(p->request->pool);
347 if (te == NULL) {
348 ngx_http_proxy_close_connection(c);
349 ngx_http_finalize_request(p->request,
350 NGX_HTTP_INTERNAL_SERVER_ERROR);
147 return; 351 return;
148 } 352 }
149 } 353 }
150 354
151 if (p->upstream.tries > 1) { 355 *le = NULL;
152 ngx_test_null(p->work_request_hunks, 356
153 ngx_http_proxy_copy_request_hunks(p), 357 } else {
154 /* void */); 358 p->work_request_hunks = p->request_hunks;
155 } else { 359 }
156 p->work_request_hunks = p->request_hunks; 360
361 if (rc == NGX_OK) {
362 break;
363 }
364
365 /* rc == NGX_AGAIN */
366
367 ngx_add_timer(c->write, p->lcf->connect_timeout);
368 c->write->timer_set = 1;
369
370 return;
371 }
372 }
373 }
374
375
376 static void ngx_http_proxy_process_upstream_status_line(ngx_event_t *rev)
377 {
378 int rc;
379 ssize_t n;
380 ngx_connection_t *c;
381 ngx_http_proxy_ctx_t *p;
382
383 c = rev->data;
384 p = c->data;
385
386 ngx_log_debug(rev->log, "http proxy process status line");
387
388 if (rev->timedout) {
389 ngx_http_proxy_close_connection(c);
390 ngx_http_finalize_request(p->request, NGX_HTTP_GATEWAY_TIME_OUT);
391 return;
392 }
393
394 if (p->header_in == NULL) {
395 p->header_in = ngx_create_temp_hunk(p->request->pool,
396 p->lcf->header_size,
397 0, 0);
398 if (p->header_in == NULL) {
399 ngx_http_proxy_close_connection(c);
400 ngx_http_finalize_request(p->request,
401 NGX_HTTP_INTERNAL_SERVER_ERROR);
402 return;
403 }
404 }
405
406 n = ngx_http_proxy_read_upstream_header(p);
407
408 if (n == NGX_AGAIN || n == NGX_ERROR) {
409 return;
410 }
411
412 rc = ngx_http_proxy_parse_status_line(p);
413
414 if (rc == NGX_AGAIN) {
415 if (p->header_in->pos == p->header_in->last) {
416 ngx_log_error(NGX_LOG_ERR, rev->log, 0,
417 "upstream sent too big header");
418 ngx_http_proxy_close_connection(c);
419 ngx_http_finalize_request(p->request, NGX_HTTP_BAD_GATEWAY);
420 return;
421 }
422
423 return;
424 }
425
426 if (rc == NGX_HTTP_PROXY_PARSE_NO_HEADER) {
427 /* TODO: HTTP/0.9 */
428 return;
429 }
430
431 /* rc == NGX_OK */
432
433 p->status_line.len = p->status_end - p->status_start;
434 p->status_line.data = ngx_palloc(p->request->pool, p->status_line.len + 1);
435 if (p->status_line.data == NULL) {
436 ngx_http_proxy_close_connection(c);
437 ngx_http_finalize_request(p->request, NGX_HTTP_INTERNAL_SERVER_ERROR);
438 return;
439 }
440 ngx_cpystrn(p->status_line.data, p->status_start, p->status_line.len + 1);
441
442 ngx_log_debug(rev->log, "http proxy status %d '%s'" _
443 p->status _ p->status_line.data);
444
445
446 if (p->headers_in.headers) {
447 p->headers_in.headers->nelts = 0;
448 } else {
449 p->headers_in.headers = ngx_create_table(p->request->pool, 10);
450 }
451
452 c->read->event_handler = ngx_http_proxy_process_upstream_headers;
453 ngx_http_proxy_process_upstream_headers(rev);
454
455 return;
456 }
457
458
459
460 static void ngx_http_proxy_process_upstream_headers(ngx_event_t *rev)
461 {
462 int i, rc;
463 ssize_t n;
464 ngx_table_elt_t *h;
465 ngx_connection_t *c;
466 ngx_http_request_t *r;
467 ngx_http_proxy_ctx_t *p;
468
469 c = rev->data;
470 p = c->data;
471 r = p->request;
472
473 ngx_log_debug(rev->log, "http proxy process header line");
474
475 if (rev->timedout) {
476 ngx_http_proxy_close_connection(c);
477 ngx_http_finalize_request(p->request, NGX_HTTP_GATEWAY_TIME_OUT);
478 return;
479 }
480
481 rc = NGX_AGAIN;
482
483 for ( ;; ) {
484 if (rc == NGX_AGAIN) {
485 n = ngx_http_proxy_read_upstream_header(p);
486
487 if (n == NGX_AGAIN || n == NGX_ERROR) {
488 return;
489 }
490 }
491
492 rc = ngx_http_parse_header_line(p->request, p->header_in);
493
494 if (rc == NGX_OK) {
495
496 /* a header line has been parsed successfully */
497
498 h = ngx_push_table(p->headers_in.headers);
499 if (h == NULL) {
500 ngx_http_proxy_close_connection(c);
501 ngx_http_finalize_request(p->request,
502 NGX_HTTP_INTERNAL_SERVER_ERROR);
503 return;
504 }
505
506 h->key.len = r->header_name_end - r->header_name_start;
507 h->value.len = r->header_end - r->header_start;
508
509 h->key.data = ngx_palloc(p->request->pool,
510 h->key.len + 1 + h->value.len + 1);
511 if (h->key.data == NULL) {
512 ngx_http_proxy_close_connection(c);
513 ngx_http_finalize_request(p->request,
514 NGX_HTTP_INTERNAL_SERVER_ERROR);
515 return;
516 }
517
518 h->value.data = h->key.data + h->key.len + 1;
519 ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1);
520 ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1);
521
522 for (i = 0; headers_in[i].name.len != 0; i++) {
523 if (headers_in[i].name.len != h->key.len) {
524 continue;
157 } 525 }
158 526
159 if (rc == NGX_OK) { 527 if (ngx_strcasecmp(headers_in[i].name.data, h->key.data) == 0) {
160 c = p->connection; 528 *((ngx_table_elt_t **)
161 wev = c->write; 529 ((char *) &p->headers_in + headers_in[i].offset)) = h;
162
163 break;
164 } 530 }
165 531 }
166 /* rc == NGX_AGAIN */ 532
167 return; 533 ngx_log_debug(c->log, "HTTP proxy header: '%s: %s'" _
168 534 h->key.data _ h->value.data);
169 } 535
170 536 continue;
537
538 } else if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
539
540 /* a whole header has been parsed successfully */
541
542 ngx_log_debug(c->log, "HTTP header done");
543
544 return;
545
546 } else if (rc != NGX_AGAIN) {
547
548 /* there was error while a header line parsing */
549
550 #if 0
551 ngx_http_header_parse_error(r, rc);
552 #endif
553 ngx_http_proxy_close_connection(c);
554 ngx_http_finalize_request(p->request, NGX_HTTP_BAD_GATEWAY);
555 return;
556 }
557
558 /* NGX_AGAIN: a header line parsing is still not complete */
559
560 if (p->header_in->last == p->header_in->end) {
561 ngx_log_error(NGX_LOG_ERR, rev->log, 0,
562 "upstream sent too big header");
563 ngx_http_proxy_close_connection(c);
564 ngx_http_finalize_request(p->request, NGX_HTTP_BAD_GATEWAY);
565 return;
566 }
567 }
568 }
569
570
571 static ssize_t ngx_http_proxy_read_upstream_header(ngx_http_proxy_ctx_t *p)
572 {
573 int event;
574 ssize_t n;
575 ngx_event_t *rev;
576
577 rev = p->upstream.connection->read;
578
579 n = p->header_in->last - p->header_in->pos;
580
581 if (n > 0) {
582 rev->ready = 0;
583 return n;
584 }
585
586 n = ngx_recv(p->upstream.connection, p->header_in->last,
587 p->header_in->end - p->header_in->last);
588
589 if (n == NGX_AGAIN) {
590 if (rev->timer_set) {
591 ngx_del_timer(rev);
171 } else { 592 } else {
172 p->work_request_hunks = chain; 593 rev->timer_set = 1;
173 594 }
174 ngx_del_timer(wev); 595
175 596 ngx_add_timer(rev, p->lcf->read_timeout);
176 if (chain) { 597
177 ngx_add_timer(wev, p->lcf->send_timeout); 598 if (!rev->active) {
178 wev->timer_set = 1; 599 if (ngx_event_flags & NGX_HAVE_CLEAR_EVENT) {
600 /* kqueue */
601 event = NGX_CLEAR_EVENT;
179 602
180 } else { 603 } else {
181 wev->timer_set = 0; 604 /* select, poll, /dev/poll */
182 /* TODO: del event */ 605 event = NGX_LEVEL_EVENT;
183 } 606 }
184 607
185 return; 608 if (ngx_add_event(rev, NGX_READ_EVENT, event) == NGX_ERROR) {
186 } 609 ngx_http_proxy_close_connection(p->upstream.connection);
187 } 610 ngx_http_finalize_request(p->request,
188 } 611 NGX_HTTP_INTERNAL_SERVER_ERROR);
612 return NGX_ERROR;
613 }
614 }
615
616 return NGX_AGAIN;
617 }
618
619 if (n == 0) {
620 ngx_log_error(NGX_LOG_INFO, rev->log, 0,
621 "upstream closed prematurely connection");
622 }
623
624 if (n == 0 || n == NGX_ERROR) {
625 ngx_http_proxy_close_connection(p->upstream.connection);
626 ngx_http_finalize_request(p->request, NGX_HTTP_BAD_GATEWAY);
627 return NGX_ERROR;
628 }
629
630 p->header_in->last += n;
631
632 return n;
633 }
634
635
636 static int ngx_http_proxy_parse_status_line(ngx_http_proxy_ctx_t *p)
637 {
638 char ch;
639 char *pos;
640 enum {
641 sw_start = 0,
642 sw_H,
643 sw_HT,
644 sw_HTT,
645 sw_HTTP,
646 sw_first_major_digit,
647 sw_major_digit,
648 sw_first_minor_digit,
649 sw_minor_digit,
650 sw_status,
651 sw_space_after_status,
652 sw_status_text,
653 sw_almost_done,
654 sw_done
655 } state;
656
657 state = p->state;
658 pos = p->header_in->pos;
659
660 while (pos < p->header_in->last && state < sw_done) {
661 ch = *pos++;
662
663 switch (state) {
664
665 /* "HTTP/" */
666 case sw_start:
667 switch (ch) {
668 case 'H':
669 state = sw_H;
670 break;
671 default:
672 return NGX_HTTP_PROXY_PARSE_NO_HEADER;
673 }
674 break;
675
676 case sw_H:
677 switch (ch) {
678 case 'T':
679 state = sw_HT;
680 break;
681 default:
682 return NGX_HTTP_PROXY_PARSE_NO_HEADER;
683 }
684 break;
685
686 case sw_HT:
687 switch (ch) {
688 case 'T':
689 state = sw_HTT;
690 break;
691 default:
692 return NGX_HTTP_PROXY_PARSE_NO_HEADER;
693 }
694 break;
695
696 case sw_HTT:
697 switch (ch) {
698 case 'P':
699 state = sw_HTTP;
700 break;
701 default:
702 return NGX_HTTP_PROXY_PARSE_NO_HEADER;
703 }
704 break;
705
706 case sw_HTTP:
707 switch (ch) {
708 case '/':
709 state = sw_first_major_digit;
710 break;
711 default:
712 return NGX_HTTP_PROXY_PARSE_NO_HEADER;
713 }
714 break;
715
716 /* the first digit of major HTTP version */
717 case sw_first_major_digit:
718 if (ch < '1' || ch > '9') {
719 return NGX_HTTP_PROXY_PARSE_NO_HEADER;
720 }
721
722 state = sw_major_digit;
723 break;
724
725 /* the major HTTP version or dot */
726 case sw_major_digit:
727 if (ch == '.') {
728 state = sw_first_minor_digit;
729 break;
730 }
731
732 if (ch < '0' || ch > '9') {
733 return NGX_HTTP_PROXY_PARSE_NO_HEADER;
734 }
735
736 break;
737
738 /* the first digit of minor HTTP version */
739 case sw_first_minor_digit:
740 if (ch < '0' || ch > '9') {
741 return NGX_HTTP_PROXY_PARSE_NO_HEADER;
742 }
743
744 state = sw_minor_digit;
745 break;
746
747 /* the minor HTTP version or the end of the request line */
748 case sw_minor_digit:
749 if (ch == ' ') {
750 state = sw_status;
751 break;
752 }
753
754 if (ch < '0' || ch > '9') {
755 return NGX_HTTP_PROXY_PARSE_NO_HEADER;
756 }
757
758 break;
759
760 /* HTTP status code */
761 case sw_status:
762 if (ch < '0' || ch > '9') {
763 return NGX_HTTP_PROXY_PARSE_NO_HEADER;
764 }
765
766 p->status = p->status * 10 + ch - '0';
767
768 if (++p->status_count == 3) {
769 state = sw_space_after_status;
770 p->status_start = pos - 3;
771 }
772
773 break;
774
775 /* space or end of line */
776 case sw_space_after_status:
777 switch (ch) {
778 case ' ':
779 state = sw_status_text;
780 break;
781 case CR:
782 state = sw_almost_done;
783 break;
784 case LF:
785 state = sw_done;
786 break;
787 default:
788 return NGX_HTTP_PROXY_PARSE_NO_HEADER;
789 }
790 break;
791
792 /* any text until end of line */
793 case sw_status_text:
794 switch (ch) {
795 case CR:
796 state = sw_almost_done;
797
798 break;
799 case LF:
800 state = sw_done;
801 break;
802 }
803 break;
804
805 /* end of request line */
806 case sw_almost_done:
807 p->status_end = pos - 2;
808 switch (ch) {
809 case LF:
810 state = sw_done;
811 break;
812 default:
813 return NGX_HTTP_PROXY_PARSE_NO_HEADER;
814 }
815 break;
816 }
817 }
818
819 p->header_in->pos = pos;
820
821 if (state == sw_done) {
822 if (p->status_end == NULL) {
823 p->status_end = pos - 1;
824 }
825
826 p->state = sw_start;
827 return NGX_OK;
828 }
829
830 p->state = state;
831 return NGX_AGAIN;
832 }
833
189 834
190 static void ngx_http_proxy_close_connection(ngx_connection_t *c) 835 static void ngx_http_proxy_close_connection(ngx_connection_t *c)
191 { 836 {
837 ngx_log_debug(c->log, "close connection: %d" _ c->fd);
838
839 if (c->fd == -1) {
840 ngx_log_error(NGX_LOG_ALERT, c->log, 0, "connection already closed");
841 return;
842 }
843
844 if (c->read->timer_set) {
845 ngx_del_timer(c->read);
846 c->read->timer_set = 0;
847 }
848
849 if (c->write->timer_set) {
850 ngx_del_timer(c->write);
851 c->write->timer_set = 0;
852 }
853
854 if (ngx_del_conn) {
855 ngx_del_conn(c);
856
857 } else {
858 if (c->read->active) {
859 ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT);
860 }
861
862 if (c->write->active) {
863 ngx_del_event(c->write, NGX_WRITE_EVENT, NGX_CLOSE_EVENT);
864 }
865 }
866
867 if (ngx_close_socket(c->fd) == -1) {
868 ngx_log_error(NGX_LOG_ALERT, c->log, ngx_socket_errno,
869 ngx_close_socket_n " failed");
870 }
871
872 c->fd = -1;
873
192 return; 874 return;
193 }
194
195 static ngx_chain_t *ngx_http_proxy_copy_request_hunks(ngx_http_proxy_ctx_t *p)
196 {
197 ngx_chain_t *ce, *te, *fe, **le;
198
199 #if (NGX_SUPPRESS_WARN)
200 le = NULL;
201 #endif
202
203 ngx_test_null(fe, ngx_alloc_chain_entry(p->request->pool), NULL);
204
205 te = fe;
206
207 for (ce = p->request_hunks; ce; ce = ce->next) {
208 te->hunk = ce->hunk;
209 *le = te;
210 le = &te->next;
211 ce->hunk->pos = ce->hunk->start;
212
213 ngx_test_null(te, ngx_alloc_chain_entry(p->request->pool), NULL);
214 }
215
216 *le = NULL;
217
218 return fe;
219 } 875 }
220 876
221 877
222 static size_t ngx_http_proxy_log_error(void *data, char *buf, size_t len) 878 static size_t ngx_http_proxy_log_error(void *data, char *buf, size_t len)
223 { 879 {
227 " while %s, upstream: %s, client: %s, URL: %s", 883 " while %s, upstream: %s, client: %s, URL: %s",
228 p->action, 884 p->action,
229 p->upstream.peers->peers[p->upstream.cur_peer].addr_port_text.data, 885 p->upstream.peers->peers[p->upstream.cur_peer].addr_port_text.data,
230 p->request->connection->addr_text.data, 886 p->request->connection->addr_text.data,
231 p->request->unparsed_uri.data); 887 p->request->unparsed_uri.data);
888 }
889
890
891 static int ngx_http_proxy_init(ngx_cycle_t *cycle)
892 {
893 ngx_http_handler_pt *h;
894 ngx_http_conf_ctx_t *ctx;
895 ngx_http_core_main_conf_t *cmcf;
896
897 ctx = (ngx_http_conf_ctx_t *) cycle->conf_ctx[ngx_http_module.index];
898 cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];
899
900 ngx_test_null(h, ngx_push_array(&cmcf->translate_handlers), NGX_ERROR);
901
902 *h = ngx_http_proxy_translate_handler;
903
904 return NGX_OK;
232 } 905 }
233 906
234 907
235 static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf) 908 static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
236 { 909 {
250 conf->peers->peers[0].host.len = sizeof("localhost") - 1; 923 conf->peers->peers[0].host.len = sizeof("localhost") - 1;
251 conf->peers->peers[0].port = htons(9000); 924 conf->peers->peers[0].port = htons(9000);
252 conf->peers->peers[0].addr_port_text.data = "127.0.0.1:9000"; 925 conf->peers->peers[0].addr_port_text.data = "127.0.0.1:9000";
253 conf->peers->peers[0].addr_port_text.len = sizeof("127.0.0.1:9000") - 1; 926 conf->peers->peers[0].addr_port_text.len = sizeof("127.0.0.1:9000") - 1;
254 927
928 conf->connect_timeout = 30000;
255 conf->send_timeout = 30000; 929 conf->send_timeout = 30000;
930 conf->header_size = 4096;
931 conf->read_timeout = 30000;
256 /* */ 932 /* */
257 933
258 return conf; 934 return conf;
259 } 935 }