Mercurial > hg > nginx-mail
comparison src/http/modules/ngx_http_fastcgi_handler.c @ 40:bc4fc02c96a3 NGINX_0_1_20
nginx 0.1.20
*) Feature: the new "script_filename" and "remote_port" parameters of
the fastcgi_params directive.
*) Bugfix: the FastCGI stderr stream was handled incorrectly.
author | Igor Sysoev <http://sysoev.ru> |
---|---|
date | Thu, 17 Feb 2005 00:00:00 +0300 |
parents | a39d1b793287 |
children | 6cfc63e68377 |
comparison
equal
deleted
inserted
replaced
39:9a816ccfbf63 | 40:bc4fc02c96a3 |
---|---|
66 u_char *last; | 66 u_char *last; |
67 ngx_uint_t type; | 67 ngx_uint_t type; |
68 size_t length; | 68 size_t length; |
69 size_t padding; | 69 size_t padding; |
70 | 70 |
71 ngx_uint_t header; | |
72 | |
71 ngx_http_fastcgi_upstream_t *upstream; | 73 ngx_http_fastcgi_upstream_t *upstream; |
72 } ngx_http_fastcgi_ctx_t; | 74 } ngx_http_fastcgi_ctx_t; |
73 | 75 |
74 | 76 |
75 #define NGX_HTTP_FASTCGI_REMOTE_ADDR 0x0002 | 77 #define NGX_HTTP_FASTCGI_REMOTE_ADDR 0x00000002 |
76 #define NGX_HTTP_FASTCGI_REMOTE_USER 0x0004 | 78 #define NGX_HTTP_FASTCGI_REMOTE_USER 0x00000004 |
77 #define NGX_HTTP_FASTCGI_SERVER_NAME 0x0008 | 79 #define NGX_HTTP_FASTCGI_SERVER_NAME 0x00000008 |
78 #define NGX_HTTP_FASTCGI_SERVER_ADDR 0x0010 | 80 #define NGX_HTTP_FASTCGI_SERVER_ADDR 0x00000010 |
79 #define NGX_HTTP_FASTCGI_SERVER_PORT 0x0020 | 81 #define NGX_HTTP_FASTCGI_SERVER_PORT 0x00000020 |
80 #define NGX_HTTP_FASTCGI_SCRIPT_NAME 0x0040 | 82 #define NGX_HTTP_FASTCGI_SCRIPT_NAME 0x00000040 |
81 #define NGX_HTTP_FASTCGI_AUTH_TYPE 0x0080 | 83 #define NGX_HTTP_FASTCGI_AUTH_TYPE 0x00000080 |
82 #define NGX_HTTP_FASTCGI_SERVER_PROTOCOL 0x0100 | 84 #define NGX_HTTP_FASTCGI_SERVER_PROTOCOL 0x00000100 |
83 #define NGX_HTTP_FASTCGI_SERVER_SOFTWARE 0x0200 | 85 #define NGX_HTTP_FASTCGI_SERVER_SOFTWARE 0x00000200 |
84 #define NGX_HTTP_FASTCGI_GATEWAY_INTERFACE 0x0400 | 86 #define NGX_HTTP_FASTCGI_GATEWAY_INTERFACE 0x00000400 |
85 #define NGX_HTTP_FASTCGI_REQUEST_URI 0x0800 | 87 #define NGX_HTTP_FASTCGI_REQUEST_URI 0x00000800 |
86 #define NGX_HTTP_FASTCGI_REDIRECT_STATUS 0x1000 | 88 #define NGX_HTTP_FASTCGI_REDIRECT_STATUS 0x00001000 |
87 #define NGX_HTTP_FASTCGI_DOCUMENT_ROOT 0x2000 | 89 #define NGX_HTTP_FASTCGI_DOCUMENT_ROOT 0x00002000 |
90 #define NGX_HTTP_FASTCGI_SCRIPT_FILENAME 0x00004000 | |
91 #define NGX_HTTP_FASTCGI_REMOTE_PORT 0x00008000 | |
88 | 92 |
89 | 93 |
90 #define NGX_HTTP_FASTCGI_RESPONDER 1 | 94 #define NGX_HTTP_FASTCGI_RESPONDER 1 |
91 | 95 |
92 #define NGX_HTTP_FASTCGI_BEGIN_REQUEST 1 | 96 #define NGX_HTTP_FASTCGI_BEGIN_REQUEST 1 |
197 { ngx_string("server_software"), NGX_HTTP_FASTCGI_SERVER_SOFTWARE }, | 201 { ngx_string("server_software"), NGX_HTTP_FASTCGI_SERVER_SOFTWARE }, |
198 { ngx_string("gateway_interface"), NGX_HTTP_FASTCGI_GATEWAY_INTERFACE }, | 202 { ngx_string("gateway_interface"), NGX_HTTP_FASTCGI_GATEWAY_INTERFACE }, |
199 | 203 |
200 { ngx_string("redirect_status"), NGX_HTTP_FASTCGI_REDIRECT_STATUS }, | 204 { ngx_string("redirect_status"), NGX_HTTP_FASTCGI_REDIRECT_STATUS }, |
201 { ngx_string("request_uri"), NGX_HTTP_FASTCGI_REQUEST_URI }, | 205 { ngx_string("request_uri"), NGX_HTTP_FASTCGI_REQUEST_URI }, |
206 | |
202 { ngx_string("document_root"), NGX_HTTP_FASTCGI_DOCUMENT_ROOT }, | 207 { ngx_string("document_root"), NGX_HTTP_FASTCGI_DOCUMENT_ROOT }, |
208 { ngx_string("script_filename"), NGX_HTTP_FASTCGI_SCRIPT_FILENAME }, | |
209 { ngx_string("remote_port"), NGX_HTTP_FASTCGI_REMOTE_PORT }, | |
203 | 210 |
204 { ngx_null_string, 0 } | 211 { ngx_null_string, 0 } |
205 }; | 212 }; |
206 | 213 |
207 | 214 |
419 | 426 |
420 | 427 |
421 static ngx_int_t | 428 static ngx_int_t |
422 ngx_http_fastcgi_create_request(ngx_http_request_t *r) | 429 ngx_http_fastcgi_create_request(ngx_http_request_t *r) |
423 { | 430 { |
424 u_char ch, *pos, addr_text[INET_ADDRSTRLEN]; | 431 u_char ch, *pos, addr_text[INET_ADDRSTRLEN], |
425 size_t size, len, index, padding, addr_len; | 432 port_text[sizeof("65535") - 1]; |
433 size_t size, len, index, padding, | |
434 addr_len, port_len; | |
426 off_t file_pos; | 435 off_t file_pos; |
427 ngx_buf_t *b; | 436 ngx_buf_t *b; |
428 socklen_t slen; | 437 socklen_t slen; |
429 ngx_chain_t *cl, *body; | 438 ngx_chain_t *cl, *body; |
430 ngx_uint_t i, n, next, *vindex; | 439 ngx_uint_t i, n, next, *vindex, port; |
431 ngx_list_part_t *part; | 440 ngx_list_part_t *part; |
432 ngx_table_elt_t *header; | 441 ngx_table_elt_t *header; |
433 struct sockaddr_in sin; | 442 struct sockaddr_in sin, *sinp; |
434 ngx_http_variable_t *var; | 443 ngx_http_variable_t *var; |
435 ngx_http_variable_value_t *value; | 444 ngx_http_variable_value_t *value; |
436 ngx_http_core_loc_conf_t *clcf; | 445 ngx_http_core_loc_conf_t *clcf; |
437 ngx_http_core_main_conf_t *cmcf; | 446 ngx_http_core_main_conf_t *cmcf; |
438 ngx_http_fastcgi_header_t *h; | 447 ngx_http_fastcgi_header_t *h; |
518 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | 527 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); |
519 len += 1 + ((clcf->root.len > 127) ? 4 : 1) | 528 len += 1 + ((clcf->root.len > 127) ? 4 : 1) |
520 + sizeof("DOCUMENT_ROOT") - 1 + clcf->root.len; | 529 + sizeof("DOCUMENT_ROOT") - 1 + clcf->root.len; |
521 } | 530 } |
522 | 531 |
532 if (flcf->params & NGX_HTTP_FASTCGI_SCRIPT_FILENAME) { | |
533 len += 1 + ((flcf->root.len + r->uri.len + index > 127) ? 4 : 1) | |
534 + sizeof("SCRIPT_FILENAME") - 1 | |
535 + flcf->root.len + r->uri.len + index; | |
536 } | |
537 | |
523 if (flcf->params & NGX_HTTP_FASTCGI_SCRIPT_NAME) { | 538 if (flcf->params & NGX_HTTP_FASTCGI_SCRIPT_NAME) { |
524 len += 1 + ((r->uri.len + index > 127) ? 4 : 1) | 539 len += 1 + ((r->uri.len + index > 127) ? 4 : 1) |
525 + sizeof("SCRIPT_NAME") - 1 + r->uri.len + index ; | 540 + sizeof("SCRIPT_NAME") - 1 + r->uri.len + index ; |
526 } | 541 } |
527 | 542 |
528 if (flcf->params & NGX_HTTP_FASTCGI_REMOTE_ADDR) { | 543 if (flcf->params & NGX_HTTP_FASTCGI_REMOTE_ADDR) { |
529 len += 1 + 1 + sizeof("REMOTE_ADDR") - 1 + r->connection->addr_text.len; | 544 len += 1 + 1 + sizeof("REMOTE_ADDR") - 1 + r->connection->addr_text.len; |
545 } | |
546 | |
547 port_len = 0; | |
548 | |
549 if (flcf->params & NGX_HTTP_FASTCGI_REMOTE_PORT) { | |
550 | |
551 /* AF_INET only */ | |
552 | |
553 if (r->connection->sockaddr->sa_family == AF_INET) { | |
554 sinp = (struct sockaddr_in *) r->connection->sockaddr; | |
555 | |
556 port = ntohs(sinp->sin_port); | |
557 | |
558 if (port > 0 && port < 65536) { | |
559 port_len = ngx_sprintf(port_text, "%ui", port) - port_text; | |
560 } | |
561 | |
562 len += 1 + 1 + sizeof("REMOTE_PORT") - 1 + port_len; | |
563 } | |
530 } | 564 } |
531 | 565 |
532 if (flcf->params & NGX_HTTP_FASTCGI_SERVER_NAME) { | 566 if (flcf->params & NGX_HTTP_FASTCGI_SERVER_NAME) { |
533 len += 1 + 1 + sizeof("SERVER_NAME") - 1 + r->server_name.len; | 567 len += 1 + 1 + sizeof("SERVER_NAME") - 1 + r->server_name.len; |
534 } | 568 } |
829 sizeof("DOCUMENT_ROOT") - 1); | 863 sizeof("DOCUMENT_ROOT") - 1); |
830 b->last = ngx_cpymem(b->last, clcf->root.data, len); | 864 b->last = ngx_cpymem(b->last, clcf->root.data, len); |
831 } | 865 } |
832 | 866 |
833 | 867 |
868 if (flcf->params & NGX_HTTP_FASTCGI_SCRIPT_FILENAME) { | |
869 *b->last++ = sizeof("SCRIPT_FILENAME") - 1; | |
870 | |
871 len = flcf->root.len + r->uri.len + index; | |
872 if (len > 127) { | |
873 *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80); | |
874 *b->last++ = (u_char) ((len >> 16) & 0xff); | |
875 *b->last++ = (u_char) ((len >> 8) & 0xff); | |
876 *b->last++ = (u_char) (len & 0xff); | |
877 | |
878 } else { | |
879 *b->last++ = (u_char) len; | |
880 } | |
881 | |
882 b->last = ngx_cpymem(b->last, "SCRIPT_FILENAME", | |
883 sizeof("SCRIPT_FILENAME") - 1); | |
884 b->last = ngx_cpymem(b->last, flcf->root.data, flcf->root.len); | |
885 b->last = ngx_cpymem(b->last, r->uri.data, r->uri.len); | |
886 | |
887 if (index) { | |
888 b->last = ngx_cpymem(b->last, flcf->index.data, index); | |
889 } | |
890 } | |
891 | |
892 | |
834 if (flcf->params & NGX_HTTP_FASTCGI_SCRIPT_NAME) { | 893 if (flcf->params & NGX_HTTP_FASTCGI_SCRIPT_NAME) { |
835 *b->last++ = sizeof("SCRIPT_NAME") - 1; | 894 *b->last++ = sizeof("SCRIPT_NAME") - 1; |
836 | 895 |
837 len = r->uri.len + index; | 896 len = r->uri.len + index; |
838 if (len > 127) { | 897 if (len > 127) { |
858 *b->last++ = sizeof("REMOTE_ADDR") - 1; | 917 *b->last++ = sizeof("REMOTE_ADDR") - 1; |
859 *b->last++ = (u_char) (r->connection->addr_text.len); | 918 *b->last++ = (u_char) (r->connection->addr_text.len); |
860 b->last = ngx_cpymem(b->last, "REMOTE_ADDR", sizeof("REMOTE_ADDR") - 1); | 919 b->last = ngx_cpymem(b->last, "REMOTE_ADDR", sizeof("REMOTE_ADDR") - 1); |
861 b->last = ngx_cpymem(b->last, r->connection->addr_text.data, | 920 b->last = ngx_cpymem(b->last, r->connection->addr_text.data, |
862 r->connection->addr_text.len); | 921 r->connection->addr_text.len); |
922 } | |
923 | |
924 | |
925 if (port_len) { | |
926 *b->last++ = sizeof("REMOTE_PORT") - 1; | |
927 *b->last++ = (u_char) port_len; | |
928 b->last = ngx_cpymem(b->last, "REMOTE_PORT", sizeof("REMOTE_PORT") - 1); | |
929 b->last = ngx_cpymem(b->last, port_text, port_len); | |
863 } | 930 } |
864 | 931 |
865 | 932 |
866 if (flcf->params & NGX_HTTP_FASTCGI_SERVER_NAME) { | 933 if (flcf->params & NGX_HTTP_FASTCGI_SERVER_NAME) { |
867 *b->last++ = sizeof("SERVER_NAME") - 1; | 934 *b->last++ = sizeof("SERVER_NAME") - 1; |
1149 if (f == NULL) { | 1216 if (f == NULL) { |
1150 return NGX_OK; | 1217 return NGX_OK; |
1151 } | 1218 } |
1152 | 1219 |
1153 f->state = ngx_http_fastcgi_st_version; | 1220 f->state = ngx_http_fastcgi_st_version; |
1221 f->header = 0; | |
1154 | 1222 |
1155 ngx_memzero(&f->upstream->headers_in, | 1223 ngx_memzero(&f->upstream->headers_in, |
1156 sizeof(ngx_http_fastcgi_headers_in_t)); | 1224 sizeof(ngx_http_fastcgi_headers_in_t)); |
1157 | 1225 |
1158 if (f->upstream->headers_in.headers.part.elts) { | 1226 if (f->upstream->headers_in.headers.part.elts) { |
1159 if (ngx_list_init(&f->upstream->headers_in.headers, r->pool, 5, | 1227 if (ngx_list_init(&f->upstream->headers_in.headers, r->pool, 8, |
1160 sizeof(ngx_table_elt_t)) == NGX_ERROR) | 1228 sizeof(ngx_table_elt_t)) == NGX_ERROR) |
1161 { | 1229 { |
1162 return NGX_ERROR; | 1230 return NGX_ERROR; |
1163 } | 1231 } |
1164 } | 1232 } |
1168 | 1236 |
1169 | 1237 |
1170 static ngx_int_t ngx_http_fastcgi_process_header(ngx_http_request_t *r) | 1238 static ngx_int_t ngx_http_fastcgi_process_header(ngx_http_request_t *r) |
1171 { | 1239 { |
1172 u_char *start, *last; | 1240 u_char *start, *last; |
1173 ngx_str_t *status_line; | 1241 ngx_str_t *status_line, line; |
1174 ngx_int_t rc, status; | 1242 ngx_int_t rc, status; |
1175 ngx_uint_t i; | 1243 ngx_uint_t i; |
1176 ngx_table_elt_t *h; | 1244 ngx_table_elt_t *h; |
1177 ngx_http_upstream_t *u; | 1245 ngx_http_upstream_t *u; |
1178 ngx_http_fastcgi_ctx_t *f; | 1246 ngx_http_fastcgi_ctx_t *f; |
1189 f->upstream = ngx_pcalloc(r->pool, sizeof(ngx_http_fastcgi_upstream_t)); | 1257 f->upstream = ngx_pcalloc(r->pool, sizeof(ngx_http_fastcgi_upstream_t)); |
1190 if (f->upstream == NULL) { | 1258 if (f->upstream == NULL) { |
1191 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 1259 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
1192 } | 1260 } |
1193 | 1261 |
1194 if (ngx_list_init(&f->upstream->headers_in.headers, r->pool, 5, | 1262 if (ngx_list_init(&f->upstream->headers_in.headers, r->pool, 8, |
1195 sizeof(ngx_table_elt_t)) == NGX_ERROR) | 1263 sizeof(ngx_table_elt_t)) == NGX_ERROR) |
1196 { | 1264 { |
1197 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 1265 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
1198 } | 1266 } |
1199 } | 1267 } |
1218 | 1286 |
1219 if (rc == NGX_ERROR) { | 1287 if (rc == NGX_ERROR) { |
1220 return NGX_HTTP_UPSTREAM_INVALID_HEADER; | 1288 return NGX_HTTP_UPSTREAM_INVALID_HEADER; |
1221 } | 1289 } |
1222 | 1290 |
1223 if (f->type != NGX_HTTP_FASTCGI_STDOUT) { | 1291 if (f->type != NGX_HTTP_FASTCGI_STDOUT |
1292 && f->type != NGX_HTTP_FASTCGI_STDERR) | |
1293 { | |
1224 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | 1294 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
1225 "upstream sent unexpected FastCGI record: %d", | 1295 "upstream sent unexpected FastCGI record: %d", |
1226 f->type); | 1296 f->type); |
1227 | 1297 |
1228 return NGX_HTTP_UPSTREAM_INVALID_HEADER; | 1298 return NGX_HTTP_UPSTREAM_INVALID_HEADER; |
1229 } | 1299 } |
1230 | 1300 |
1231 if (f->length == 0) { | 1301 if (f->type == NGX_HTTP_FASTCGI_STDOUT && f->length == 0) { |
1232 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | 1302 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
1233 "upstream closed prematurely FastCGI stdout"); | 1303 "upstream closed prematurely FastCGI stdout"); |
1234 | 1304 |
1235 return NGX_HTTP_UPSTREAM_INVALID_HEADER; | 1305 return NGX_HTTP_UPSTREAM_INVALID_HEADER; |
1236 } | 1306 } |
1256 u->header_in.pos = u->header_in.last; | 1326 u->header_in.pos = u->header_in.last; |
1257 | 1327 |
1258 return NGX_AGAIN; | 1328 return NGX_AGAIN; |
1259 } | 1329 } |
1260 | 1330 |
1331 | |
1261 /* f->state == ngx_http_fastcgi_st_data */ | 1332 /* f->state == ngx_http_fastcgi_st_data */ |
1333 | |
1334 if (f->type == NGX_HTTP_FASTCGI_STDERR) { | |
1335 | |
1336 if (f->header) { | |
1337 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, | |
1338 "upstream split a header in FastCGI records"); | |
1339 | |
1340 return NGX_HTTP_UPSTREAM_INVALID_HEADER; | |
1341 } | |
1342 | |
1343 if (f->length) { | |
1344 line.data = u->header_in.pos; | |
1345 | |
1346 if (u->header_in.pos + f->length <= u->header_in.last) { | |
1347 line.len = f->length; | |
1348 u->header_in.pos += f->length; | |
1349 f->length = 0; | |
1350 f->state = ngx_http_fastcgi_st_padding; | |
1351 | |
1352 } else { | |
1353 line.len = u->header_in.last - u->header_in.pos; | |
1354 f->length -= u->header_in.last - u->header_in.pos; | |
1355 u->header_in.pos = u->header_in.last; | |
1356 } | |
1357 | |
1358 while (line.data[line.len - 1] == LF | |
1359 || line.data[line.len - 1] == CR | |
1360 || line.data[line.len - 1] == '.' | |
1361 || line.data[line.len - 1] == ' ') | |
1362 { | |
1363 line.len--; | |
1364 } | |
1365 | |
1366 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
1367 "FastCGI sent in stderr: \"%V\"", &line); | |
1368 | |
1369 if (u->header_in.pos == u->header_in.last) { | |
1370 return NGX_AGAIN; | |
1371 } | |
1372 | |
1373 } else { | |
1374 f->state = ngx_http_fastcgi_st_version; | |
1375 } | |
1376 | |
1377 continue; | |
1378 } | |
1379 | |
1380 | |
1381 /* f->type == NGX_HTTP_FASTCGI_STDOUT */ | |
1262 | 1382 |
1263 start = u->header_in.pos; | 1383 start = u->header_in.pos; |
1264 | 1384 |
1265 if (u->header_in.pos + f->length < u->header_in.last) { | 1385 if (u->header_in.pos + f->length < u->header_in.last) { |
1266 | 1386 |
1273 u->header_in.last = u->header_in.pos + f->length; | 1393 u->header_in.last = u->header_in.pos + f->length; |
1274 | 1394 |
1275 } else { | 1395 } else { |
1276 last = NULL; | 1396 last = NULL; |
1277 } | 1397 } |
1398 | |
1399 f->header = 1; | |
1278 | 1400 |
1279 for ( ;; ) { | 1401 for ( ;; ) { |
1280 | 1402 |
1281 rc = ngx_http_parse_header_line(r, &u->header_in); | 1403 rc = ngx_http_parse_header_line(r, &u->header_in); |
1282 | 1404 |
1570 line.data = f->pos; | 1692 line.data = f->pos; |
1571 | 1693 |
1572 if (f->pos + f->length <= f->last) { | 1694 if (f->pos + f->length <= f->last) { |
1573 line.len = f->length; | 1695 line.len = f->length; |
1574 f->pos += f->length; | 1696 f->pos += f->length; |
1697 f->length = 0; | |
1698 f->state = ngx_http_fastcgi_st_padding; | |
1575 | 1699 |
1576 } else { | 1700 } else { |
1577 line.len = f->last - f->pos; | 1701 line.len = f->last - f->pos; |
1578 f->length -= f->last - f->pos; | 1702 f->length -= f->last - f->pos; |
1579 f->pos = f->last; | 1703 f->pos = f->last; |
1580 } | 1704 } |
1581 | 1705 |
1582 /* | 1706 while (line.data[line.len - 1] == LF |
1583 * TODO: copy split stderr output into buffer, | 1707 || line.data[line.len - 1] == CR |
1584 * clean it up | 1708 || line.data[line.len - 1] == '.' |
1585 */ | 1709 || line.data[line.len - 1] == ' ') |
1710 { | |
1711 line.len--; | |
1712 } | |
1586 | 1713 |
1587 ngx_log_error(NGX_LOG_ERR, p->log, 0, | 1714 ngx_log_error(NGX_LOG_ERR, p->log, 0, |
1588 "FastCGI stderr: %V", &line); | 1715 "FastCGI sent in stderr: \"%V\"", &line); |
1589 | 1716 |
1590 if (f->pos == f->last) { | 1717 if (f->pos == f->last) { |
1591 break; | 1718 break; |
1592 } | 1719 } |
1593 } | 1720 |
1594 | 1721 } else { |
1595 f->state = ngx_http_fastcgi_st_version; | 1722 f->state = ngx_http_fastcgi_st_version; |
1723 } | |
1596 | 1724 |
1597 continue; | 1725 continue; |
1598 } | 1726 } |
1599 | 1727 |
1600 | 1728 |