Mercurial > hg > nginx
comparison src/http/modules/proxy/ngx_http_event_proxy_handler.c @ 75:869b10be682f
nginx-0.0.1-2003-04-14-21:04:58 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Mon, 14 Apr 2003 17:04:58 +0000 |
parents | 17ab1af8c3dd |
children | 6127d7075471 |
comparison
equal
deleted
inserted
replaced
74:17ab1af8c3dd | 75:869b10be682f |
---|---|
5 #include <ngx_file.h> | 5 #include <ngx_file.h> |
6 #include <ngx_hunk.h> | 6 #include <ngx_hunk.h> |
7 #include <ngx_inet.h> | 7 #include <ngx_inet.h> |
8 #include <ngx_conf_file.h> | 8 #include <ngx_conf_file.h> |
9 #include <ngx_event_write.h> | 9 #include <ngx_event_write.h> |
10 #include <ngx_event_proxy.h> | |
10 | 11 |
11 #include <ngx_http.h> | 12 #include <ngx_http.h> |
12 #include <ngx_http_config.h> | 13 #include <ngx_http_config.h> |
13 #include <ngx_http_core_module.h> | 14 #include <ngx_http_core_module.h> |
14 #include <ngx_http_output_filter.h> | 15 #include <ngx_http_output_filter.h> |
15 #include <ngx_http_event_proxy_handler.h> | 16 #include <ngx_http_event_proxy_handler.h> |
16 | 17 |
18 | |
19 /* STUB */ | |
20 typedef struct { | |
21 int dummy; | |
22 } ngx_cache_header_t; | |
17 | 23 |
18 static int ngx_http_proxy_handler(ngx_http_request_t *r); | 24 static int ngx_http_proxy_handler(ngx_http_request_t *r); |
19 | 25 |
20 static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_proxy_ctx_t *p); | 26 static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_proxy_ctx_t *p); |
21 static int ngx_http_proxy_process_upstream(ngx_http_proxy_ctx_t *p, | 27 static int ngx_http_proxy_process_upstream(ngx_http_proxy_ctx_t *p, |
28 | 34 |
29 static int ngx_http_proxy_process_upstream_status_line(ngx_http_proxy_ctx_t *p); | 35 static int ngx_http_proxy_process_upstream_status_line(ngx_http_proxy_ctx_t *p); |
30 static int ngx_http_proxy_process_upstream_headers(ngx_http_proxy_ctx_t *p); | 36 static int ngx_http_proxy_process_upstream_headers(ngx_http_proxy_ctx_t *p); |
31 static int ngx_http_proxy_process_upstream_header_line(ngx_http_proxy_ctx_t *p); | 37 static int ngx_http_proxy_process_upstream_header_line(ngx_http_proxy_ctx_t *p); |
32 | 38 |
33 | 39 static int ngx_http_proxy_read_upstream_body(ngx_http_proxy_ctx_t *p); |
34 static int ngx_http_proxy_write_upstream_body(ngx_event_t *wev); | 40 static int ngx_http_proxy_write_upstream_body(ngx_http_proxy_ctx_t *p); |
35 | 41 |
36 | 42 |
37 static int ngx_http_proxy_read_response_body(ngx_event_t *ev); | 43 static int ngx_http_proxy_read_response_body(ngx_event_t *ev); |
38 static int ngx_http_proxy_write_to_client(ngx_event_t *ev); | 44 static int ngx_http_proxy_write_to_client(ngx_event_t *ev); |
39 | 45 |
713 ngx_http_request_t *r; | 719 ngx_http_request_t *r; |
714 | 720 |
715 r = p->request; | 721 r = p->request; |
716 | 722 |
717 ngx_test_null(p->header_in, | 723 ngx_test_null(p->header_in, |
718 ngx_create_temp_hunk(r->pool, p->lcf->header_size, 0, 0), | 724 ngx_create_temp_hunk(r->pool, |
725 p->lcf->header_size | |
726 - sizeof(ngx_cache_header_t), | |
727 sizeof(ngx_cache_header_t), | |
728 0), | |
719 NGX_ERROR); | 729 NGX_ERROR); |
720 | 730 |
721 p->header_in->type = NGX_HUNK_MEMORY|NGX_HUNK_IN_MEMORY; | 731 p->header_in->type = NGX_HUNK_MEMORY|NGX_HUNK_IN_MEMORY; |
722 | 732 |
723 #if 0 | 733 #if 0 |
746 static int ngx_http_proxy_read_upstream_header(ngx_http_proxy_ctx_t *p) | 756 static int ngx_http_proxy_read_upstream_header(ngx_http_proxy_ctx_t *p) |
747 { | 757 { |
748 int i, n, rc; | 758 int i, n, rc; |
749 ngx_event_t *rev; | 759 ngx_event_t *rev; |
750 ngx_table_elt_t *ch, *ph; | 760 ngx_table_elt_t *ch, *ph; |
761 ngx_event_proxy_t *ep; | |
751 ngx_http_request_t *r; | 762 ngx_http_request_t *r; |
763 ngx_http_proxy_log_ctx_t *lcx; | |
752 | 764 |
753 rev = p->connection->read; | 765 rev = p->connection->read; |
754 | 766 |
755 do { | 767 do { |
756 n = ngx_event_recv(p->connection, p->header_in->last, | 768 n = ngx_event_recv(p->connection, p->header_in->last, |
831 | 843 |
832 r->headers_out.status = p->status; | 844 r->headers_out.status = p->status; |
833 | 845 |
834 rc = ngx_http_send_header(r); | 846 rc = ngx_http_send_header(r); |
835 | 847 |
848 #if 1 | |
849 rc = ngx_http_output_filter(r, p->header_in); | |
850 | |
851 ngx_test_null(ep, ngx_pcalloc(r->pool, sizeof(ngx_event_proxy_t)), | |
852 NGX_ERROR); | |
853 | |
854 ep->output_filter = (ngx_event_proxy_output_filter_pt) | |
855 ngx_http_output_filter; | |
856 ep->output_data = r; | |
857 ep->block_size = p->lcf->block_size; | |
858 ep->max_block_size = p->lcf->max_block_size; | |
859 ep->file_block_size = p->lcf->file_block_size; | |
860 ep->upstream = p->connection; | |
861 ep->client = r->connection; | |
862 ep->pool = r->pool; | |
863 ep->log = p->log; | |
864 ep->temp_path = p->lcf->temp_path; | |
865 | |
866 ngx_test_null(ep->temp_file, ngx_palloc(r->pool, sizeof(ngx_file_t)), | |
867 NGX_ERROR); | |
868 ep->temp_file->fd = NGX_INVALID_FILE; | |
869 ep->temp_file->log = p->log; | |
870 | |
871 ep->number = 10; | |
872 ep->random = 5; | |
873 | |
874 ep->max_temp_size = 6000; | |
875 ep->temp_file_warn = "an upstream response is buffered " | |
876 "to a temporary file"; | |
877 | |
878 p->event_proxy = ep; | |
879 | |
880 lcx = p->log->data; | |
881 lcx->action = "reading an upstream"; | |
882 | |
883 p->state_read_upstream_handler = ngx_http_proxy_read_upstream_body; | |
884 p->state_write_upstream_handler = ngx_http_proxy_write_upstream_body; | |
885 | |
886 ngx_http_proxy_read_upstream_body(p); | |
887 #endif | |
888 | |
889 #if 0 | |
836 /* STUB */ | 890 /* STUB */ |
837 p->header_in->type |= NGX_HUNK_LAST; | 891 p->header_in->type |= NGX_HUNK_LAST; |
838 rc = ngx_http_output_filter(r, p->header_in); | 892 rc = ngx_http_output_filter(r, p->header_in); |
839 ngx_http_proxy_finalize_request(p, NGX_OK); | 893 ngx_http_proxy_finalize_request(p, NGX_OK); |
894 #endif | |
840 | 895 |
841 /* STUB */ return NGX_DONE; | 896 /* STUB */ return NGX_DONE; |
842 } | 897 } |
843 | 898 |
844 if (rc > NGX_OK) { | 899 if (rc > NGX_OK) { |
1028 | 1083 |
1029 return NGX_OK; | 1084 return NGX_OK; |
1030 } | 1085 } |
1031 | 1086 |
1032 | 1087 |
1088 static int ngx_http_proxy_read_upstream_body(ngx_http_proxy_ctx_t *p) | |
1089 { | |
1090 int rc; | |
1091 | |
1092 rc = ngx_event_proxy_read_upstream(p->event_proxy); | |
1093 if (rc == NGX_OK) { | |
1094 rc = ngx_event_close_connection(p->connection->read); | |
1095 } | |
1096 | |
1097 return rc; | |
1098 } | |
1099 | |
1100 | |
1101 static int ngx_http_proxy_write_upstream_body(ngx_http_proxy_ctx_t *p) | |
1102 { | |
1103 return ngx_event_proxy_write_to_client(p->event_proxy); | |
1104 } | |
1105 | |
1106 | |
1107 #if 0 | |
1033 static int ngx_http_proxy_read_upstream_body(ngx_event_t *rev) | 1108 static int ngx_http_proxy_read_upstream_body(ngx_event_t *rev) |
1034 { | 1109 { |
1035 int rc, n, size; | 1110 int rc, n, size, eof; |
1036 ngx_hunk_t *h; | 1111 ngx_hunk_t *h; |
1037 ngx_chain_t *chain, chain_entry, *ce, *te; | 1112 ngx_chain_t *chain, *ce, *tce; |
1113 ngx_event_t *wev; | |
1038 ngx_connection_t *c; | 1114 ngx_connection_t *c; |
1039 ngx_http_request_t *r; | 1115 ngx_http_request_t *r; |
1040 ngx_http_proxy_ctx_t *p; | 1116 ngx_http_proxy_ctx_t *p; |
1041 | 1117 |
1042 c = (ngx_connection_t *) rev->data; | 1118 c = (ngx_connection_t *) rev->data; |
1043 r = (ngx_http_request_t *) c->data; | 1119 r = (ngx_http_request_t *) c->data; |
1044 p = (ngx_http_proxy_ctx_t *) | 1120 p = (ngx_http_proxy_ctx_t *) |
1045 ngx_http_get_module_ctx(r, ngx_http_proxy_module_ctx); | 1121 ngx_http_get_module_ctx(r, ngx_http_proxy_module_ctx); |
1046 | 1122 |
1047 chain_entry.next = NULL; | 1123 eof = 0; |
1048 | 1124 |
1049 for ( ;; ) { | 1125 for ( ;; ) { |
1050 | 1126 |
1051 #if (USE_KQUEUE) | 1127 #if (USE_KQUEUE) |
1052 | 1128 |
1053 if (ev->eof && ev->available == 0) { | 1129 if (ev->eof && ev->available == 0) { |
1130 eof = 1; | |
1054 break; | 1131 break; |
1055 } | 1132 } |
1056 | 1133 |
1057 #elif (HAVE_KQUEUE0) | 1134 #elif (HAVE_KQUEUE0) |
1058 | 1135 |
1059 if (ngx_event_type == NGX_HAVE_KQUEUE_EVENT | 1136 if (ngx_event_type == NGX_HAVE_KQUEUE_EVENT |
1060 && ev->eof && ev->available == 0) | 1137 && ev->eof && ev->available == 0) |
1061 { | 1138 { |
1139 eof = 1; | |
1062 break; | 1140 break; |
1063 } | 1141 } |
1064 | 1142 |
1065 #endif | 1143 #endif |
1144 | |
1145 /* use the free hunks if they exist */ | |
1066 | 1146 |
1067 if (p->free_hunks) { | 1147 if (p->free_hunks) { |
1068 chain = p->free_hunks; | 1148 chain = p->free_hunks; |
1069 p->free_hunks = NULL; | 1149 p->free_hunks = NULL; |
1150 | |
1151 /* allocate a new hunk if it's still allowed */ | |
1070 | 1152 |
1071 } else if (p->allocated < p->lcf->max_block_size) { | 1153 } else if (p->allocated < p->lcf->max_block_size) { |
1072 ngx_test_null(h, | 1154 ngx_test_null(h, |
1073 ngx_create_temp_hunk(r->pool, p->block_size, 50, 50), | 1155 ngx_create_temp_hunk(r->pool, p->block_size, 50, 50), |
1074 NGX_ERROR); | 1156 NGX_ERROR); |
1075 | 1157 |
1076 p->allocated += p->block_size; | 1158 p->allocated += p->block_size; |
1077 chain_entry.hunk = h; | 1159 |
1078 chain = &chain_entry; | 1160 ngx_test_null(tce, ngx_create_chain_entry(r->pool), NGX_ERROR); |
1161 tce->hunk = h; | |
1162 tce->next = NULL; | |
1163 chain = tce; | |
1164 | |
1165 /* use the shadow hunks if they exist */ | |
1166 | |
1167 } else if (p->shadow_hunks) { | |
1168 chain = p->shadow_hunks; | |
1169 p->shadow_hunks = NULL; | |
1170 | |
1171 /* write all the incoming hunks or the first hunk only | |
1172 to a temporary file and convert them to the shadow hunks */ | |
1079 | 1173 |
1080 } else { | 1174 } else { |
1081 if (p->temp_file->fd == NGX_INVALID_FILE) { | 1175 if (r->cachable) { |
1082 rc = ngx_create_temp_file(p->temp_file, p->lcf->temp_path, | 1176 rc = ngx_http_proxy_write_chain_to_temp_file(p); |
1083 r->pool, 0, 2, r->cachable); | |
1084 | |
1085 if (rc != NGX_OK) { | 1177 if (rc != NGX_OK) { |
1086 return rc; | 1178 return rc; |
1087 } | 1179 } |
1088 | 1180 |
1089 if (p->lcf->temp_file_warn) { | 1181 } else { |
1090 ngx_log_error(NGX_LOG_WARN, p->log, 0, | 1182 tce = p->in_hunks->next; |
1091 "an upstream response is buffered " | 1183 p->in_hunks->next = NULL; |
1092 "to a temporary file"); | 1184 |
1185 rc = ngx_http_proxy_write_chain_to_temp_file(p); | |
1186 if (rc != NGX_OK) { | |
1187 p->in_hunks = tce; | |
1188 return rc; | |
1093 } | 1189 } |
1094 } | 1190 |
1095 | 1191 p->in_hunks = tce; |
1096 n = ngx_write_chain_to_file(p->temp_file, p->in_hunks, | |
1097 p->temp_offset, r->pool); | |
1098 | |
1099 if (n == NGX_ERROR) { | |
1100 return NGX_ERROR; | |
1101 } | |
1102 | |
1103 for (ce = p->in_hunks; ce; ce = ce->next) { | |
1104 ngx_test_null(h, ngx_pcalloc(r->pool, sizeof(ngx_hunk_t)), | |
1105 NGX_ERROR); | |
1106 | |
1107 h->type = NGX_HUNK_FILE | |
1108 |NGX_HUNK_TEMP|NGX_HUNK_IN_MEMORY|NGX_HUNK_RECYCLED; | |
1109 | |
1110 ce->hunk->shadow = h; | |
1111 h->shadow = ce->hunk; | |
1112 | |
1113 h->file_pos = p->temp_offset; | |
1114 p->temp_offset += ce->hunk->last - ce->hunk->pos; | |
1115 h->file_last = p->temp_offset; | |
1116 | |
1117 h->file->fd = p->temp_file->fd; | |
1118 h->file->log = p->log; | |
1119 | |
1120 h->pos = ce->hunk->pos; | |
1121 h->last = ce->hunk->last; | |
1122 h->start = ce->hunk->start; | |
1123 h->end = ce->hunk->end; | |
1124 h->pre_start = ce->hunk->pre_start; | |
1125 h->post_end = ce->hunk->post_end; | |
1126 | |
1127 ngx_test_null(te, ngx_create_chain_entry(r->pool), NGX_ERROR); | |
1128 te->hunk = h; | |
1129 te->next = NULL; | |
1130 | |
1131 if (p->last_out_hunk) { | |
1132 p->last_out_hunk->next = te; | |
1133 p->last_out_hunk = te; | |
1134 | |
1135 } else { | |
1136 p->last_out_hunk = te; | |
1137 } | |
1138 } | 1192 } |
1139 } | 1193 } |
1140 | 1194 |
1141 n = ngx_recv_chain(c, chain); | 1195 n = ngx_recv_chain(c, chain); |
1142 | 1196 |
1147 if (n == NGX_AGAIN) { | 1201 if (n == NGX_AGAIN) { |
1148 return NGX_AGAIN; | 1202 return NGX_AGAIN; |
1149 } | 1203 } |
1150 | 1204 |
1151 if (n == 0) { | 1205 if (n == 0) { |
1206 eof = 1; | |
1152 break; | 1207 break; |
1153 } | 1208 } |
1154 | 1209 |
1155 for (ce = chain; ce && n > 0; ce = ce->next) { | 1210 for (ce = chain; ce && n > 0; ce = ce->next) { |
1156 ngx_test_null(te, ngx_create_chain_entry(r->pool), NGX_ERROR); | 1211 ngx_test_null(tce, ngx_create_chain_entry(r->pool), NGX_ERROR); |
1157 te->hunk = ce->hunk; | 1212 tce->hunk = ce->hunk; |
1158 te->next = NULL; | 1213 tce->next = NULL; |
1159 | 1214 |
1160 if (p->last_in_hunk) { | 1215 if (p->last_in_hunk) { |
1161 p->last_in_hunk->next = te; | 1216 p->last_in_hunk->next = tce; |
1162 p->last_in_hunk = te; | 1217 p->last_in_hunk = tce; |
1163 | 1218 |
1164 } else { | 1219 } else { |
1165 p->last_in_hunk = te; | 1220 p->last_in_hunk = tce; |
1166 } | 1221 } |
1167 | 1222 |
1168 size = ce->hunk->end - ce->hunk->last; | 1223 size = ce->hunk->end - ce->hunk->last; |
1169 | 1224 |
1170 if (n >= size) { | 1225 if (n >= size) { |
1194 | 1249 |
1195 if (ce) { | 1250 if (ce) { |
1196 ce->next = p->free_hunks; | 1251 ce->next = p->free_hunks; |
1197 p->free_hunks = ce; | 1252 p->free_hunks = ce; |
1198 break; | 1253 break; |
1199 | 1254 } |
1200 return NGX_OK; | 1255 } |
1201 } | 1256 |
1202 } | 1257 wev = p->request->connection->write; |
1203 | 1258 |
1204 if (p->out_hunks && p->request->connection->write->ready) { | 1259 if (r->cachable) { |
1205 return | 1260 if (p->in_hunks) { |
1206 ngx_http_proxy_write_upstream_body(p->request->connection->write); | 1261 rc = ngx_http_proxy_write_chain_to_temp_file(p); |
1262 if (rc != NGX_OK) { | |
1263 return rc; | |
1264 } | |
1265 } | |
1266 | |
1267 if (p->out_hunks && wev->ready) { | |
1268 return ngx_http_proxy_write_upstream_body(wev); | |
1269 } | |
1270 | |
1271 } else { | |
1272 if ((p->out_hunks || p->in_hunks) && wev->ready) { | |
1273 return ngx_http_proxy_write_upstream_body(wev); | |
1274 } | |
1207 } | 1275 } |
1208 | 1276 |
1209 return NGX_OK; | 1277 return NGX_OK; |
1210 } | 1278 } |
1211 | 1279 |
1280 | |
1281 static int ngx_http_proxy_write_chain_to_temp_file(ngx_http_proxy_ctx_t *p) | |
1282 { | |
1283 int i, rc; | |
1284 ngx_hunk_t *h; | |
1285 ngx_chain_t *ce, *tce; | |
1286 | |
1287 if (p->temp_file->fd == NGX_INVALID_FILE) { | |
1288 rc = ngx_create_temp_file(p->temp_file, p->lcf->temp_path, | |
1289 p->request->pool, | |
1290 0, 2, | |
1291 p->request->cachable); | |
1292 | |
1293 if (rc != NGX_OK) { | |
1294 return rc; | |
1295 } | |
1296 | |
1297 if (p->lcf->temp_file_warn) { | |
1298 ngx_log_error(NGX_LOG_WARN, p->log, 0, | |
1299 "an upstream response is buffered " | |
1300 "to a temporary file"); | |
1301 } | |
1302 } | |
1303 | |
1304 if (ngx_write_chain_to_file(p->temp_file, p->in_hunks, | |
1305 p->temp_offset, p->request->pool) == NGX_ERROR) { | |
1306 return NGX_ERROR; | |
1307 } | |
1308 | |
1309 for (ce = p->in_hunks; ce; ce = ce->next) { | |
1310 ngx_test_null(h, ngx_pcalloc(p->request->pool, sizeof(ngx_hunk_t)), | |
1311 NGX_ERROR); | |
1312 | |
1313 h->type = NGX_HUNK_FILE | |
1314 |NGX_HUNK_TEMP|NGX_HUNK_IN_MEMORY|NGX_HUNK_RECYCLED; | |
1315 | |
1316 ce->hunk->shadow = h; | |
1317 h->shadow = ce->hunk; | |
1318 | |
1319 h->file_pos = p->temp_offset; | |
1320 p->temp_offset += ce->hunk->last - ce->hunk->pos; | |
1321 h->file_last = p->temp_offset; | |
1322 | |
1323 h->file->fd = p->temp_file->fd; | |
1324 h->file->log = p->log; | |
1325 | |
1326 h->pos = ce->hunk->pos; | |
1327 h->last = ce->hunk->last; | |
1328 h->start = ce->hunk->start; | |
1329 h->end = ce->hunk->end; | |
1330 h->pre_start = ce->hunk->pre_start; | |
1331 h->post_end = ce->hunk->post_end; | |
1332 | |
1333 ngx_test_null(tce, ngx_create_chain_entry(p->request->pool), NGX_ERROR); | |
1334 tce->hunk = h; | |
1335 tce->next = NULL; | |
1336 | |
1337 if (p->last_out_hunk) { | |
1338 p->last_out_hunk->next = tce; | |
1339 p->last_out_hunk = tce; | |
1340 | |
1341 } else { | |
1342 p->last_out_hunk = tce; | |
1343 } | |
1344 } | |
1345 | |
1346 return NGX_OK; | |
1347 } | |
1212 | 1348 |
1213 static int ngx_http_proxy_write_upstream_body(ngx_event_t *wev) | 1349 static int ngx_http_proxy_write_upstream_body(ngx_event_t *wev) |
1214 { | 1350 { |
1215 int rc; | 1351 int rc; |
1216 ngx_hunk_t *h, *sh; | 1352 ngx_hunk_t *h, *sh; |
1254 | 1390 |
1255 return NGX_OK; | 1391 return NGX_OK; |
1256 } | 1392 } |
1257 | 1393 |
1258 | 1394 |
1259 | 1395 #endif |
1260 | 1396 |
1261 | 1397 |
1262 | 1398 |
1263 | 1399 |
1264 static int ngx_http_proxy_read_response_body(ngx_event_t *ev) | 1400 static int ngx_http_proxy_read_response_body(ngx_event_t *ev) |
1626 conf->connect_timeout = 10000; | 1762 conf->connect_timeout = 10000; |
1627 conf->send_timeout = 10000; | 1763 conf->send_timeout = 10000; |
1628 conf->read_timeout = 10000; | 1764 conf->read_timeout = 10000; |
1629 conf->header_size = 1024; | 1765 conf->header_size = 1024; |
1630 conf->block_size = 4096; | 1766 conf->block_size = 4096; |
1631 conf->max_block_size = 32768; | 1767 conf->max_block_size = 4096 * 3; |
1768 conf->file_block_size = 4096; | |
1632 | 1769 |
1633 ngx_test_null(conf->temp_path, ngx_pcalloc(pool, sizeof(ngx_path_t)), NULL); | 1770 ngx_test_null(conf->temp_path, ngx_pcalloc(pool, sizeof(ngx_path_t)), NULL); |
1634 | 1771 |
1635 conf->temp_path->name.data = "temp"; | 1772 conf->temp_path->name.data = "temp"; |
1636 conf->temp_path->name.len = 4; | 1773 conf->temp_path->name.len = 4; |