Mercurial > hg > nginx
comparison src/http/modules/proxy/ngx_http_proxy_handler.c @ 155:46eb23d9471d
nginx-0.0.1-2003-10-22-20:38:26 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Wed, 22 Oct 2003 16:38:26 +0000 |
parents | eac26585476e |
children | afc333135a6b |
comparison
equal
deleted
inserted
replaced
154:eac26585476e | 155:46eb23d9471d |
---|---|
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 | 26 |
27 static int ngx_http_proxy_init(ngx_cycle_t *cycle); | 27 static int ngx_http_proxy_init(ngx_cycle_t *cycle); |
28 static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf); | 28 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, | |
30 void *parent, void *child); | |
29 | 31 |
30 static char *ngx_http_proxy_set_pass(ngx_conf_t *cf, ngx_command_t *cmd, | 32 static char *ngx_http_proxy_set_pass(ngx_conf_t *cf, ngx_command_t *cmd, |
31 void *conf); | 33 void *conf); |
32 static char *ngx_http_proxy_parse_upstream(ngx_str_t *url, | 34 static char *ngx_http_proxy_parse_upstream(ngx_str_t *url, |
33 ngx_http_proxy_upstream_t *u); | 35 ngx_http_proxy_upstream_t *u); |
40 ngx_http_proxy_set_pass, | 42 ngx_http_proxy_set_pass, |
41 NGX_HTTP_LOC_CONF_OFFSET, | 43 NGX_HTTP_LOC_CONF_OFFSET, |
42 0, | 44 0, |
43 NULL}, | 45 NULL}, |
44 | 46 |
47 {ngx_string("proxy_connect_timeout"), | |
48 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
49 ngx_conf_set_msec_slot, | |
50 NGX_HTTP_LOC_CONF_OFFSET, | |
51 offsetof(ngx_http_proxy_loc_conf_t, connect_timeout), | |
52 NULL}, | |
53 | |
54 {ngx_string("proxy_send_timeout"), | |
55 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
56 ngx_conf_set_msec_slot, | |
57 NGX_HTTP_LOC_CONF_OFFSET, | |
58 offsetof(ngx_http_proxy_loc_conf_t, send_timeout), | |
59 NULL}, | |
60 | |
61 {ngx_string("proxy_header_buffer_size"), | |
62 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
63 ngx_conf_set_size_slot, | |
64 NGX_HTTP_LOC_CONF_OFFSET, | |
65 offsetof(ngx_http_proxy_loc_conf_t, header_buffer_size), | |
66 NULL}, | |
67 | |
68 {ngx_string("proxy_read_timeout"), | |
69 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
70 ngx_conf_set_msec_slot, | |
71 NGX_HTTP_LOC_CONF_OFFSET, | |
72 offsetof(ngx_http_proxy_loc_conf_t, read_timeout), | |
73 NULL}, | |
74 | |
75 {ngx_string("proxy_buffers"), | |
76 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2, | |
77 ngx_conf_set_bufs_slot, | |
78 NGX_HTTP_LOC_CONF_OFFSET, | |
79 offsetof(ngx_http_proxy_loc_conf_t, bufs), | |
80 NULL}, | |
81 | |
82 {ngx_string("proxy_busy_buffers_size"), | |
83 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
84 ngx_conf_set_size_slot, | |
85 NGX_HTTP_LOC_CONF_OFFSET, | |
86 offsetof(ngx_http_proxy_loc_conf_t, busy_buffers_size), | |
87 NULL}, | |
88 | |
89 {ngx_string("proxy_temp_path"), | |
90 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234, | |
91 ngx_conf_set_path_slot, | |
92 NGX_HTTP_LOC_CONF_OFFSET, | |
93 offsetof(ngx_http_proxy_loc_conf_t, temp_path), | |
94 NULL}, | |
95 | |
96 {ngx_string("proxy_temp_file_write_size"), | |
97 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
98 ngx_conf_set_size_slot, | |
99 NGX_HTTP_LOC_CONF_OFFSET, | |
100 offsetof(ngx_http_proxy_loc_conf_t, temp_file_write_size), | |
101 NULL}, | |
102 | |
45 ngx_null_command | 103 ngx_null_command |
46 }; | 104 }; |
47 | 105 |
48 | 106 |
49 ngx_http_module_t ngx_http_proxy_module_ctx = { | 107 ngx_http_module_t ngx_http_proxy_module_ctx = { |
52 | 110 |
53 NULL, /* create server configuration */ | 111 NULL, /* create server configuration */ |
54 NULL, /* merge server configuration */ | 112 NULL, /* merge server configuration */ |
55 | 113 |
56 ngx_http_proxy_create_loc_conf, /* create location configration */ | 114 ngx_http_proxy_create_loc_conf, /* create location configration */ |
57 #if 0 | 115 ngx_http_proxy_merge_loc_conf /* merge location configration */ |
58 ngx_http_proxy_merge_conf /* merge location configration */ | |
59 #endif | |
60 | |
61 NULL | |
62 }; | 116 }; |
63 | 117 |
64 | 118 |
65 ngx_module_t ngx_http_proxy_module = { | 119 ngx_module_t ngx_http_proxy_module = { |
66 NGX_MODULE, | 120 NGX_MODULE, |
106 }; | 160 }; |
107 | 161 |
108 | 162 |
109 static char http_version[] = " HTTP/1.0" CRLF; | 163 static char http_version[] = " HTTP/1.0" CRLF; |
110 static char host_header[] = "Host: "; | 164 static char host_header[] = "Host: "; |
111 static char conn_close_header[] = "Connection: close" CRLF; | 165 static char connection_close_header[] = "Connection: close" CRLF; |
112 | 166 |
113 | 167 |
114 | 168 |
115 static int ngx_http_proxy_handler(ngx_http_request_t *r) | 169 static int ngx_http_proxy_handler(ngx_http_request_t *r) |
116 { | 170 { |
166 + r->uri.len - p->location_len | 220 + r->uri.len - p->location_len |
167 + 1 + r->args.len /* 1 is for "?" */ | 221 + 1 + r->args.len /* 1 is for "?" */ |
168 + sizeof(http_version) - 1 | 222 + sizeof(http_version) - 1 |
169 + sizeof(host_header) - 1 + p->host_header.len + 2 | 223 + sizeof(host_header) - 1 + p->host_header.len + 2 |
170 /* 2 is for "\r\n" */ | 224 /* 2 is for "\r\n" */ |
171 + sizeof(conn_close_header) - 1 | 225 + sizeof(connection_close_header) - 1 |
172 + 2; /* 2 is for "\r\n" at the header end */ | 226 + 2; /* 2 is for "\r\n" at the header end */ |
173 | 227 |
174 header = (ngx_table_elt_t *) r->headers_in.headers->elts; | 228 header = (ngx_table_elt_t *) r->headers_in.headers->elts; |
175 for (i = 0; i < r->headers_in.headers->nelts; i++) { | 229 for (i = 0; i < r->headers_in.headers->nelts; i++) { |
176 | 230 |
187 } | 241 } |
188 | 242 |
189 /* STUB */ len++; | 243 /* STUB */ len++; |
190 | 244 |
191 ngx_test_null(h, ngx_create_temp_hunk(r->pool, len, 0, 0), NULL); | 245 ngx_test_null(h, ngx_create_temp_hunk(r->pool, len, 0, 0), NULL); |
192 ngx_add_hunk_to_chain(chain, h, r->pool, NULL); | 246 ngx_alloc_link_and_set_hunk(chain, h, r->pool, NULL); |
193 | 247 |
194 | 248 |
195 /* the request line */ | 249 /* the request line */ |
196 | 250 |
197 h->last = ngx_cpymem(h->last, http_methods[p->method - 1].data, | 251 h->last = ngx_cpymem(h->last, http_methods[p->method - 1].data, |
218 *(h->last++) = CR; *(h->last++) = LF; | 272 *(h->last++) = CR; *(h->last++) = LF; |
219 | 273 |
220 | 274 |
221 /* the "Connection: close" header */ | 275 /* the "Connection: close" header */ |
222 | 276 |
223 h->last = ngx_cpymem(h->last, conn_close_header, | 277 h->last = ngx_cpymem(h->last, connection_close_header, |
224 sizeof(conn_close_header) - 1); | 278 sizeof(connection_close_header) - 1); |
225 | 279 |
226 | 280 |
227 for (i = 0; i < r->headers_in.headers->nelts; i++) { | 281 for (i = 0; i < r->headers_in.headers->nelts; i++) { |
228 | 282 |
229 if (&header[i] == r->headers_in.host) { | 283 if (&header[i] == r->headers_in.host) { |
339 | 393 |
340 if (p->upstream.tries > 1) { | 394 if (p->upstream.tries > 1) { |
341 #if (NGX_SUPPRESS_WARN) | 395 #if (NGX_SUPPRESS_WARN) |
342 le = NULL; | 396 le = NULL; |
343 #endif | 397 #endif |
344 p->work_request_hunks = | 398 p->work_request_hunks = ngx_alloc_chain_link(p->request->pool); |
345 ngx_alloc_chain_entry(p->request->pool); | |
346 if (p->work_request_hunks == NULL) { | 399 if (p->work_request_hunks == NULL) { |
347 ngx_http_proxy_finalize_request(p, | 400 ngx_http_proxy_finalize_request(p, |
348 NGX_HTTP_INTERNAL_SERVER_ERROR); | 401 NGX_HTTP_INTERNAL_SERVER_ERROR); |
349 return; | 402 return; |
350 } | 403 } |
355 te->hunk = ce->hunk; | 408 te->hunk = ce->hunk; |
356 *le = te; | 409 *le = te; |
357 le = &te->next; | 410 le = &te->next; |
358 ce->hunk->pos = ce->hunk->start; | 411 ce->hunk->pos = ce->hunk->start; |
359 | 412 |
360 te = ngx_alloc_chain_entry(p->request->pool); | 413 te = ngx_alloc_chain_link(p->request->pool); |
361 if (te == NULL) { | 414 if (te == NULL) { |
362 ngx_http_proxy_finalize_request(p, | 415 ngx_http_proxy_finalize_request(p, |
363 NGX_HTTP_INTERNAL_SERVER_ERROR); | 416 NGX_HTTP_INTERNAL_SERVER_ERROR); |
364 return; | 417 return; |
365 } | 418 } |
402 return; | 455 return; |
403 } | 456 } |
404 | 457 |
405 if (p->header_in == NULL) { | 458 if (p->header_in == NULL) { |
406 p->header_in = ngx_create_temp_hunk(p->request->pool, | 459 p->header_in = ngx_create_temp_hunk(p->request->pool, |
407 p->lcf->header_size, | 460 p->lcf->header_buffer_size, |
408 0, 0); | 461 0, 0); |
409 if (p->header_in == NULL) { | 462 if (p->header_in == NULL) { |
410 ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR); | 463 ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR); |
411 return; | 464 return; |
412 } | 465 } |
561 | 614 |
562 } else if (rc != NGX_AGAIN) { | 615 } else if (rc != NGX_AGAIN) { |
563 | 616 |
564 /* there was error while a header line parsing */ | 617 /* there was error while a header line parsing */ |
565 | 618 |
566 #if 0 | |
567 ngx_http_header_parse_error(r, rc); | |
568 ngx_http_proxy_next_upstream(p); | |
569 #endif | |
570 ngx_http_proxy_finalize_request(p, NGX_HTTP_BAD_GATEWAY); | 619 ngx_http_proxy_finalize_request(p, NGX_HTTP_BAD_GATEWAY); |
571 return; | 620 return; |
572 } | 621 } |
573 | 622 |
574 /* NGX_AGAIN: a header line parsing is still not complete */ | 623 /* NGX_AGAIN: a header line parsing is still not complete */ |
690 r->headers_out.date = p->headers_in.date; | 739 r->headers_out.date = p->headers_in.date; |
691 } | 740 } |
692 | 741 |
693 /* */ | 742 /* */ |
694 | 743 |
695 #if 0 | 744 |
696 /* TODO: look "Content-Length" */ | 745 /* TODO: preallocate event_pipe hunks, look "Content-Length" */ |
697 p->block_size = p->lcf->block_size; | |
698 #endif | |
699 | 746 |
700 r->headers_out.status = p->status; | 747 r->headers_out.status = p->status; |
701 | 748 |
702 rc = ngx_http_send_header(r); | 749 rc = ngx_http_send_header(r); |
703 | 750 |
713 ep->output_filter = (ngx_event_pipe_output_filter_pt) | 760 ep->output_filter = (ngx_event_pipe_output_filter_pt) |
714 ngx_http_output_filter; | 761 ngx_http_output_filter; |
715 ep->output_ctx = r; | 762 ep->output_ctx = r; |
716 ep->tag = (ngx_hunk_tag_t) &ngx_http_proxy_module; | 763 ep->tag = (ngx_hunk_tag_t) &ngx_http_proxy_module; |
717 ep->bufs = p->lcf->bufs; | 764 ep->bufs = p->lcf->bufs; |
718 ep->max_busy_len = p->lcf->max_busy_len; | 765 ep->busy_size = p->lcf->busy_buffers_size; |
719 ep->upstream = p->upstream.connection; | 766 ep->upstream = p->upstream.connection; |
720 ep->downstream = r->connection; | 767 ep->downstream = r->connection; |
721 ep->pool = r->pool; | 768 ep->pool = r->pool; |
722 ep->log = r->connection->log; | 769 ep->log = r->connection->log; |
723 ep->temp_path = p->lcf->temp_path; | 770 ep->temp_path = p->lcf->temp_path; |
734 ep->max_temp_file_size = p->lcf->max_temp_file_size; | 781 ep->max_temp_file_size = p->lcf->max_temp_file_size; |
735 ep->temp_file_write_size = p->lcf->temp_file_write_size; | 782 ep->temp_file_write_size = p->lcf->temp_file_write_size; |
736 ep->temp_file_warn = "an upstream response is buffered " | 783 ep->temp_file_warn = "an upstream response is buffered " |
737 "to a temporary file"; | 784 "to a temporary file"; |
738 | 785 |
739 ep->preread_hunks = ngx_alloc_chain_entry(r->pool); | 786 ep->preread_hunks = ngx_alloc_chain_link(r->pool); |
740 if (ep->preread_hunks == NULL) { | 787 if (ep->preread_hunks == NULL) { |
741 ngx_http_proxy_finalize_request(p, 0); | 788 ngx_http_proxy_finalize_request(p, 0); |
742 return; | 789 return; |
743 } | 790 } |
744 ep->preread_hunks->hunk = p->header_in; | 791 ep->preread_hunks->hunk = p->header_in; |
756 | 803 |
757 if (p->lcf->cyclic_temp_file) { | 804 if (p->lcf->cyclic_temp_file) { |
758 | 805 |
759 /* | 806 /* |
760 * we need to disable the use of sendfile() if we use cyclic temp file | 807 * we need to disable the use of sendfile() if we use cyclic temp file |
761 * because the writing a new data can interfere with sendfile | 808 * because the writing a new data can interfere with sendfile() |
762 * that uses the same kernel file pages | 809 * that uses the same kernel file pages (at least on FreeBSD) |
763 */ | 810 */ |
764 | 811 |
765 ep->cyclic_temp_file = 1; | 812 ep->cyclic_temp_file = 1; |
766 r->sendfile = 0; | 813 r->sendfile = 0; |
767 | 814 |
1158 | 1205 |
1159 ngx_test_null(conf, | 1206 ngx_test_null(conf, |
1160 ngx_pcalloc(cf->pool, sizeof(ngx_http_proxy_loc_conf_t)), | 1207 ngx_pcalloc(cf->pool, sizeof(ngx_http_proxy_loc_conf_t)), |
1161 NGX_CONF_ERROR); | 1208 NGX_CONF_ERROR); |
1162 | 1209 |
1163 /* STUB */ | 1210 /* set by ngx_pcalloc(): |
1164 ngx_test_null(conf->peers, ngx_pcalloc(cf->pool, sizeof(ngx_peers_t)), | 1211 |
1165 NGX_CONF_ERROR); | 1212 conf->bufs.num = 0; |
1166 | 1213 |
1167 conf->peers->number = 1; | 1214 conf->path = NULL; |
1168 conf->peers->peers[0].addr = inet_addr("127.0.0.1"); | 1215 |
1169 conf->peers->peers[0].host.data = "localhost"; | 1216 conf->upstreams = NULL; |
1170 conf->peers->peers[0].host.len = sizeof("localhost") - 1; | 1217 conf->peers = NULL; |
1171 conf->peers->peers[0].port = htons(9000); | 1218 |
1172 conf->peers->peers[0].addr_port_text.data = "127.0.0.1:9000"; | 1219 */ |
1173 conf->peers->peers[0].addr_port_text.len = sizeof("127.0.0.1:9000") - 1; | 1220 |
1174 | 1221 conf->connect_timeout = NGX_CONF_UNSET; |
1175 conf->connect_timeout = 30000; | 1222 conf->send_timeout = NGX_CONF_UNSET; |
1176 conf->send_timeout = 30000; | 1223 conf->header_buffer_size = NGX_CONF_UNSET; |
1177 conf->header_size = 4096; | 1224 conf->read_timeout = NGX_CONF_UNSET; |
1178 conf->read_timeout = 30000; | 1225 conf->busy_buffers_size = NGX_CONF_UNSET; |
1179 | 1226 |
1180 conf->bufs.num = 5; | 1227 /* |
1181 conf->bufs.size = 4096; | 1228 * "proxy_max_temp_file_size" is hardcoded to 1G for reverse proxy, |
1182 conf->max_busy_len = 8192; | 1229 * it should be configurable in the generic proxy |
1183 | 1230 */ |
1184 | 1231 conf->max_temp_file_size = 1024 * 1024 * 1024; |
1185 /* CHECK in _init conf->max_temp_size >= conf->bufs.size !!! */ | 1232 |
1186 conf->max_temp_file_size = 4096 * 3; | 1233 conf->temp_file_write_size = NGX_CONF_UNSET; |
1187 | 1234 |
1188 | 1235 /* "proxy_cyclic_temp_file" is disabled */ |
1189 conf->temp_file_write_size = 4096 * 2; | 1236 conf->cyclic_temp_file = 0; |
1190 conf->cyclic_temp_file= 1; | |
1191 | |
1192 ngx_test_null(conf->temp_path, ngx_pcalloc(cf->pool, sizeof(ngx_path_t)), | |
1193 NULL); | |
1194 | |
1195 conf->temp_path->name.data = "temp"; | |
1196 conf->temp_path->name.len = 4; | |
1197 conf->temp_path->level[0] = 1; | |
1198 conf->temp_path->level[1] = 2; | |
1199 conf->temp_path->level[2] = 3; | |
1200 conf->temp_path->len = 0; | |
1201 | |
1202 for (i = 0; i < 3; i++) { | |
1203 if (conf->temp_path->level[i] == 0) { | |
1204 break; | |
1205 } | |
1206 conf->temp_path->len += conf->temp_path->level[i] + 1; | |
1207 } | |
1208 | |
1209 /* */ | |
1210 | 1237 |
1211 return conf; | 1238 return conf; |
1212 } | 1239 } |
1240 | |
1241 | |
1242 static char *ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, | |
1243 void *parent, void *child) | |
1244 { | |
1245 ngx_http_proxy_loc_conf_t *prev = parent; | |
1246 ngx_http_proxy_loc_conf_t *conf = child; | |
1247 | |
1248 ngx_conf_merge_msec_value(conf->connect_timeout, | |
1249 prev->connect_timeout, 60000); | |
1250 ngx_conf_merge_msec_value(conf->send_timeout, prev->send_timeout, 30000); | |
1251 ngx_conf_merge_size_value(conf->header_buffer_size, | |
1252 prev->header_buffer_size, 4096); | |
1253 ngx_conf_merge_msec_value(conf->read_timeout, prev->read_timeout, 30000); | |
1254 ngx_conf_merge_bufs_value(conf->bufs, prev->bufs, 8, 4096); | |
1255 ngx_conf_merge_size_value(conf->busy_buffers_size, | |
1256 prev->busy_buffers_size, 8192); | |
1257 | |
1258 #if 0 | |
1259 if (conf->max_temp_file_size > conf->bufs.size) { | |
1260 return "\"proxy_max_temp_file\" must be greater " | |
1261 "than one of the \"proxy_buffers\""; | |
1262 } | |
1263 #endif | |
1264 | |
1265 ngx_conf_merge_size_value(conf->temp_file_write_size, | |
1266 prev->temp_file_write_size, 16384); | |
1267 | |
1268 ngx_conf_merge_path_value(conf->temp_path, prev->temp_path, | |
1269 "temp", 1, 2, 0, cf->pool); | |
1270 | |
1271 return NULL; | |
1272 } | |
1273 | |
1213 | 1274 |
1214 | 1275 |
1215 static char *ngx_http_proxy_set_pass(ngx_conf_t *cf, ngx_command_t *cmd, | 1276 static char *ngx_http_proxy_set_pass(ngx_conf_t *cf, ngx_command_t *cmd, |
1216 void *conf) | 1277 void *conf) |
1217 { | 1278 { |
1335 clcf->handler = ngx_http_proxy_handler; | 1396 clcf->handler = ngx_http_proxy_handler; |
1336 | 1397 |
1337 return NULL; | 1398 return NULL; |
1338 } | 1399 } |
1339 | 1400 |
1401 | |
1340 static char *ngx_http_proxy_parse_upstream(ngx_str_t *url, | 1402 static char *ngx_http_proxy_parse_upstream(ngx_str_t *url, |
1341 ngx_http_proxy_upstream_t *u) | 1403 ngx_http_proxy_upstream_t *u) |
1342 { | 1404 { |
1343 size_t i; | 1405 size_t i; |
1344 | 1406 |