Mercurial > hg > nginx
comparison src/http/modules/ngx_http_fastcgi_module.c @ 3097:8393cadef25d stable-0.7
merge r3011, r3012, r3026:
FastCGI fixes:
*) continue to parse available fastcgi record after a split header,
this fixes the erroneous message "upstream prematurely closed connection
while reading response header from upstream"
*) fix a garbage in a split fastcgi header
*) refactor fastcgi stderr handling
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Mon, 07 Sep 2009 10:12:49 +0000 |
parents | f892042956e3 |
children | 2efa8d2fcde1 |
comparison
equal
deleted
inserted
replaced
3096:8ba95d7cab37 | 3097:8393cadef25d |
---|---|
1070 | 1070 |
1071 | 1071 |
1072 static ngx_int_t | 1072 static ngx_int_t |
1073 ngx_http_fastcgi_process_header(ngx_http_request_t *r) | 1073 ngx_http_fastcgi_process_header(ngx_http_request_t *r) |
1074 { | 1074 { |
1075 u_char *p, *start, *last, *part_start; | 1075 u_char *p, *msg, *start, *last, |
1076 *part_start, *part_end; | |
1076 size_t size; | 1077 size_t size; |
1077 ngx_str_t *status_line, line, *pattern; | 1078 ngx_str_t *status_line, *pattern; |
1078 ngx_int_t rc, status; | 1079 ngx_int_t rc, status; |
1079 ngx_buf_t buf; | 1080 ngx_buf_t buf; |
1080 ngx_uint_t i; | 1081 ngx_uint_t i; |
1081 ngx_table_elt_t *h; | 1082 ngx_table_elt_t *h; |
1082 ngx_http_upstream_t *u; | 1083 ngx_http_upstream_t *u; |
1156 /* f->state == ngx_http_fastcgi_st_data */ | 1157 /* f->state == ngx_http_fastcgi_st_data */ |
1157 | 1158 |
1158 if (f->type == NGX_HTTP_FASTCGI_STDERR) { | 1159 if (f->type == NGX_HTTP_FASTCGI_STDERR) { |
1159 | 1160 |
1160 if (f->length) { | 1161 if (f->length) { |
1161 line.data = u->buffer.pos; | 1162 msg = u->buffer.pos; |
1162 | 1163 |
1163 if (u->buffer.pos + f->length <= u->buffer.last) { | 1164 if (u->buffer.pos + f->length <= u->buffer.last) { |
1164 line.len = f->length; | |
1165 u->buffer.pos += f->length; | 1165 u->buffer.pos += f->length; |
1166 f->length = 0; | 1166 f->length = 0; |
1167 f->state = ngx_http_fastcgi_st_padding; | 1167 f->state = ngx_http_fastcgi_st_padding; |
1168 | 1168 |
1169 } else { | 1169 } else { |
1170 line.len = u->buffer.last - u->buffer.pos; | |
1171 f->length -= u->buffer.last - u->buffer.pos; | 1170 f->length -= u->buffer.last - u->buffer.pos; |
1172 u->buffer.pos = u->buffer.last; | 1171 u->buffer.pos = u->buffer.last; |
1173 } | 1172 } |
1174 | 1173 |
1175 while (line.data[line.len - 1] == LF | 1174 for (p = u->buffer.pos - 1; msg < p; p--) { |
1176 || line.data[line.len - 1] == CR | 1175 if (*p != LF && *p != CR && *p != '.' && *p != ' ') { |
1177 || line.data[line.len - 1] == '.' | 1176 break; |
1178 || line.data[line.len - 1] == ' ') | 1177 } |
1179 { | |
1180 line.len--; | |
1181 } | 1178 } |
1182 | 1179 |
1180 p++; | |
1181 | |
1183 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | 1182 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
1184 "FastCGI sent in stderr: \"%V\"", &line); | 1183 "FastCGI sent in stderr: \"%*s\"", p - msg, msg); |
1185 | 1184 |
1186 flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module); | 1185 flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module); |
1187 | 1186 |
1188 if (flcf->catch_stderr) { | 1187 if (flcf->catch_stderr) { |
1189 pattern = flcf->catch_stderr->elts; | 1188 pattern = flcf->catch_stderr->elts; |
1190 | 1189 |
1191 line.data[line.len - 1] = '\0'; | |
1192 | |
1193 for (i = 0; i < flcf->catch_stderr->nelts; i++) { | 1190 for (i = 0; i < flcf->catch_stderr->nelts; i++) { |
1194 if (ngx_strstr(line.data, pattern[i].data)) { | 1191 if (ngx_strnstr(msg, (char *) pattern[i].data, |
1192 p - msg) | |
1193 != NULL) | |
1194 { | |
1195 return NGX_HTTP_UPSTREAM_INVALID_HEADER; | 1195 return NGX_HTTP_UPSTREAM_INVALID_HEADER; |
1196 } | 1196 } |
1197 } | 1197 } |
1198 } | 1198 } |
1199 | 1199 |
1242 } | 1242 } |
1243 | 1243 |
1244 for ( ;; ) { | 1244 for ( ;; ) { |
1245 | 1245 |
1246 part_start = u->buffer.pos; | 1246 part_start = u->buffer.pos; |
1247 part_end = u->buffer.last; | |
1247 | 1248 |
1248 rc = ngx_http_parse_header_line(r, &u->buffer, 1); | 1249 rc = ngx_http_parse_header_line(r, &u->buffer, 1); |
1249 | 1250 |
1250 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 1251 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
1251 "http fastcgi parser: %d", rc); | 1252 "http fastcgi parser: %d", rc); |
1442 } | 1443 } |
1443 | 1444 |
1444 part = ngx_array_push(f->split_parts); | 1445 part = ngx_array_push(f->split_parts); |
1445 | 1446 |
1446 part->start = part_start; | 1447 part->start = part_start; |
1447 part->end = u->buffer.last; | 1448 part->end = part_end; |
1449 | |
1450 if (u->buffer.pos < u->buffer.last) { | |
1451 continue; | |
1452 } | |
1448 | 1453 |
1449 return NGX_AGAIN; | 1454 return NGX_AGAIN; |
1450 } | 1455 } |
1451 } | 1456 } |
1452 | 1457 |
1453 | 1458 |
1454 static ngx_int_t | 1459 static ngx_int_t |
1455 ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf) | 1460 ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf) |
1456 { | 1461 { |
1462 u_char *m, *msg; | |
1457 ngx_int_t rc; | 1463 ngx_int_t rc; |
1458 ngx_buf_t *b, **prev; | 1464 ngx_buf_t *b, **prev; |
1459 ngx_str_t line; | |
1460 ngx_chain_t *cl; | 1465 ngx_chain_t *cl; |
1461 ngx_http_request_t *r; | 1466 ngx_http_request_t *r; |
1462 ngx_http_fastcgi_ctx_t *f; | 1467 ngx_http_fastcgi_ctx_t *f; |
1463 | 1468 |
1464 if (buf->pos == buf->last) { | 1469 if (buf->pos == buf->last) { |
1538 | 1543 |
1539 if (f->pos == f->last) { | 1544 if (f->pos == f->last) { |
1540 break; | 1545 break; |
1541 } | 1546 } |
1542 | 1547 |
1543 line.data = f->pos; | 1548 msg = f->pos; |
1544 | 1549 |
1545 if (f->pos + f->length <= f->last) { | 1550 if (f->pos + f->length <= f->last) { |
1546 line.len = f->length; | |
1547 f->pos += f->length; | 1551 f->pos += f->length; |
1548 f->length = 0; | 1552 f->length = 0; |
1549 f->state = ngx_http_fastcgi_st_padding; | 1553 f->state = ngx_http_fastcgi_st_padding; |
1550 | 1554 |
1551 } else { | 1555 } else { |
1552 line.len = f->last - f->pos; | |
1553 f->length -= f->last - f->pos; | 1556 f->length -= f->last - f->pos; |
1554 f->pos = f->last; | 1557 f->pos = f->last; |
1555 } | 1558 } |
1556 | 1559 |
1557 while (line.data[line.len - 1] == LF | 1560 for (m = f->pos - 1; msg < m; m--) { |
1558 || line.data[line.len - 1] == CR | 1561 if (*m != LF && *m != CR && *m != '.' && *m != ' ') { |
1559 || line.data[line.len - 1] == '.' | 1562 break; |
1560 || line.data[line.len - 1] == ' ') | 1563 } |
1561 { | |
1562 line.len--; | |
1563 } | 1564 } |
1564 | 1565 |
1565 ngx_log_error(NGX_LOG_ERR, p->log, 0, | 1566 ngx_log_error(NGX_LOG_ERR, p->log, 0, |
1566 "FastCGI sent in stderr: \"%V\"", &line); | 1567 "FastCGI sent in stderr: \"%*s\"", |
1568 m + 1 - msg, msg); | |
1567 | 1569 |
1568 if (f->pos == f->last) { | 1570 if (f->pos == f->last) { |
1569 break; | 1571 break; |
1570 } | 1572 } |
1571 | 1573 |