Lines 3-9
Link Here
|
3 |
* |
3 |
* |
4 |
* Apache server module for FastCGI. |
4 |
* Apache server module for FastCGI. |
5 |
* |
5 |
* |
6 |
* $Id: mod_fastcgi.c,v 1.162 2007/11/12 23:00:10 robs Exp $ |
6 |
* $Id: mod_fastcgi.c,v 1.169 2008/11/09 14:31:03 robs Exp $ |
7 |
* |
7 |
* |
8 |
* Copyright (c) 1995-1996 Open Market, Inc. |
8 |
* Copyright (c) 1995-1996 Open Market, Inc. |
9 |
* |
9 |
* |
Lines 647-653
Link Here
|
647 |
{ |
647 |
{ |
648 |
char *p, *next, *name, *value; |
648 |
char *p, *next, *name, *value; |
649 |
int len, flag; |
649 |
int len, flag; |
650 |
int hasContentType, hasStatus, hasLocation; |
650 |
int hasLocation = FALSE; |
651 |
|
651 |
|
652 |
ASSERT(fr->parseHeader == SCAN_CGI_READING_HEADERS); |
652 |
ASSERT(fr->parseHeader == SCAN_CGI_READING_HEADERS); |
653 |
|
653 |
|
Lines 689-695
Link Here
|
689 |
* Parse all the headers. |
689 |
* Parse all the headers. |
690 |
*/ |
690 |
*/ |
691 |
fr->parseHeader = SCAN_CGI_FINISHED; |
691 |
fr->parseHeader = SCAN_CGI_FINISHED; |
692 |
hasContentType = hasStatus = hasLocation = FALSE; |
|
|
693 |
next = (char *)fr->header->elts; |
692 |
next = (char *)fr->header->elts; |
694 |
for(;;) { |
693 |
for(;;) { |
695 |
next = get_header_line(name = next, TRUE); |
694 |
next = get_header_line(name = next, TRUE); |
Lines 718-731
Link Here
|
718 |
if (strcasecmp(name, "Status") == 0) { |
717 |
if (strcasecmp(name, "Status") == 0) { |
719 |
int statusValue = strtol(value, NULL, 10); |
718 |
int statusValue = strtol(value, NULL, 10); |
720 |
|
719 |
|
721 |
if (hasStatus) { |
|
|
722 |
goto DuplicateNotAllowed; |
723 |
} |
724 |
if (statusValue < 0) { |
720 |
if (statusValue < 0) { |
725 |
fr->parseHeader = SCAN_CGI_BAD_HEADER; |
721 |
fr->parseHeader = SCAN_CGI_BAD_HEADER; |
726 |
return ap_psprintf(r->pool, "invalid Status '%s'", value); |
722 |
return ap_psprintf(r->pool, "invalid Status '%s'", value); |
727 |
} |
723 |
} |
728 |
hasStatus = TRUE; |
|
|
729 |
r->status = statusValue; |
724 |
r->status = statusValue; |
730 |
r->status_line = ap_pstrdup(r->pool, value); |
725 |
r->status_line = ap_pstrdup(r->pool, value); |
731 |
continue; |
726 |
continue; |
Lines 733-742
Link Here
|
733 |
|
728 |
|
734 |
if (fr->role == FCGI_RESPONDER) { |
729 |
if (fr->role == FCGI_RESPONDER) { |
735 |
if (strcasecmp(name, "Content-type") == 0) { |
730 |
if (strcasecmp(name, "Content-type") == 0) { |
736 |
if (hasContentType) { |
|
|
737 |
goto DuplicateNotAllowed; |
738 |
} |
739 |
hasContentType = TRUE; |
740 |
#ifdef APACHE2 |
731 |
#ifdef APACHE2 |
741 |
ap_set_content_type(r, value); |
732 |
ap_set_content_type(r, value); |
742 |
#else |
733 |
#else |
Lines 745-756
Link Here
|
745 |
continue; |
736 |
continue; |
746 |
} |
737 |
} |
747 |
|
738 |
|
|
|
739 |
/* |
740 |
* Special case headers that should not persist on error |
741 |
* or across redirects, i.e. use headers_out rather than |
742 |
* err_headers_out. |
743 |
*/ |
744 |
|
748 |
if (strcasecmp(name, "Location") == 0) { |
745 |
if (strcasecmp(name, "Location") == 0) { |
749 |
if (hasLocation) { |
|
|
750 |
goto DuplicateNotAllowed; |
751 |
} |
752 |
hasLocation = TRUE; |
746 |
hasLocation = TRUE; |
753 |
ap_table_set(r->headers_out, "Location", value); |
747 |
ap_table_set(r->headers_out, name, value); |
|
|
748 |
continue; |
749 |
} |
750 |
|
751 |
if (strcasecmp(name, "Content-Length") == 0) { |
752 |
ap_table_set(r->headers_out, name, value); |
754 |
continue; |
753 |
continue; |
755 |
} |
754 |
} |
756 |
|
755 |
|
Lines 841-850
Link Here
|
841 |
*p = '\0'; |
840 |
*p = '\0'; |
842 |
fr->parseHeader = SCAN_CGI_BAD_HEADER; |
841 |
fr->parseHeader = SCAN_CGI_BAD_HEADER; |
843 |
return ap_psprintf(r->pool, "malformed header '%s'", name); |
842 |
return ap_psprintf(r->pool, "malformed header '%s'", name); |
844 |
|
|
|
845 |
DuplicateNotAllowed: |
846 |
fr->parseHeader = SCAN_CGI_BAD_HEADER; |
847 |
return ap_psprintf(r->pool, "duplicate header '%s'", name); |
848 |
} |
843 |
} |
849 |
|
844 |
|
850 |
/* |
845 |
/* |
Lines 1387-1394
Link Here
|
1387 |
} |
1382 |
} |
1388 |
|
1383 |
|
1389 |
/* Connect */ |
1384 |
/* Connect */ |
1390 |
if (connect(fr->fd, (struct sockaddr *)socket_addr, socket_addr_len) == 0) |
1385 |
do { |
|
|
1386 |
if (connect(fr->fd, (struct sockaddr *) socket_addr, socket_addr_len) == 0) { |
1391 |
goto ConnectionComplete; |
1387 |
goto ConnectionComplete; |
|
|
1388 |
} |
1389 |
} while (errno == EINTR); |
1392 |
|
1390 |
|
1393 |
#ifdef WIN32 |
1391 |
#ifdef WIN32 |
1394 |
|
1392 |
|
Lines 1432-1438
Link Here
|
1432 |
tval.tv_sec = dynamicPleaseStartDelay; |
1430 |
tval.tv_sec = dynamicPleaseStartDelay; |
1433 |
tval.tv_usec = 0; |
1431 |
tval.tv_usec = 0; |
1434 |
|
1432 |
|
1435 |
status = ap_select((fr->fd+1), &read_fds, &write_fds, NULL, &tval); |
1433 |
do { |
|
|
1434 |
status = ap_select(fr->fd + 1, &read_fds, &write_fds, NULL, &tval); |
1435 |
} while (status < 0 && errno == EINTR); |
1436 |
|
1436 |
if (status < 0) |
1437 |
if (status < 0) |
1437 |
break; |
1438 |
break; |
1438 |
|
1439 |
|
Lines 1461-1467
Link Here
|
1461 |
FD_SET(fr->fd, &write_fds); |
1462 |
FD_SET(fr->fd, &write_fds); |
1462 |
read_fds = write_fds; |
1463 |
read_fds = write_fds; |
1463 |
|
1464 |
|
1464 |
status = ap_select((fr->fd+1), &read_fds, &write_fds, NULL, &tval); |
1465 |
do { |
|
|
1466 |
status = ap_select(fr->fd + 1, &read_fds, &write_fds, NULL, &tval); |
1467 |
} while (status < 0 && errno == EINTR); |
1465 |
|
1468 |
|
1466 |
if (status == 0) { |
1469 |
if (status == 0) { |
1467 |
ap_log_rerror(FCGI_LOG_ERR_NOERRNO, r, |
1470 |
ap_log_rerror(FCGI_LOG_ERR_NOERRNO, r, |
Lines 1762-1767
Link Here
|
1762 |
} |
1765 |
} |
1763 |
|
1766 |
|
1764 |
client_send = 0; |
1767 |
client_send = 0; |
|
|
1768 |
|
1769 |
if (fcgi_protocol_dequeue(rp, fr)) |
1770 |
{ |
1771 |
state = STATE_ERROR; |
1772 |
break; |
1773 |
} |
1765 |
} |
1774 |
} |
1766 |
|
1775 |
|
1767 |
break; |
1776 |
break; |
Lines 2107-2112
Link Here
|
2107 |
} |
2116 |
} |
2108 |
|
2117 |
|
2109 |
client_send = 0; |
2118 |
client_send = 0; |
|
|
2119 |
|
2120 |
if (fcgi_protocol_dequeue(rp, fr)) |
2121 |
{ |
2122 |
state = STATE_ERROR; |
2123 |
break; |
2124 |
} |
2110 |
} |
2125 |
} |
2111 |
|
2126 |
|
2112 |
break; |
2127 |
break; |
Lines 2193-2199
Link Here
|
2193 |
} |
2208 |
} |
2194 |
|
2209 |
|
2195 |
/* wait on the socket */ |
2210 |
/* wait on the socket */ |
|
|
2211 |
do { |
2196 |
select_status = ap_select(nfds, &read_set, &write_set, NULL, &timeout); |
2212 |
select_status = ap_select(nfds, &read_set, &write_set, NULL, &timeout); |
|
|
2213 |
} while (select_status < 0 && errno == EINTR); |
2197 |
|
2214 |
|
2198 |
if (select_status < 0) |
2215 |
if (select_status < 0) |
2199 |
{ |
2216 |
{ |
Lines 2264-2276
Link Here
|
2264 |
|
2281 |
|
2265 |
if (rv < 0) |
2282 |
if (rv < 0) |
2266 |
{ |
2283 |
{ |
|
|
2284 |
if (errno == EAGAIN) |
2285 |
{ |
2286 |
/* this reportedly occurs on AIX 5.2 sporadically */ |
2287 |
struct timeval tv; |
2288 |
tv.tv_sec = 1; |
2289 |
tv.tv_usec = 0; |
2290 |
|
2291 |
ap_log_rerror(FCGI_LOG_INFO, r, "FastCGI: comm with server " |
2292 |
"\"%s\" interrupted: read will be retried in 1 second", |
2293 |
fr->fs_path); |
2294 |
|
2295 |
/* avoid sleep/alarm interactions */ |
2296 |
ap_select(0, NULL, NULL, NULL, &tv); |
2297 |
} |
2298 |
else |
2299 |
{ |
2267 |
ap_log_rerror(FCGI_LOG_ERR, r, "FastCGI: comm with server " |
2300 |
ap_log_rerror(FCGI_LOG_ERR, r, "FastCGI: comm with server " |
2268 |
"\"%s\" aborted: read failed", fr->fs_path); |
2301 |
"\"%s\" aborted: read failed", fr->fs_path); |
2269 |
state = STATE_ERROR; |
2302 |
state = STATE_ERROR; |
2270 |
break; |
2303 |
break; |
2271 |
} |
2304 |
} |
2272 |
|
2305 |
} |
2273 |
if (rv == 0) |
2306 |
else if (rv == 0) |
2274 |
{ |
2307 |
{ |
2275 |
fr->keepReadingFromFcgiApp = FALSE; |
2308 |
fr->keepReadingFromFcgiApp = FALSE; |
2276 |
state = STATE_CLIENT_SEND; |
2309 |
state = STATE_CLIENT_SEND; |
Lines 2603-2609
Link Here
|
2603 |
return HTTP_MOVED_TEMPORARILY; |
2636 |
return HTTP_MOVED_TEMPORARILY; |
2604 |
|
2637 |
|
2605 |
default: |
2638 |
default: |
|
|
2639 |
#ifdef APACHE2 |
2640 |
{ |
2641 |
apr_bucket_brigade *brigade = apr_brigade_create(r->pool, r->connection->bucket_alloc); |
2642 |
apr_bucket* bucket = apr_bucket_eos_create(r->connection->bucket_alloc); |
2643 |
APR_BRIGADE_INSERT_HEAD(brigade, bucket); |
2644 |
return ap_pass_brigade(r->output_filters, brigade); |
2645 |
} |
2646 |
#else |
2606 |
return OK; |
2647 |
return OK; |
|
|
2648 |
#endif |
2607 |
} |
2649 |
} |
2608 |
} |
2650 |
} |
2609 |
|
2651 |
|