Mercurial > hg > nginx
comparison src/http/modules/proxy/ngx_http_proxy_handler.c @ 159:981e4af2a425
nginx-0.0.1-2003-10-24-20:10:38 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Fri, 24 Oct 2003 16:10:38 +0000 |
parents | d377ee423603 |
children | e7e094d34162 |
comparison
equal
deleted
inserted
replaced
158:d377ee423603 | 159:981e4af2a425 |
---|---|
21 | 21 |
22 static int ngx_http_proxy_parse_status_line(ngx_http_proxy_ctx_t *p); | 22 static int ngx_http_proxy_parse_status_line(ngx_http_proxy_ctx_t *p); |
23 static void ngx_http_proxy_next_upstream(ngx_http_proxy_ctx_t *p); | 23 static void ngx_http_proxy_next_upstream(ngx_http_proxy_ctx_t *p); |
24 static void ngx_http_proxy_finalize_request(ngx_http_proxy_ctx_t *p, int rc); | 24 static void ngx_http_proxy_finalize_request(ngx_http_proxy_ctx_t *p, int rc); |
25 static void ngx_http_proxy_close_connection(ngx_connection_t *c); | 25 static void ngx_http_proxy_close_connection(ngx_connection_t *c); |
26 | |
27 static size_t ngx_http_proxy_log_error(void *data, char *buf, size_t len); | |
26 | 28 |
27 static int ngx_http_proxy_init(ngx_cycle_t *cycle); | 29 static int ngx_http_proxy_init(ngx_cycle_t *cycle); |
28 static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf); | 30 static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf); |
29 static char *ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, | 31 static char *ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, |
30 void *parent, void *child); | 32 void *parent, void *child); |
179 p->upstream.tries = p->lcf->peers->number; | 181 p->upstream.tries = p->lcf->peers->number; |
180 | 182 |
181 p->request = r; | 183 p->request = r; |
182 p->method = r->method; | 184 p->method = r->method; |
183 | 185 |
184 /* TODO: from lcf->upstream */ | 186 /* TODO: we currently support reverse proxy only */ |
185 p->uri.data = "/"; | 187 p->accel = 1; |
186 p->uri.len = 1; | |
187 p->location_len = 1; | |
188 | |
189 /* STUB */ p->accel = 1; | |
190 | 188 |
191 ngx_test_null(p->request_hunks, ngx_http_proxy_create_request(p), | 189 ngx_test_null(p->request_hunks, ngx_http_proxy_create_request(p), |
192 NGX_HTTP_INTERNAL_SERVER_ERROR); | 190 NGX_HTTP_INTERNAL_SERVER_ERROR); |
193 | 191 |
192 /* TODO: read request body */ | |
193 | |
194 p->upstream.log = r->connection->log; | |
195 p->saved_ctx = r->connection->log->data; | |
196 r->connection->log->data = p;; | |
197 r->connection->log->handler = ngx_http_proxy_log_error; | |
194 p->action = "connecting to upstream"; | 198 p->action = "connecting to upstream"; |
195 | 199 |
196 /* TODO: log->data would be changed, how to restore log->data ? */ | |
197 p->upstream.log = r->connection->log; | |
198 | |
199 ngx_http_proxy_send_request(p); | 200 ngx_http_proxy_send_request(p); |
200 | 201 |
201 return NGX_DONE; | 202 return NGX_DONE; |
202 } | 203 } |
203 | 204 |
204 | 205 |
205 static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_proxy_ctx_t *p) | 206 static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_proxy_ctx_t *p) |
206 { | 207 { |
207 int i; | 208 int i; |
208 size_t len; | 209 size_t len; |
209 ngx_hunk_t *h; | 210 ngx_hunk_t *h; |
210 ngx_chain_t *chain; | 211 ngx_chain_t *chain; |
211 ngx_table_elt_t *header; | 212 ngx_table_elt_t *header; |
212 ngx_http_request_t *r; | 213 ngx_http_request_t *r; |
214 ngx_http_proxy_upstream_t *u; | |
213 | 215 |
214 r = p->request; | 216 r = p->request; |
217 u = p->lcf->upstream; | |
215 | 218 |
216 len = http_methods[p->method - 1].len | 219 len = http_methods[p->method - 1].len |
217 + p->uri.len | 220 + u->uri.len |
218 + r->uri.len - p->location_len | 221 + r->uri.len - u->location->len |
219 + 1 + r->args.len /* 1 is for "?" */ | 222 + 1 + r->args.len /* 1 is for "?" */ |
220 + sizeof(http_version) - 1 | 223 + sizeof(http_version) - 1 |
221 + sizeof(host_header) - 1 + p->lcf->upstream->host_header.len + 2 | 224 + sizeof(host_header) - 1 + u->host_header.len + 2 |
222 /* 2 is for "\r\n" */ | 225 /* 2 is for "\r\n" */ |
223 + sizeof(connection_close_header) - 1 | 226 + sizeof(connection_close_header) - 1 |
224 + 2; /* 2 is for "\r\n" at the header end */ | 227 + 2; /* 2 is for "\r\n" at the header end */ |
225 | 228 |
226 header = (ngx_table_elt_t *) r->headers_in.headers->elts; | 229 header = (ngx_table_elt_t *) r->headers_in.headers->elts; |
247 /* the request line */ | 250 /* the request line */ |
248 | 251 |
249 h->last = ngx_cpymem(h->last, http_methods[p->method - 1].data, | 252 h->last = ngx_cpymem(h->last, http_methods[p->method - 1].data, |
250 http_methods[p->method - 1].len); | 253 http_methods[p->method - 1].len); |
251 | 254 |
252 h->last = ngx_cpymem(h->last, p->uri.data, p->uri.len); | 255 h->last = ngx_cpymem(h->last, u->uri.data, u->uri.len); |
253 | 256 |
254 h->last = ngx_cpymem(h->last, | 257 h->last = ngx_cpymem(h->last, |
255 r->uri.data + p->location_len, | 258 r->uri.data + u->location->len, |
256 r->uri.len - p->location_len); | 259 r->uri.len - u->location->len); |
257 | 260 |
258 if (r->args.len > 0) { | 261 if (r->args.len > 0) { |
259 *(h->last++) = '?'; | 262 *(h->last++) = '?'; |
260 h->last = ngx_cpymem(h->last, r->args.data, r->args.len); | 263 h->last = ngx_cpymem(h->last, r->args.data, r->args.len); |
261 } | 264 } |
262 | 265 |
263 h->last = ngx_cpymem(h->last, http_version, sizeof(http_version) - 1); | 266 h->last = ngx_cpymem(h->last, http_version, sizeof(http_version) - 1); |
264 | 267 |
265 | 268 |
266 /* the "Host" header */ | 269 /* "Host" header */ |
267 | 270 |
268 h->last = ngx_cpymem(h->last, host_header, sizeof(host_header) - 1); | 271 h->last = ngx_cpymem(h->last, host_header, sizeof(host_header) - 1); |
269 h->last = ngx_cpymem(h->last, p->lcf->upstream->host_header.data, | 272 h->last = ngx_cpymem(h->last, u->host_header.data, u->host_header.len); |
270 p->lcf->upstream->host_header.len); | |
271 *(h->last++) = CR; *(h->last++) = LF; | 273 *(h->last++) = CR; *(h->last++) = LF; |
272 | 274 |
273 | 275 |
274 /* the "Connection: close" header */ | 276 /* "Connection: close" header */ |
275 | 277 |
276 h->last = ngx_cpymem(h->last, connection_close_header, | 278 h->last = ngx_cpymem(h->last, connection_close_header, |
277 sizeof(connection_close_header) - 1); | 279 sizeof(connection_close_header) - 1); |
278 | 280 |
279 | 281 |
305 } | 307 } |
306 | 308 |
307 /* add "\r\n" at the header end */ | 309 /* add "\r\n" at the header end */ |
308 *(h->last++) = CR; *(h->last++) = LF; | 310 *(h->last++) = CR; *(h->last++) = LF; |
309 | 311 |
310 /* STUB */ *(h->last++) = '\0'; | 312 /* STUB */ *(h->last) = '\0'; |
311 ngx_log_debug(r->connection->log, "PROXY:\n'%s'" _ h->pos); | 313 ngx_log_debug(r->connection->log, "PROXY:\n'%s'" _ h->pos); |
312 | 314 |
313 return chain; | 315 return chain; |
314 } | 316 } |
315 | 317 |
320 ngx_http_proxy_ctx_t *p; | 322 ngx_http_proxy_ctx_t *p; |
321 | 323 |
322 c = wev->data; | 324 c = wev->data; |
323 p = c->data; | 325 p = c->data; |
324 | 326 |
327 if (wev->timedout) { | |
328 p->timedout = 1; | |
329 ngx_http_proxy_next_upstream(p); | |
330 return; | |
331 } | |
332 | |
325 ngx_http_proxy_send_request(p); | 333 ngx_http_proxy_send_request(p); |
326 | 334 |
327 return; | 335 return; |
328 } | 336 } |
329 | 337 |
330 | 338 |
331 static void ngx_http_proxy_send_request(ngx_http_proxy_ctx_t *p) | 339 static void ngx_http_proxy_send_request(ngx_http_proxy_ctx_t *p) |
332 { | 340 { |
333 int rc; | 341 int rc; |
334 ngx_chain_t *chain, *ce, *te, **le; | 342 ngx_chain_t *chain, *cl, *tl, **ll; |
335 ngx_connection_t *c; | 343 ngx_connection_t *c; |
336 | 344 |
337 c = p->upstream.connection; | 345 c = p->upstream.connection; |
338 | 346 |
339 for ( ;; ) { | 347 for ( ;; ) { |
348 | |
340 if (c) { | 349 if (c) { |
341 chain = ngx_write_chain(c, p->work_request_hunks); | 350 chain = ngx_write_chain(c, p->work_request_hunks); |
342 | 351 |
343 if (chain != NGX_CHAIN_ERROR) { | 352 if (chain != NGX_CHAIN_ERROR) { |
344 p->work_request_hunks = chain; | 353 p->work_request_hunks = chain; |
354 p->request_sent = 1; | |
345 | 355 |
346 if (c->write->timer_set) { | 356 if (c->write->timer_set) { |
347 ngx_del_timer(c->write); | 357 ngx_del_timer(c->write); |
348 } | 358 } |
349 | 359 |
388 | 398 |
389 c = p->upstream.connection; | 399 c = p->upstream.connection; |
390 c->pool = p->request->pool; | 400 c->pool = p->request->pool; |
391 c->read->log = c->write->log = c->log = p->request->connection->log; | 401 c->read->log = c->write->log = c->log = p->request->connection->log; |
392 | 402 |
393 if (p->upstream.tries > 1) { | 403 if (p->upstream.tries > 1 && p->request_sent) { |
394 #if (NGX_SUPPRESS_WARN) | 404 |
395 le = NULL; | 405 /* reinit the request chain */ |
396 #endif | 406 |
397 p->work_request_hunks = ngx_alloc_chain_link(p->request->pool); | 407 p->work_request_hunks = ngx_alloc_chain_link(p->request->pool); |
398 if (p->work_request_hunks == NULL) { | 408 if (p->work_request_hunks == NULL) { |
399 ngx_http_proxy_finalize_request(p, | 409 ngx_http_proxy_finalize_request(p, |
400 NGX_HTTP_INTERNAL_SERVER_ERROR); | 410 NGX_HTTP_INTERNAL_SERVER_ERROR); |
401 return; | 411 return; |
402 } | 412 } |
403 | 413 |
404 te = p->work_request_hunks; | 414 tl = p->work_request_hunks; |
405 | 415 ll = &p->work_request_hunks; |
406 for (ce = p->request_hunks; ce; ce = ce->next) { | 416 |
407 te->hunk = ce->hunk; | 417 for (cl = p->request_hunks; cl; cl = cl->next) { |
408 *le = te; | 418 tl->hunk = cl->hunk; |
409 le = &te->next; | 419 *ll = tl; |
410 ce->hunk->pos = ce->hunk->start; | 420 ll = &tl->next; |
411 | 421 cl->hunk->pos = cl->hunk->start; |
412 te = ngx_alloc_chain_link(p->request->pool); | 422 |
413 if (te == NULL) { | 423 tl = ngx_alloc_chain_link(p->request->pool); |
424 if (tl == NULL) { | |
414 ngx_http_proxy_finalize_request(p, | 425 ngx_http_proxy_finalize_request(p, |
415 NGX_HTTP_INTERNAL_SERVER_ERROR); | 426 NGX_HTTP_INTERNAL_SERVER_ERROR); |
416 return; | 427 return; |
417 } | 428 } |
418 } | 429 } |
419 | 430 |
420 *le = NULL; | 431 *ll = NULL; |
421 | 432 |
422 } else { | 433 } else { |
423 p->work_request_hunks = p->request_hunks; | 434 p->work_request_hunks = p->request_hunks; |
424 } | 435 } |
436 | |
437 p->request_sent = 0; | |
438 p->timedout = 0; | |
425 | 439 |
426 if (rc == NGX_OK) { | 440 if (rc == NGX_OK) { |
427 break; | 441 break; |
428 } | 442 } |
429 | 443 |
448 p = c->data; | 462 p = c->data; |
449 | 463 |
450 ngx_log_debug(rev->log, "http proxy process status line"); | 464 ngx_log_debug(rev->log, "http proxy process status line"); |
451 | 465 |
452 if (rev->timedout) { | 466 if (rev->timedout) { |
467 p->timedout = 1; | |
453 ngx_http_proxy_next_upstream(p); | 468 ngx_http_proxy_next_upstream(p); |
454 return; | 469 return; |
455 } | 470 } |
456 | 471 |
457 if (p->header_in == NULL) { | 472 if (p->header_in == NULL) { |
535 r = p->request; | 550 r = p->request; |
536 | 551 |
537 ngx_log_debug(rev->log, "http proxy process header line"); | 552 ngx_log_debug(rev->log, "http proxy process header line"); |
538 | 553 |
539 if (rev->timedout) { | 554 if (rev->timedout) { |
555 p->timedout = 1; | |
540 ngx_http_proxy_next_upstream(p); | 556 ngx_http_proxy_next_upstream(p); |
541 return; | 557 return; |
542 } | 558 } |
543 | 559 |
544 rc = NGX_AGAIN; | 560 rc = NGX_AGAIN; |
855 ep = p->event_pipe; | 871 ep = p->event_pipe; |
856 | 872 |
857 if (ev->timedout) { | 873 if (ev->timedout) { |
858 if (ev->write) { | 874 if (ev->write) { |
859 ep->downstream_error = 1; | 875 ep->downstream_error = 1; |
876 ngx_log_error(NGX_LOG_ERR, c->log, NGX_ETIMEDOUT, | |
877 "client timed out"); | |
860 | 878 |
861 } else { | 879 } else { |
862 ep->upstream_error = 1; | 880 ep->upstream_error = 1; |
881 ngx_log_error(NGX_LOG_ERR, c->log, NGX_ETIMEDOUT, | |
882 "upstream timed out"); | |
863 } | 883 } |
864 | 884 |
865 } else { | 885 } else { |
866 if (ngx_event_pipe(ep, ev->write) == NGX_ABORT) { | 886 if (ngx_event_pipe(ep, ev->write) == NGX_ABORT) { |
867 ngx_http_proxy_finalize_request(p, 0); | 887 ngx_http_proxy_finalize_request(p, 0); |
1103 } | 1123 } |
1104 | 1124 |
1105 | 1125 |
1106 static void ngx_http_proxy_next_upstream(ngx_http_proxy_ctx_t *p) | 1126 static void ngx_http_proxy_next_upstream(ngx_http_proxy_ctx_t *p) |
1107 { | 1127 { |
1128 ngx_event_connect_peer_failed(&p->upstream); | |
1129 | |
1130 if (p->timedout) { | |
1131 ngx_log_error(NGX_LOG_ERR, p->request->connection->log, NGX_ETIMEDOUT, | |
1132 "upstream timed out"); | |
1133 } | |
1134 | |
1108 if (p->upstream.connection) { | 1135 if (p->upstream.connection) { |
1109 ngx_http_proxy_close_connection(p->upstream.connection); | 1136 ngx_http_proxy_close_connection(p->upstream.connection); |
1110 p->upstream.connection = NULL; | 1137 p->upstream.connection = NULL; |
1138 } | |
1139 | |
1140 if (p->upstream.tries == 0) { | |
1141 ngx_http_proxy_finalize_request(p, | |
1142 p->timedout ? NGX_HTTP_GATEWAY_TIME_OUT: | |
1143 NGX_HTTP_BAD_GATEWAY); | |
1144 return; | |
1111 } | 1145 } |
1112 | 1146 |
1113 if (!p->fatal_error) { | 1147 if (!p->fatal_error) { |
1114 ngx_http_proxy_send_request(p); | 1148 ngx_http_proxy_send_request(p); |
1115 } | 1149 } |