Mercurial > hg > nginx
comparison src/http/modules/ngx_http_fastcgi_module.c @ 1990:c7757ce0ae97 stable-0.5
r1699, r1700, r1701, r1702, r1707 merge:
upstream parse_header fix and optimization,
fix fastcgi_catch_stderr segfault merged in r1524:
*) return NGX_HTTP_UPSTREAM_INVALID_HEADER for invalid status
*) return NGX_ERROR instead of NGX_HTTP_INTERNAL_SERVER_ERROR
in u->parse_header()
*) return NGX_HTTP_UPSTREAM_INVALID_HEADER instead of NGX_HTTP_BAD_GATEWAY
to go to a next upstream on invalid_header condition
*) now ngx_conf_set_str_array_slot() tests NGX_CONF_UNSET_PTR
this fixes fastcgi_catch_stderr segfault
*) ngx_http_upstream_hide_headers_hash()
*) proxy/fastcgi pass_header/hide_header use
ngx_http_upstream_hide_headers_hash()
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Sun, 04 May 2008 09:29:43 +0000 |
parents | b4d3c9c1ae20 |
children |
comparison
equal
deleted
inserted
replaced
1989:0ba9a893dd1a | 1990:c7757ce0ae97 |
---|---|
883 umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module); | 883 umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module); |
884 | 884 |
885 if (f == NULL) { | 885 if (f == NULL) { |
886 f = ngx_pcalloc(r->pool, sizeof(ngx_http_fastcgi_ctx_t)); | 886 f = ngx_pcalloc(r->pool, sizeof(ngx_http_fastcgi_ctx_t)); |
887 if (f == NULL) { | 887 if (f == NULL) { |
888 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 888 return NGX_ERROR; |
889 } | 889 } |
890 | 890 |
891 ngx_http_set_ctx(r, f, ngx_http_fastcgi_module); | 891 ngx_http_set_ctx(r, f, ngx_http_fastcgi_module); |
892 } | 892 } |
893 | 893 |
991 | 991 |
992 line.data[line.len - 1] = '\0'; | 992 line.data[line.len - 1] = '\0'; |
993 | 993 |
994 for (i = 0; i < flcf->catch_stderr->nelts; i++) { | 994 for (i = 0; i < flcf->catch_stderr->nelts; i++) { |
995 if (ngx_strstr(line.data, pattern[i].data)) { | 995 if (ngx_strstr(line.data, pattern[i].data)) { |
996 return NGX_HTTP_BAD_GATEWAY; | 996 return NGX_HTTP_UPSTREAM_INVALID_HEADER; |
997 } | 997 } |
998 } | 998 } |
999 } | 999 } |
1000 | 1000 |
1001 if (u->buffer.pos == u->buffer.last) { | 1001 if (u->buffer.pos == u->buffer.last) { |
1059 | 1059 |
1060 /* a header line has been parsed successfully */ | 1060 /* a header line has been parsed successfully */ |
1061 | 1061 |
1062 h = ngx_list_push(&u->headers_in.headers); | 1062 h = ngx_list_push(&u->headers_in.headers); |
1063 if (h == NULL) { | 1063 if (h == NULL) { |
1064 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 1064 return NGX_ERROR; |
1065 } | 1065 } |
1066 | 1066 |
1067 if (f->split_parts && f->split_parts->nelts) { | 1067 if (f->split_parts && f->split_parts->nelts) { |
1068 | 1068 |
1069 part = f->split_parts->elts; | 1069 part = f->split_parts->elts; |
1073 size += part[i].end - part[i].start; | 1073 size += part[i].end - part[i].start; |
1074 } | 1074 } |
1075 | 1075 |
1076 p = ngx_palloc(r->pool, size); | 1076 p = ngx_palloc(r->pool, size); |
1077 if (p == NULL) { | 1077 if (p == NULL) { |
1078 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 1078 return NGX_ERROR; |
1079 } | 1079 } |
1080 | 1080 |
1081 buf.pos = p; | 1081 buf.pos = p; |
1082 | 1082 |
1083 for (i = 0; i < f->split_parts->nelts; i++) { | 1083 for (i = 0; i < f->split_parts->nelts; i++) { |
1101 h->value.data = r->header_start; | 1101 h->value.data = r->header_start; |
1102 h->value.data[h->value.len] = '\0'; | 1102 h->value.data[h->value.len] = '\0'; |
1103 | 1103 |
1104 h->lowcase_key = ngx_palloc(r->pool, h->key.len); | 1104 h->lowcase_key = ngx_palloc(r->pool, h->key.len); |
1105 if (h->lowcase_key == NULL) { | 1105 if (h->lowcase_key == NULL) { |
1106 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 1106 return NGX_ERROR; |
1107 } | 1107 } |
1108 | 1108 |
1109 } else { | 1109 } else { |
1110 | 1110 |
1111 h->key.len = r->header_name_end - r->header_name_start; | 1111 h->key.len = r->header_name_end - r->header_name_start; |
1113 | 1113 |
1114 h->key.data = ngx_palloc(r->pool, | 1114 h->key.data = ngx_palloc(r->pool, |
1115 h->key.len + 1 + h->value.len + 1 | 1115 h->key.len + 1 + h->value.len + 1 |
1116 + h->key.len); | 1116 + h->key.len); |
1117 if (h->key.data == NULL) { | 1117 if (h->key.data == NULL) { |
1118 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 1118 return NGX_ERROR; |
1119 } | 1119 } |
1120 | 1120 |
1121 h->value.data = h->key.data + h->key.len + 1; | 1121 h->value.data = h->key.data + h->key.len + 1; |
1122 h->lowcase_key = h->key.data + h->key.len + 1 | 1122 h->lowcase_key = h->key.data + h->key.len + 1 |
1123 + h->value.len + 1; | 1123 + h->value.len + 1; |
1141 | 1141 |
1142 hh = ngx_hash_find(&umcf->headers_in_hash, h->hash, | 1142 hh = ngx_hash_find(&umcf->headers_in_hash, h->hash, |
1143 h->lowcase_key, h->key.len); | 1143 h->lowcase_key, h->key.len); |
1144 | 1144 |
1145 if (hh && hh->handler(r, h, hh->offset) != NGX_OK) { | 1145 if (hh && hh->handler(r, h, hh->offset) != NGX_OK) { |
1146 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 1146 return NGX_ERROR; |
1147 } | 1147 } |
1148 | 1148 |
1149 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 1149 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
1150 "http fastcgi header: \"%V: %V\"", | 1150 "http fastcgi header: \"%V: %V\"", |
1151 &h->key, &h->value); | 1151 &h->key, &h->value); |
1170 status_line = &u->headers_in.status->value; | 1170 status_line = &u->headers_in.status->value; |
1171 | 1171 |
1172 status = ngx_atoi(status_line->data, 3); | 1172 status = ngx_atoi(status_line->data, 3); |
1173 | 1173 |
1174 if (status == NGX_ERROR) { | 1174 if (status == NGX_ERROR) { |
1175 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 1175 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
1176 "upstream sent invalid status \"%V\"", | |
1177 status_line); | |
1178 return NGX_HTTP_UPSTREAM_INVALID_HEADER; | |
1176 } | 1179 } |
1177 | 1180 |
1178 u->headers_in.status_n = status; | 1181 u->headers_in.status_n = status; |
1179 u->headers_in.status_line = *status_line; | 1182 u->headers_in.status_line = *status_line; |
1180 | 1183 |
1231 | 1234 |
1232 if (f->split_parts == NULL) { | 1235 if (f->split_parts == NULL) { |
1233 f->split_parts = ngx_array_create(r->pool, 1, | 1236 f->split_parts = ngx_array_create(r->pool, 1, |
1234 sizeof(ngx_http_fastcgi_split_part_t)); | 1237 sizeof(ngx_http_fastcgi_split_part_t)); |
1235 if (f->split_parts == NULL) { | 1238 if (f->split_parts == NULL) { |
1236 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 1239 return NGX_ERROR; |
1237 } | 1240 } |
1238 } | 1241 } |
1239 | 1242 |
1240 part = ngx_array_push(f->split_parts); | 1243 part = ngx_array_push(f->split_parts); |
1241 | 1244 |
1636 * | 1639 * |
1637 * conf->upstream.bufs.num = 0; | 1640 * conf->upstream.bufs.num = 0; |
1638 * conf->upstream.next_upstream = 0; | 1641 * conf->upstream.next_upstream = 0; |
1639 * conf->upstream.temp_path = NULL; | 1642 * conf->upstream.temp_path = NULL; |
1640 * conf->upstream.hide_headers_hash = { NULL, 0 }; | 1643 * conf->upstream.hide_headers_hash = { NULL, 0 }; |
1641 * conf->upstream.hide_headers = NULL; | |
1642 * conf->upstream.pass_headers = NULL; | |
1643 * conf->upstream.schema = { 0, NULL }; | 1644 * conf->upstream.schema = { 0, NULL }; |
1644 * conf->upstream.uri = { 0, NULL }; | 1645 * conf->upstream.uri = { 0, NULL }; |
1645 * conf->upstream.location = NULL; | 1646 * conf->upstream.location = NULL; |
1646 * conf->upstream.store_lengths = NULL; | 1647 * conf->upstream.store_lengths = NULL; |
1647 * conf->upstream.store_values = NULL; | 1648 * conf->upstream.store_values = NULL; |
1667 conf->upstream.temp_file_write_size_conf = NGX_CONF_UNSET_SIZE; | 1668 conf->upstream.temp_file_write_size_conf = NGX_CONF_UNSET_SIZE; |
1668 | 1669 |
1669 conf->upstream.pass_request_headers = NGX_CONF_UNSET; | 1670 conf->upstream.pass_request_headers = NGX_CONF_UNSET; |
1670 conf->upstream.pass_request_body = NGX_CONF_UNSET; | 1671 conf->upstream.pass_request_body = NGX_CONF_UNSET; |
1671 | 1672 |
1673 conf->upstream.hide_headers = NGX_CONF_UNSET_PTR; | |
1674 conf->upstream.pass_headers = NGX_CONF_UNSET_PTR; | |
1675 | |
1672 conf->upstream.intercept_errors = NGX_CONF_UNSET; | 1676 conf->upstream.intercept_errors = NGX_CONF_UNSET; |
1673 | 1677 |
1674 /* "fastcgi_cyclic_temp_file" is disabled */ | 1678 /* "fastcgi_cyclic_temp_file" is disabled */ |
1675 conf->upstream.cyclic_temp_file = 0; | 1679 conf->upstream.cyclic_temp_file = 0; |
1676 | 1680 |
1687 ngx_http_fastcgi_loc_conf_t *conf = child; | 1691 ngx_http_fastcgi_loc_conf_t *conf = child; |
1688 | 1692 |
1689 u_char *p; | 1693 u_char *p; |
1690 size_t size; | 1694 size_t size; |
1691 uintptr_t *code; | 1695 uintptr_t *code; |
1692 ngx_str_t *header; | 1696 ngx_uint_t i; |
1693 ngx_uint_t i, j; | |
1694 ngx_array_t hide_headers; | |
1695 ngx_keyval_t *src; | 1697 ngx_keyval_t *src; |
1696 ngx_hash_key_t *hk; | |
1697 ngx_hash_init_t hash; | 1698 ngx_hash_init_t hash; |
1698 ngx_http_script_compile_t sc; | 1699 ngx_http_script_compile_t sc; |
1699 ngx_http_script_copy_code_t *copy; | 1700 ngx_http_script_copy_code_t *copy; |
1700 | 1701 |
1701 if (conf->upstream.store != 0) { | 1702 if (conf->upstream.store != 0) { |
1853 ngx_conf_merge_ptr_value(conf->catch_stderr, prev->catch_stderr, NULL); | 1854 ngx_conf_merge_ptr_value(conf->catch_stderr, prev->catch_stderr, NULL); |
1854 | 1855 |
1855 | 1856 |
1856 ngx_conf_merge_str_value(conf->index, prev->index, ""); | 1857 ngx_conf_merge_str_value(conf->index, prev->index, ""); |
1857 | 1858 |
1858 if (conf->upstream.hide_headers == NULL | 1859 hash.max_size = 512; |
1859 && conf->upstream.pass_headers == NULL) | 1860 hash.bucket_size = ngx_align(64, ngx_cacheline_size); |
1860 { | 1861 hash.name = "fastcgi_hide_headers_hash"; |
1861 conf->upstream.hide_headers = prev->upstream.hide_headers; | 1862 |
1862 conf->upstream.pass_headers = prev->upstream.pass_headers; | 1863 if (ngx_http_upstream_hide_headers_hash(cf, &conf->upstream, |
1863 conf->upstream.hide_headers_hash = prev->upstream.hide_headers_hash; | 1864 &prev->upstream, |
1864 | 1865 ngx_http_fastcgi_hide_headers, |
1865 if (conf->upstream.hide_headers_hash.buckets) { | 1866 &hash) |
1866 goto peers; | |
1867 } | |
1868 | |
1869 } else { | |
1870 if (conf->upstream.hide_headers == NULL) { | |
1871 conf->upstream.hide_headers = prev->upstream.hide_headers; | |
1872 } | |
1873 | |
1874 if (conf->upstream.pass_headers == NULL) { | |
1875 conf->upstream.pass_headers = prev->upstream.pass_headers; | |
1876 } | |
1877 } | |
1878 | |
1879 if (ngx_array_init(&hide_headers, cf->temp_pool, 4, sizeof(ngx_hash_key_t)) | |
1880 != NGX_OK) | 1867 != NGX_OK) |
1881 { | 1868 { |
1882 return NGX_CONF_ERROR; | 1869 return NGX_CONF_ERROR; |
1883 } | 1870 } |
1884 | |
1885 for (header = ngx_http_fastcgi_hide_headers; header->len; header++) { | |
1886 hk = ngx_array_push(&hide_headers); | |
1887 if (hk == NULL) { | |
1888 return NGX_CONF_ERROR; | |
1889 } | |
1890 | |
1891 hk->key = *header; | |
1892 hk->key_hash = ngx_hash_key_lc(header->data, header->len); | |
1893 hk->value = (void *) 1; | |
1894 } | |
1895 | |
1896 if (conf->upstream.hide_headers) { | |
1897 | |
1898 header = conf->upstream.hide_headers->elts; | |
1899 | |
1900 for (i = 0; i < conf->upstream.hide_headers->nelts; i++) { | |
1901 | |
1902 hk = hide_headers.elts; | |
1903 | |
1904 for (j = 0; j < hide_headers.nelts; j++) { | |
1905 if (ngx_strcasecmp(header[i].data, hk[j].key.data) == 0) { | |
1906 goto exist; | |
1907 } | |
1908 } | |
1909 | |
1910 hk = ngx_array_push(&hide_headers); | |
1911 if (hk == NULL) { | |
1912 return NGX_CONF_ERROR; | |
1913 } | |
1914 | |
1915 hk->key = header[i]; | |
1916 hk->key_hash = ngx_hash_key_lc(header[i].data, header[i].len); | |
1917 hk->value = (void *) 1; | |
1918 | |
1919 exist: | |
1920 | |
1921 continue; | |
1922 } | |
1923 } | |
1924 | |
1925 if (conf->upstream.pass_headers) { | |
1926 | |
1927 hk = hide_headers.elts; | |
1928 header = conf->upstream.pass_headers->elts; | |
1929 | |
1930 for (i = 0; i < conf->upstream.pass_headers->nelts; i++) { | |
1931 | |
1932 for (j = 0; j < hide_headers.nelts; j++) { | |
1933 | |
1934 if (hk[j].key.data == NULL) { | |
1935 continue; | |
1936 } | |
1937 | |
1938 if (ngx_strcasecmp(header[i].data, hk[j].key.data) == 0) { | |
1939 hk[j].key.data = NULL; | |
1940 break; | |
1941 } | |
1942 } | |
1943 } | |
1944 } | |
1945 | |
1946 hash.hash = &conf->upstream.hide_headers_hash; | |
1947 hash.key = ngx_hash_key_lc; | |
1948 hash.max_size = 512; | |
1949 hash.bucket_size = ngx_align(64, ngx_cacheline_size); | |
1950 hash.name = "fastcgi_hide_headers_hash"; | |
1951 hash.pool = cf->pool; | |
1952 hash.temp_pool = NULL; | |
1953 | |
1954 if (ngx_hash_init(&hash, hide_headers.elts, hide_headers.nelts) != NGX_OK) { | |
1955 return NGX_CONF_ERROR; | |
1956 } | |
1957 | |
1958 peers: | |
1959 | 1871 |
1960 if (conf->upstream.upstream == NULL) { | 1872 if (conf->upstream.upstream == NULL) { |
1961 conf->upstream.upstream = prev->upstream.upstream; | 1873 conf->upstream.upstream = prev->upstream.upstream; |
1962 conf->upstream.schema = prev->upstream.schema; | 1874 conf->upstream.schema = prev->upstream.schema; |
1963 } | 1875 } |