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