comparison src/http/modules/proxy/ngx_http_proxy_handler.c @ 148:5afee0074707

nginx-0.0.1-2003-10-17-00:19:16 import
author Igor Sysoev <igor@sysoev.ru>
date Thu, 16 Oct 2003 20:19:16 +0000
parents ef8c87afcfc5
children ad5f382c9e7d
comparison
equal deleted inserted replaced
147:be71fca7f9d7 148:5afee0074707
15 static void ngx_http_proxy_send_request(ngx_http_proxy_ctx_t *p); 15 static void ngx_http_proxy_send_request(ngx_http_proxy_ctx_t *p);
16 static void ngx_http_proxy_process_upstream_status_line(ngx_event_t *rev); 16 static void ngx_http_proxy_process_upstream_status_line(ngx_event_t *rev);
17 static void ngx_http_proxy_process_upstream_headers(ngx_event_t *rev); 17 static void ngx_http_proxy_process_upstream_headers(ngx_event_t *rev);
18 static ssize_t ngx_http_proxy_read_upstream_header(ngx_http_proxy_ctx_t *); 18 static ssize_t ngx_http_proxy_read_upstream_header(ngx_http_proxy_ctx_t *);
19 static void ngx_http_proxy_send_response(ngx_http_proxy_ctx_t *p); 19 static void ngx_http_proxy_send_response(ngx_http_proxy_ctx_t *p);
20 static void ngx_http_proxy_process_upstream_body(ngx_event_t *rev); 20 static void ngx_http_proxy_process_upstream(ngx_event_t *rev);
21 static void ngx_http_proxy_process_downstream(ngx_event_t *wev);
21 22
22 static int ngx_http_proxy_parse_status_line(ngx_http_proxy_ctx_t *p); 23 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); 24 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); 25 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); 26 static void ngx_http_proxy_close_connection(ngx_connection_t *c);
26 27
27 static int ngx_http_proxy_init(ngx_cycle_t *cycle); 28 static int ngx_http_proxy_init(ngx_cycle_t *cycle);
28 static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf); 29 static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf);
29 30
31 static char *ngx_http_proxy_set_pass(ngx_conf_t *cf, ngx_command_t *cmd,
32 void *conf);
33 static char *ngx_http_proxy_parse_upstream(ngx_str_t *url,
34 ngx_http_proxy_upstream_t *u);
35
30 36
31 static ngx_command_t ngx_http_proxy_commands[] = { 37 static ngx_command_t ngx_http_proxy_commands[] = {
38
39 {ngx_string("proxy_pass"),
40 NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
41 ngx_http_proxy_set_pass,
42 NGX_HTTP_LOC_CONF_OFFSET,
43 0,
44 NULL},
45
32 ngx_null_command 46 ngx_null_command
33 }; 47 };
34 48
35 49
36 ngx_http_module_t ngx_http_proxy_module_ctx = { 50 ngx_http_module_t ngx_http_proxy_module_ctx = {
52 ngx_module_t ngx_http_proxy_module = { 66 ngx_module_t ngx_http_proxy_module = {
53 NGX_MODULE, 67 NGX_MODULE,
54 &ngx_http_proxy_module_ctx, /* module context */ 68 &ngx_http_proxy_module_ctx, /* module context */
55 ngx_http_proxy_commands, /* module directives */ 69 ngx_http_proxy_commands, /* module directives */
56 NGX_HTTP_MODULE, /* module type */ 70 NGX_HTTP_MODULE, /* module type */
57 ngx_http_proxy_init, /* init module */ 71 NULL, /* init module */
58 NULL /* init child */ 72 NULL /* init child */
59 }; 73 };
60 74
61 75
62 static ngx_str_t http_methods[] = { 76 static ngx_str_t http_methods[] = {
97 static char host_header[] = "Host: "; 111 static char host_header[] = "Host: ";
98 static char conn_close_header[] = "Connection: close" CRLF; 112 static char conn_close_header[] = "Connection: close" CRLF;
99 113
100 114
101 115
102 static int ngx_http_proxy_translate_handler(ngx_http_request_t *r)
103 {
104 #if 0
105 r->handler = ngx_http_proxy_handler;
106 return NGX_OK;
107 #else
108 return NGX_DECLINED;
109 #endif
110 }
111
112
113 static int ngx_http_proxy_handler(ngx_http_request_t *r) 116 static int ngx_http_proxy_handler(ngx_http_request_t *r)
114 { 117 {
115 int rc; 118 ngx_http_proxy_ctx_t *p;
116 ngx_http_proxy_ctx_t *p;
117 ngx_http_proxy_loc_conf_t *lcf;
118 119
119 ngx_http_create_ctx(r, p, ngx_http_proxy_module, 120 ngx_http_create_ctx(r, p, ngx_http_proxy_module,
120 sizeof(ngx_http_proxy_ctx_t), 121 sizeof(ngx_http_proxy_ctx_t),
121 NGX_HTTP_INTERNAL_SERVER_ERROR); 122 NGX_HTTP_INTERNAL_SERVER_ERROR);
122 123
124 p->upstream.peers = p->lcf->peers; 125 p->upstream.peers = p->lcf->peers;
125 p->upstream.tries = p->lcf->peers->number; 126 p->upstream.tries = p->lcf->peers->number;
126 127
127 p->request = r; 128 p->request = r;
128 p->method = r->method; 129 p->method = r->method;
130
131 /* TODO: from lcf->upstream */
129 p->uri.data = "/"; 132 p->uri.data = "/";
130 p->uri.len = 1; 133 p->uri.len = 1;
131 p->location_len = 1; 134 p->location_len = 1;
132 135
133 /* STUB */ p->accel = 1; 136 /* STUB */ p->accel = 1;
142 /* TODO: log->data would be changed, how to restore log->data ? */ 145 /* TODO: log->data would be changed, how to restore log->data ? */
143 p->upstream.log = r->connection->log; 146 p->upstream.log = r->connection->log;
144 147
145 ngx_http_proxy_send_request(p); 148 ngx_http_proxy_send_request(p);
146 149
147 return NGX_OK; 150 return NGX_DONE;
148 } 151 }
149 152
150 153
151 static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_proxy_ctx_t *p) 154 static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_proxy_ctx_t *p)
152 { 155 {
578 } 581 }
579 582
580 583
581 static ssize_t ngx_http_proxy_read_upstream_header(ngx_http_proxy_ctx_t *p) 584 static ssize_t ngx_http_proxy_read_upstream_header(ngx_http_proxy_ctx_t *p)
582 { 585 {
583 int event;
584 ssize_t n; 586 ssize_t n;
585 ngx_event_t *rev; 587 ngx_event_t *rev;
586 588
587 rev = p->upstream.connection->read; 589 rev = p->upstream.connection->read;
588 590
589 n = p->header_in->last - p->header_in->pos; 591 n = p->header_in->last - p->header_in->pos;
590 592
591 if (n > 0) { 593 if (n > 0) {
594 #if 0
595 /* TODO THINK */
592 rev->ready = 0; 596 rev->ready = 0;
597 #endif
593 return n; 598 return n;
594 } 599 }
595 600
596 n = ngx_recv(p->upstream.connection, p->header_in->last, 601 n = ngx_recv(p->upstream.connection, p->header_in->last,
597 p->header_in->end - p->header_in->last); 602 p->header_in->end - p->header_in->last);
698 if (ep == NULL) { 703 if (ep == NULL) {
699 ngx_http_proxy_finalize_request(p, 0); 704 ngx_http_proxy_finalize_request(p, 0);
700 return; 705 return;
701 } 706 }
702 707
708 ep->input_filter = ngx_event_proxy_copy_input_filter;
703 ep->output_filter = (ngx_event_proxy_output_filter_pt) 709 ep->output_filter = (ngx_event_proxy_output_filter_pt)
704 ngx_http_output_filter; 710 ngx_http_output_filter;
705 ep->output_data = r; 711 ep->output_ctx = r;
706 ep->block_size = p->lcf->block_size; 712 ep->bufs = p->lcf->bufs;
707 ep->max_block_size = p->lcf->max_block_size; 713 ep->max_busy_len = p->lcf->max_busy_len;
708 ep->upstream = p->upstream.connection; 714 ep->upstream = p->upstream.connection;
709 ep->downstream = r->connection; 715 ep->downstream = r->connection;
710 ep->pool = r->pool; 716 ep->pool = r->pool;
711 ep->log = r->connection->log; 717 ep->log = r->connection->log;
712 ep->temp_path = p->lcf->temp_path; 718 ep->temp_path = p->lcf->temp_path;
740 #if 0 746 #if 0
741 lcx = p->log->data; 747 lcx = p->log->data;
742 lcx->action = "reading an upstream"; 748 lcx->action = "reading an upstream";
743 #endif 749 #endif
744 750
745 ngx_event_proxy_read_upstream(ep);
746
747 p->upstream.connection->read->event_handler = 751 p->upstream.connection->read->event_handler =
748 ngx_http_proxy_process_upstream_body; 752 ngx_http_proxy_process_upstream;
753 r->connection->write->event_handler =
754 ngx_http_proxy_process_downstream;
755
756 ngx_http_proxy_process_upstream(p->upstream.connection->read);
749 757
750 return; 758 return;
751 } 759 }
752 760
753 761
754 static void ngx_http_proxy_process_upstream_body(ngx_event_t *rev) 762 static void ngx_http_proxy_process_upstream(ngx_event_t *rev)
755 { 763 {
756 ngx_connection_t *c; 764 ngx_connection_t *c;
757 ngx_http_proxy_ctx_t *p; 765 ngx_http_proxy_ctx_t *p;
758 766
759 c = rev->data; 767 c = rev->data;
760 p = c->data; 768 p = c->data;
761 769
762 ngx_log_debug(rev->log, "http proxy process upstream body"); 770 ngx_log_debug(rev->log, "http proxy process upstream");
763 771
764 if (rev->timedout) { 772 if (rev->timedout) {
765 ngx_http_proxy_close_connection(p->upstream.connection); 773 ngx_http_proxy_close_connection(c);
766 p->upstream.connection = NULL; 774 p->upstream.connection = NULL;
767 return; 775 return;
768 } 776 }
769 777
770 ngx_event_proxy_read_upstream(p->event_proxy); 778 if (ngx_event_proxy_read_upstream(p->event_proxy) == NGX_ABORT) {
771 779 ngx_http_proxy_finalize_request(p, 0);
772 if (p->event_proxy->upstream_eof) { 780 return;
773 ngx_http_proxy_close_connection(p->upstream.connection); 781 }
774 p->upstream.connection = NULL; 782
775 return; 783 if (p->event_proxy->upstream_eof
776 } 784 || p->event_proxy->upstream_error
777 785 || p->event_proxy->upstream_done)
778 if (p->event_proxy->upstream_error) { 786 {
779 ngx_http_proxy_close_connection(p->upstream.connection); 787 ngx_http_proxy_finalize_request(p, ngx_http_send_last(p->request));
780 p->upstream.connection = NULL; 788 return;
789 }
790
791 return;
792 }
793
794
795 static void ngx_http_proxy_process_downstream(ngx_event_t *wev)
796 {
797 ngx_connection_t *c;
798 ngx_http_proxy_ctx_t *p;
799
800 c = wev->data;
801 p = c->data;
802
803 ngx_log_debug(wev->log, "http proxy process downstream");
804
805 if (wev->timedout) {
806 ngx_http_close_connection(c);
807 return;
808 }
809
810 if (ngx_event_proxy_write_to_downstream(p->event_proxy) == NGX_ABORT) {
811 ngx_http_proxy_finalize_request(p, 0);
812 return;
813 }
814
815 if (p->event_proxy->downstream_done) {
816 ngx_http_proxy_finalize_request(p, 0);
817 return;
818 }
819
820 if (p->event_proxy->downstream_error) {
821 ngx_http_close_connection(c);
781 return; 822 return;
782 } 823 }
783 824
784 return; 825 return;
785 } 826 }
1074 p->request->connection->addr_text.data, 1115 p->request->connection->addr_text.data,
1075 p->request->unparsed_uri.data); 1116 p->request->unparsed_uri.data);
1076 } 1117 }
1077 1118
1078 1119
1079 static int ngx_http_proxy_init(ngx_cycle_t *cycle)
1080 {
1081 ngx_http_handler_pt *h;
1082 ngx_http_conf_ctx_t *ctx;
1083 ngx_http_core_main_conf_t *cmcf;
1084
1085 ctx = (ngx_http_conf_ctx_t *) cycle->conf_ctx[ngx_http_module.index];
1086 cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];
1087
1088 ngx_test_null(h, ngx_push_array(
1089 &cmcf->phases[NGX_HTTP_TRANSLATE_PHASE].handlers),
1090 NGX_ERROR);
1091
1092 *h = ngx_http_proxy_translate_handler;
1093
1094 return NGX_OK;
1095 }
1096
1097
1098 static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf) 1120 static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
1099 { 1121 {
1100 int i; 1122 int i;
1101 ngx_http_proxy_loc_conf_t *conf; 1123 ngx_http_proxy_loc_conf_t *conf;
1102 1124
1119 conf->connect_timeout = 30000; 1141 conf->connect_timeout = 30000;
1120 conf->send_timeout = 30000; 1142 conf->send_timeout = 30000;
1121 conf->header_size = 4096; 1143 conf->header_size = 4096;
1122 conf->read_timeout = 30000; 1144 conf->read_timeout = 30000;
1123 1145
1124 conf->block_size = 4096; 1146 conf->bufs.num = 10;
1125 conf->max_block_size = 4096 * 3; 1147 conf->bufs.size = 4096;
1148 conf->max_busy_len = 8192 + 4096;
1126 conf->max_temp_file_size = 4096 * 5; 1149 conf->max_temp_file_size = 4096 * 5;
1127 conf->temp_file_write_size = 4096 * 2; 1150 conf->temp_file_write_size = 4096 * 2;
1128 1151
1129 ngx_test_null(conf->temp_path, ngx_pcalloc(cf->pool, sizeof(ngx_path_t)), 1152 ngx_test_null(conf->temp_path, ngx_pcalloc(cf->pool, sizeof(ngx_path_t)),
1130 NULL); 1153 NULL);
1145 1168
1146 /* */ 1169 /* */
1147 1170
1148 return conf; 1171 return conf;
1149 } 1172 }
1173
1174
1175 static char *ngx_http_proxy_set_pass(ngx_conf_t *cf, ngx_command_t *cmd,
1176 void *conf)
1177 {
1178 ngx_http_proxy_loc_conf_t *lcf = conf;
1179
1180 int i, len;
1181 char *err, *host;
1182 ngx_str_t *value;
1183 struct hostent *h;
1184 u_int32_t addr;
1185 ngx_http_conf_ctx_t *ctx;
1186 ngx_http_core_loc_conf_t *clcf;
1187
1188
1189 value = cf->args->elts;
1190
1191 if (ngx_strncasecmp(value[1].data, "http://", 7) != 0) {
1192 return "invalid URL prefix";
1193 }
1194
1195 ngx_test_null(lcf->upstream,
1196 ngx_pcalloc(cf->pool, sizeof(ngx_http_proxy_upstream_t)),
1197 NGX_CONF_ERROR);
1198
1199 value[1].data += 7;
1200 value[1].len -= 7;
1201
1202 err = ngx_http_proxy_parse_upstream(&value[1], lcf->upstream);
1203
1204 if (err) {
1205 return err;
1206 }
1207
1208 ngx_test_null(host, ngx_palloc(cf->pool, lcf->upstream->host.len + 1),
1209 NGX_CONF_ERROR);
1210 ngx_cpystrn(host, lcf->upstream->host.data, lcf->upstream->host.len + 1);
1211
1212 addr = inet_addr(host);
1213
1214 if (addr == INADDR_NONE) {
1215 h = gethostbyname(host);
1216
1217 if (h == NULL || h->h_addr_list[0] == NULL) {
1218 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "host %s not found", host);
1219 return NGX_CONF_ERROR;
1220 }
1221
1222 for (i = 0; h->h_addr_list[i] != NULL; i++) { /* void */ }
1223
1224 /* MP: ngx_shared_palloc() */
1225
1226 ngx_test_null(lcf->peers,
1227 ngx_pcalloc(cf->pool,
1228 sizeof(ngx_peers_t)
1229 + sizeof(ngx_peer_t) * (i - 1)),
1230 NGX_CONF_ERROR);
1231
1232 lcf->peers->number = i;
1233
1234 for (i = 0; h->h_addr_list[i] != NULL; i++) {
1235 lcf->peers->peers[i].host.data = host;
1236 lcf->peers->peers[i].host.len = lcf->upstream->host.len;
1237 lcf->peers->peers[i].addr = *(u_int32_t *)(h->h_addr_list[i]);
1238 lcf->peers->peers[i].port = lcf->upstream->port;
1239
1240 len = INET_ADDRSTRLEN + lcf->upstream->port_text.len + 1;
1241 ngx_test_null(lcf->peers->peers[i].addr_port_text.data,
1242 ngx_palloc(cf->pool, len),
1243 NGX_CONF_ERROR);
1244
1245 len = ngx_inet_ntop(AF_INET,
1246 (char *) &lcf->peers->peers[i].addr,
1247 lcf->peers->peers[i].addr_port_text.data,
1248 len);
1249
1250 lcf->peers->peers[i].addr_port_text.data[len++] = ':';
1251
1252 ngx_cpystrn(lcf->peers->peers[i].addr_port_text.data + len,
1253 lcf->upstream->port_text.data,
1254 lcf->upstream->port_text.len + 1);
1255
1256 lcf->peers->peers[i].addr_port_text.len =
1257 len + lcf->upstream->port_text.len + 1;
1258 }
1259
1260 } else {
1261
1262 /* MP: ngx_shared_palloc() */
1263
1264 ngx_test_null(lcf->peers, ngx_pcalloc(cf->pool, sizeof(ngx_peers_t)),
1265 NGX_CONF_ERROR);
1266
1267 lcf->peers->number = 1;
1268
1269 lcf->peers->peers[0].host.data = host;
1270 lcf->peers->peers[0].host.len = lcf->upstream->host.len;
1271 lcf->peers->peers[0].addr = addr;
1272 lcf->peers->peers[0].port = lcf->upstream->port;
1273
1274 len = lcf->upstream->host.len + lcf->upstream->port_text.len + 1;
1275
1276 ngx_test_null(lcf->peers->peers[0].addr_port_text.data,
1277 ngx_palloc(cf->pool, len + 1),
1278 NGX_CONF_ERROR);
1279
1280 len = lcf->upstream->host.len;
1281
1282 ngx_memcpy(lcf->peers->peers[0].addr_port_text.data,
1283 lcf->upstream->host.data, len);
1284
1285 lcf->peers->peers[0].addr_port_text.data[len++] = ':';
1286
1287 ngx_cpystrn(lcf->peers->peers[0].addr_port_text.data + len,
1288 lcf->upstream->port_text.data,
1289 lcf->upstream->port_text.len + 1);
1290 }
1291
1292 ctx = cf->ctx;
1293 clcf = ctx->loc_conf[ngx_http_core_module.ctx_index];
1294 lcf->upstream->location = &clcf->name;
1295 clcf->handler = ngx_http_proxy_handler;
1296
1297 return NULL;
1298 }
1299
1300 static char *ngx_http_proxy_parse_upstream(ngx_str_t *url,
1301 ngx_http_proxy_upstream_t *u)
1302 {
1303 size_t i;
1304
1305 if (url->data[0] == ':' || url->data[0] == '/') {
1306 return "invalid upstream URL";
1307 }
1308
1309 u->host.data = url->data;
1310 u->host_header.data = url->data;
1311
1312 for (i = 1; i < url->len; i++) {
1313 if (url->data[i] == ':') {
1314 u->port_text.data = &url->data[i] + 1;
1315 u->host.len = i;
1316 }
1317
1318 if (url->data[i] == '/') {
1319 u->uri.data = &url->data[i];
1320 u->uri.len = url->len - i;
1321 u->host_header.len = i;
1322
1323 if (u->host.len == 0) {
1324 u->host.len = i;
1325 }
1326
1327 if (u->port_text.data == NULL) {
1328 u->port = htons(80);
1329 u->port_text.len = 2;
1330 u->port_text.data = "80";
1331 return NULL;
1332 }
1333
1334 u->port_text.len = &url->data[i] - u->port_text.data;
1335
1336 if (u->port_text.len > 0) {
1337 u->port = ngx_atoi(u->port_text.data, u->port_text.len);
1338 if (u->port > 0) {
1339 u->port = htons((u_short) u->port);
1340 return NULL;
1341 }
1342 }
1343
1344 return "invalid port in upstream URL";
1345 }
1346 }
1347
1348 if (u->host.len == 0) {
1349 u->host.len = i;
1350 }
1351
1352 u->host_header.len = i;
1353
1354 u->uri.data = "/";
1355 u->uri.len = 1;
1356
1357 if (u->port_text.data == NULL) {
1358 u->port = htons(80);
1359 u->port_text.len = 2;
1360 u->port_text.data = "80";
1361 return NULL;
1362 }
1363
1364 u->port_text.len = &url->data[i] - u->port_text.data;
1365
1366 if (u->port_text.len > 0) {
1367 u->port = ngx_atoi(u->port_text.data, u->port_text.len);
1368 if (u->port > 0) {
1369 u->port = htons((u_short) u->port);
1370 return NULL;
1371 }
1372 }
1373
1374 return "invalid port in upstream URL";
1375 }