Mercurial > hg > nginx-quic
comparison src/http/ngx_http_core_module.c @ 2027:f321b59ae0e9
locations tree
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Sat, 24 May 2008 14:14:13 +0000 |
parents | b56d4b1ebac7 |
children | c036922f6f07 |
comparison
equal
deleted
inserted
replaced
2026:72db8932f782 | 2027:f321b59ae0e9 |
---|---|
15 u_char *name; | 15 u_char *name; |
16 uint32_t method; | 16 uint32_t method; |
17 } ngx_http_method_name_t; | 17 } ngx_http_method_name_t; |
18 | 18 |
19 | 19 |
20 #define NGX_HTTP_LOCATION_EXACT 1 | |
21 #define NGX_HTTP_LOCATION_AUTO_REDIRECT 2 | |
22 #define NGX_HTTP_LOCATION_NOREGEX 3 | |
23 #define NGX_HTTP_LOCATION_REGEX 4 | |
24 | |
25 | |
26 #define NGX_HTTP_REQUEST_BODY_FILE_OFF 0 | 20 #define NGX_HTTP_REQUEST_BODY_FILE_OFF 0 |
27 #define NGX_HTTP_REQUEST_BODY_FILE_ON 1 | 21 #define NGX_HTTP_REQUEST_BODY_FILE_ON 1 |
28 #define NGX_HTTP_REQUEST_BODY_FILE_CLEAN 2 | 22 #define NGX_HTTP_REQUEST_BODY_FILE_CLEAN 2 |
29 | 23 |
30 | 24 |
31 static ngx_int_t ngx_http_core_find_location(ngx_http_request_t *r, | 25 static ngx_int_t ngx_http_core_find_location(ngx_http_request_t *r); |
32 ngx_array_t *locations, ngx_uint_t regex_start, size_t len); | 26 static ngx_int_t ngx_http_core_find_static_location(ngx_http_request_t *r, |
27 ngx_http_location_tree_node_t *node); | |
33 | 28 |
34 static ngx_int_t ngx_http_core_preconfiguration(ngx_conf_t *cf); | 29 static ngx_int_t ngx_http_core_preconfiguration(ngx_conf_t *cf); |
35 static void *ngx_http_core_create_main_conf(ngx_conf_t *cf); | 30 static void *ngx_http_core_create_main_conf(ngx_conf_t *cf); |
36 static char *ngx_http_core_init_main_conf(ngx_conf_t *cf, void *conf); | 31 static char *ngx_http_core_init_main_conf(ngx_conf_t *cf, void *conf); |
37 static void *ngx_http_core_create_srv_conf(ngx_conf_t *cf); | 32 static void *ngx_http_core_create_srv_conf(ngx_conf_t *cf); |
43 | 38 |
44 static char *ngx_http_core_server(ngx_conf_t *cf, ngx_command_t *cmd, | 39 static char *ngx_http_core_server(ngx_conf_t *cf, ngx_command_t *cmd, |
45 void *dummy); | 40 void *dummy); |
46 static char *ngx_http_core_location(ngx_conf_t *cf, ngx_command_t *cmd, | 41 static char *ngx_http_core_location(ngx_conf_t *cf, ngx_command_t *cmd, |
47 void *dummy); | 42 void *dummy); |
48 static ngx_int_t ngx_http_core_cmp_locations(const void *first, | |
49 const void *second); | |
50 | 43 |
51 static char *ngx_http_core_types(ngx_conf_t *cf, ngx_command_t *cmd, | 44 static char *ngx_http_core_types(ngx_conf_t *cf, ngx_command_t *cmd, |
52 void *conf); | 45 void *conf); |
53 static char *ngx_http_core_type(ngx_conf_t *cf, ngx_command_t *dummy, | 46 static char *ngx_http_core_type(ngx_conf_t *cf, ngx_command_t *dummy, |
54 void *conf); | 47 void *conf); |
785 { | 778 { |
786 u_char *p; | 779 u_char *p; |
787 size_t len; | 780 size_t len; |
788 ngx_int_t rc; | 781 ngx_int_t rc; |
789 ngx_http_core_loc_conf_t *clcf; | 782 ngx_http_core_loc_conf_t *clcf; |
790 ngx_http_core_srv_conf_t *cscf; | |
791 | 783 |
792 r->content_handler = NULL; | 784 r->content_handler = NULL; |
793 r->uri_changed = 0; | 785 r->uri_changed = 0; |
794 | 786 |
795 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); | 787 rc = ngx_http_core_find_location(r); |
796 | |
797 rc = ngx_http_core_find_location(r, &cscf->locations, cscf->regex_start, 0); | |
798 | 788 |
799 if (rc == NGX_HTTP_INTERNAL_SERVER_ERROR) { | 789 if (rc == NGX_HTTP_INTERNAL_SERVER_ERROR) { |
800 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | 790 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); |
801 return NGX_OK; | 791 return NGX_OK; |
802 } | 792 } |
830 | 820 |
831 ngx_http_finalize_request(r, NGX_HTTP_REQUEST_ENTITY_TOO_LARGE); | 821 ngx_http_finalize_request(r, NGX_HTTP_REQUEST_ENTITY_TOO_LARGE); |
832 return NGX_OK; | 822 return NGX_OK; |
833 } | 823 } |
834 | 824 |
835 | 825 if (rc == NGX_DONE) { |
836 if (rc == NGX_HTTP_LOCATION_AUTO_REDIRECT) { | |
837 r->headers_out.location = ngx_list_push(&r->headers_out.headers); | 826 r->headers_out.location = ngx_list_push(&r->headers_out.headers); |
838 if (r->headers_out.location == NULL) { | 827 if (r->headers_out.location == NULL) { |
839 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | 828 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); |
840 return NGX_OK; | 829 return NGX_OK; |
841 } | 830 } |
1110 } | 1099 } |
1111 } | 1100 } |
1112 | 1101 |
1113 | 1102 |
1114 static ngx_int_t | 1103 static ngx_int_t |
1115 ngx_http_core_find_location(ngx_http_request_t *r, | 1104 ngx_http_core_find_location(ngx_http_request_t *r) |
1116 ngx_array_t *locations, ngx_uint_t regex_start, size_t len) | 1105 { |
1117 { | 1106 ngx_int_t rc; |
1118 ngx_int_t n, rc; | 1107 ngx_http_core_loc_conf_t *pclcf; |
1119 ngx_uint_t i, found; | 1108 |
1109 pclcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | |
1110 | |
1111 rc = ngx_http_core_find_static_location(r, pclcf->static_locations); | |
1112 | |
1113 if (rc == NGX_AGAIN) { | |
1114 /* look up nested locations */ | |
1115 rc = ngx_http_core_find_location(r); | |
1116 } | |
1117 | |
1118 if (rc == NGX_OK || rc == NGX_DONE) { | |
1119 return rc; | |
1120 } | |
1121 | |
1122 /* rc == NGX_DECLINED or rc == NGX_AGAIN in nested location */ | |
1123 | |
1124 #if (NGX_PCRE) | |
1125 { | |
1126 ngx_int_t n; | |
1120 ngx_http_core_loc_conf_t *clcf, **clcfp; | 1127 ngx_http_core_loc_conf_t *clcf, **clcfp; |
1121 #if (NGX_PCRE) | 1128 |
1122 ngx_uint_t noregex; | 1129 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); |
1123 #endif | 1130 |
1124 | 1131 if (clcf->noregex == 0 && pclcf->regex_locations) { |
1125 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 1132 |
1126 "find location for \"%V\"", &r->uri); | 1133 for (clcfp = pclcf->regex_locations; *clcfp; clcfp++) { |
1127 | 1134 |
1128 found = 0; | 1135 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
1129 #if (NGX_PCRE) | 1136 "test location: ~ \"%V\"", &(*clcfp)->name); |
1130 noregex = 0; | 1137 |
1131 #endif | 1138 n = ngx_regex_exec((*clcfp)->regex, &r->uri, NULL, 0); |
1132 | 1139 |
1133 clcfp = locations->elts; | 1140 if (n == NGX_REGEX_NO_MATCHED) { |
1134 for (i = 0; i < locations->nelts; i++) { | |
1135 | |
1136 if (clcfp[i]->noname | |
1137 #if (NGX_PCRE) | |
1138 || clcfp[i]->regex | |
1139 #endif | |
1140 || clcfp[i]->named) | |
1141 { | |
1142 break; | |
1143 } | |
1144 | |
1145 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
1146 "find location: %s\"%V\"", | |
1147 clcfp[i]->exact_match ? "= " : "", &clcfp[i]->name); | |
1148 | |
1149 if (clcfp[i]->auto_redirect | |
1150 && r->uri.len == clcfp[i]->name.len - 1 | |
1151 && ngx_strncmp(r->uri.data, clcfp[i]->name.data, | |
1152 clcfp[i]->name.len - 1) | |
1153 == 0) | |
1154 { | |
1155 /* the locations are lexicographically sorted */ | |
1156 | |
1157 r->loc_conf = clcfp[i]->loc_conf; | |
1158 | |
1159 return NGX_HTTP_LOCATION_AUTO_REDIRECT; | |
1160 } | |
1161 | |
1162 if (r->uri.len < clcfp[i]->name.len) { | |
1163 continue; | |
1164 } | |
1165 | |
1166 n = ngx_strncmp(r->uri.data, clcfp[i]->name.data, clcfp[i]->name.len); | |
1167 | |
1168 if (n < 0) { | |
1169 /* the locations are lexicographically sorted */ | |
1170 break; | |
1171 } | |
1172 | |
1173 if (n == 0) { | |
1174 if (clcfp[i]->exact_match) { | |
1175 | |
1176 if (r->uri.len == clcfp[i]->name.len) { | |
1177 r->loc_conf = clcfp[i]->loc_conf; | |
1178 return NGX_HTTP_LOCATION_EXACT; | |
1179 } | |
1180 | |
1181 continue; | 1141 continue; |
1182 } | 1142 } |
1183 | 1143 |
1184 if (len > clcfp[i]->name.len) { | 1144 if (n < 0) { |
1185 /* the previous match is longer */ | 1145 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, |
1186 break; | 1146 ngx_regex_exec_n |
1147 " failed: %d on \"%V\" using \"%V\"", | |
1148 n, &r->uri, &(*clcfp)->name); | |
1149 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
1187 } | 1150 } |
1188 | 1151 |
1189 found = 1; | 1152 /* match */ |
1190 | 1153 |
1191 r->loc_conf = clcfp[i]->loc_conf; | 1154 r->loc_conf = (*clcfp)->loc_conf; |
1192 #if (NGX_PCRE) | 1155 |
1193 noregex = clcfp[i]->noregex; | 1156 /* look up nested locations */ |
1157 | |
1158 return ngx_http_core_find_location(r); | |
1159 } | |
1160 } | |
1161 } | |
1194 #endif | 1162 #endif |
1195 } | 1163 |
1196 } | 1164 return rc; |
1197 | 1165 } |
1198 if (found) { | 1166 |
1199 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | 1167 |
1200 | 1168 /* |
1201 if (clcf->locations) { | 1169 * NGX_OK - exact match |
1202 rc = ngx_http_core_find_location(r, clcf->locations, | 1170 * NGX_DONE - auto redirect |
1203 clcf->regex_start, len); | 1171 * NGX_AGAIN - inclusive match |
1204 | 1172 * NGX_DECLINED - no match |
1205 if (rc != NGX_OK) { | 1173 */ |
1206 return rc; | 1174 |
1175 static ngx_int_t | |
1176 ngx_http_core_find_static_location(ngx_http_request_t *r, | |
1177 ngx_http_location_tree_node_t *node) | |
1178 { | |
1179 u_char *uri; | |
1180 size_t len, n; | |
1181 ngx_int_t rc, rv; | |
1182 | |
1183 len = r->uri.len; | |
1184 uri = r->uri.data; | |
1185 | |
1186 rv = NGX_DECLINED; | |
1187 | |
1188 for ( ;; ) { | |
1189 | |
1190 if (node == NULL) { | |
1191 return rv; | |
1192 } | |
1193 | |
1194 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
1195 "test location: \"%*s\"", node->len, node->name); | |
1196 | |
1197 n = (len <= (size_t) node->len) ? len : node->len; | |
1198 | |
1199 rc = ngx_memcmp(uri, node->name, n); | |
1200 | |
1201 if (rc != 0) { | |
1202 node = (rc < 0) ? node->left : node->right; | |
1203 | |
1204 continue; | |
1205 } | |
1206 | |
1207 if (len > (size_t) node->len) { | |
1208 | |
1209 if (node->inclusive) { | |
1210 | |
1211 r->loc_conf = node->inclusive->loc_conf; | |
1212 rv = NGX_AGAIN; | |
1213 | |
1214 node = node->tree; | |
1215 uri += n; | |
1216 len -= n; | |
1217 | |
1218 continue; | |
1207 } | 1219 } |
1208 } | 1220 |
1209 } | 1221 /* exact only */ |
1210 | 1222 |
1211 #if (NGX_PCRE) | 1223 node = node->right; |
1212 | 1224 |
1213 if (noregex) { | |
1214 return NGX_HTTP_LOCATION_NOREGEX; | |
1215 } | |
1216 | |
1217 /* regex matches */ | |
1218 | |
1219 for (i = regex_start; i < locations->nelts; i++) { | |
1220 | |
1221 if (!clcfp[i]->regex) { | |
1222 break; | |
1223 } | |
1224 | |
1225 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
1226 "find location: ~ \"%V\"", &clcfp[i]->name); | |
1227 | |
1228 n = ngx_regex_exec(clcfp[i]->regex, &r->uri, NULL, 0); | |
1229 | |
1230 if (n == NGX_REGEX_NO_MATCHED) { | |
1231 continue; | 1225 continue; |
1232 } | 1226 } |
1233 | 1227 |
1234 if (n < 0) { | 1228 if (len == (size_t) node->len) { |
1235 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, | 1229 |
1236 ngx_regex_exec_n | 1230 r->loc_conf = (node->exact) ? node->exact->loc_conf: |
1237 " failed: %d on \"%V\" using \"%V\"", | 1231 node->inclusive->loc_conf; |
1238 n, &r->uri, &clcfp[i]->name); | 1232 return NGX_OK; |
1239 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 1233 } |
1240 } | 1234 |
1241 | 1235 /* len < node->len */ |
1242 /* match */ | 1236 |
1243 | 1237 if (len + 1 == (size_t) node->len && node->auto_redirect) { |
1244 r->loc_conf = clcfp[i]->loc_conf; | 1238 |
1245 | 1239 r->loc_conf = (node->exact) ? node->exact->loc_conf: |
1246 return NGX_HTTP_LOCATION_REGEX; | 1240 node->inclusive->loc_conf; |
1247 } | 1241 rv = NGX_DONE; |
1248 | 1242 } |
1249 #endif /* NGX_PCRE */ | 1243 |
1250 | 1244 node = node->left; |
1251 return NGX_OK; | 1245 } |
1252 } | 1246 } |
1253 | 1247 |
1254 | 1248 |
1255 ngx_int_t | 1249 ngx_int_t |
1256 ngx_http_set_content_type(ngx_http_request_t *r) | 1250 ngx_http_set_content_type(ngx_http_request_t *r) |
1894 | 1888 |
1895 | 1889 |
1896 ngx_int_t | 1890 ngx_int_t |
1897 ngx_http_named_location(ngx_http_request_t *r, ngx_str_t *name) | 1891 ngx_http_named_location(ngx_http_request_t *r, ngx_str_t *name) |
1898 { | 1892 { |
1899 ngx_uint_t i; | |
1900 ngx_http_core_srv_conf_t *cscf; | 1893 ngx_http_core_srv_conf_t *cscf; |
1901 ngx_http_core_loc_conf_t **clcfp; | 1894 ngx_http_core_loc_conf_t **clcfp; |
1902 ngx_http_core_main_conf_t *cmcf; | 1895 ngx_http_core_main_conf_t *cmcf; |
1903 | 1896 |
1904 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); | 1897 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); |
1905 | 1898 |
1906 clcfp = cscf->locations.elts; | 1899 for (clcfp = cscf->named_locations; *clcfp; clcfp++) { |
1907 | 1900 |
1908 for (i = cscf->named_start; i < cscf->locations.nelts; i++) { | 1901 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
1909 | 1902 "test location: \"%V\"", &(*clcfp)->name); |
1910 if (name->len != clcfp[i]->name.len | 1903 |
1911 || ngx_strncmp(name->data, clcfp[i]->name.data, name->len) != 0) | 1904 if (name->len != (*clcfp)->name.len |
1905 || ngx_strncmp(name->data, (*clcfp)->name.data, name->len) != 0) | |
1912 { | 1906 { |
1913 continue; | 1907 continue; |
1914 } | 1908 } |
1915 | 1909 |
1916 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 1910 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
1917 "named location: %V \"%V?%V\"", name, &r->uri, &r->args); | 1911 "using location: %V \"%V?%V\"", name, &r->uri, &r->args); |
1918 | 1912 |
1919 r->internal = 1; | 1913 r->internal = 1; |
1920 r->content_handler = NULL; | 1914 r->content_handler = NULL; |
1921 r->loc_conf = clcfp[i]->loc_conf; | 1915 r->loc_conf = (*clcfp)->loc_conf; |
1922 | 1916 |
1923 ngx_http_update_location_config(r); | 1917 ngx_http_update_location_config(r); |
1924 | 1918 |
1925 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); | 1919 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); |
1926 | 1920 |
1933 | 1927 |
1934 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | 1928 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
1935 "could not find named location \"%V\"", name); | 1929 "could not find named location \"%V\"", name); |
1936 | 1930 |
1937 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | 1931 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); |
1932 | |
1938 return NGX_DONE; | 1933 return NGX_DONE; |
1939 } | 1934 } |
1940 | 1935 |
1941 | 1936 |
1942 ngx_http_cleanup_t * | 1937 ngx_http_cleanup_t * |
1981 ngx_uint_t i; | 1976 ngx_uint_t i; |
1982 ngx_conf_t pcf; | 1977 ngx_conf_t pcf; |
1983 ngx_http_module_t *module; | 1978 ngx_http_module_t *module; |
1984 ngx_http_conf_ctx_t *ctx, *http_ctx; | 1979 ngx_http_conf_ctx_t *ctx, *http_ctx; |
1985 ngx_http_core_srv_conf_t *cscf, **cscfp; | 1980 ngx_http_core_srv_conf_t *cscf, **cscfp; |
1986 ngx_http_core_loc_conf_t **clcfp; | |
1987 ngx_http_core_main_conf_t *cmcf; | 1981 ngx_http_core_main_conf_t *cmcf; |
1988 | 1982 |
1989 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)); | 1983 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)); |
1990 if (ctx == NULL) { | 1984 if (ctx == NULL) { |
1991 return NGX_CONF_ERROR; | 1985 return NGX_CONF_ERROR; |
2058 cf->cmd_type = NGX_HTTP_SRV_CONF; | 2052 cf->cmd_type = NGX_HTTP_SRV_CONF; |
2059 | 2053 |
2060 rv = ngx_conf_parse(cf, NULL); | 2054 rv = ngx_conf_parse(cf, NULL); |
2061 | 2055 |
2062 *cf = pcf; | 2056 *cf = pcf; |
2063 | |
2064 if (rv != NGX_CONF_OK) { | |
2065 return rv; | |
2066 } | |
2067 | |
2068 ngx_sort(cscf->locations.elts, (size_t) cscf->locations.nelts, | |
2069 sizeof(ngx_http_core_loc_conf_t *), ngx_http_core_cmp_locations); | |
2070 | |
2071 clcfp = cscf->locations.elts; | |
2072 | |
2073 #if (NGX_PCRE) | |
2074 | |
2075 cscf->regex_start = cscf->locations.nelts; | |
2076 | |
2077 for (i = 0; i < cscf->locations.nelts; i++) { | |
2078 if (clcfp[i]->regex) { | |
2079 cscf->regex_start = i; | |
2080 break; | |
2081 } | |
2082 } | |
2083 | |
2084 #endif | |
2085 | |
2086 cscf->named_start = cscf->locations.nelts; | |
2087 | |
2088 for (i = 0; i < cscf->locations.nelts; i++) { | |
2089 if (clcfp[i]->named) { | |
2090 cscf->named_start = i; | |
2091 break; | |
2092 } | |
2093 } | |
2094 | 2057 |
2095 return rv; | 2058 return rv; |
2096 } | 2059 } |
2097 | 2060 |
2098 | 2061 |
2103 ngx_uint_t i; | 2066 ngx_uint_t i; |
2104 ngx_str_t *value; | 2067 ngx_str_t *value; |
2105 ngx_conf_t save; | 2068 ngx_conf_t save; |
2106 ngx_http_module_t *module; | 2069 ngx_http_module_t *module; |
2107 ngx_http_conf_ctx_t *ctx, *pctx; | 2070 ngx_http_conf_ctx_t *ctx, *pctx; |
2108 ngx_http_core_srv_conf_t *cscf; | 2071 ngx_http_core_loc_conf_t *clcf, *pclcf; |
2109 ngx_http_core_loc_conf_t *clcf, *pclcf, **clcfp; | |
2110 | 2072 |
2111 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)); | 2073 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)); |
2112 if (ctx == NULL) { | 2074 if (ctx == NULL) { |
2113 return NGX_CONF_ERROR; | 2075 return NGX_CONF_ERROR; |
2114 } | 2076 } |
2199 } | 2161 } |
2200 } | 2162 } |
2201 | 2163 |
2202 pclcf = pctx->loc_conf[ngx_http_core_module.ctx_index]; | 2164 pclcf = pctx->loc_conf[ngx_http_core_module.ctx_index]; |
2203 | 2165 |
2204 if (pclcf->name.len == 0) { | 2166 if (pclcf->name.len) { |
2205 cscf = ctx->srv_conf[ngx_http_core_module.ctx_index]; | 2167 |
2206 | 2168 /* nested location */ |
2207 clcfp = ngx_array_push(&cscf->locations); | 2169 |
2208 if (clcfp == NULL) { | |
2209 return NGX_CONF_ERROR; | |
2210 } | |
2211 | |
2212 } else { | |
2213 #if 0 | 2170 #if 0 |
2214 clcf->prev_location = pclcf; | 2171 clcf->prev_location = pclcf; |
2215 #endif | 2172 #endif |
2216 | 2173 |
2217 if (pclcf->exact_match) { | 2174 if (pclcf->exact_match) { |
2225 if (pclcf->named) { | 2182 if (pclcf->named) { |
2226 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | 2183 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
2227 "location \"%V\" could not be inside " | 2184 "location \"%V\" could not be inside " |
2228 "the named location \"%V\"", | 2185 "the named location \"%V\"", |
2229 &clcf->name, &pclcf->name); | 2186 &clcf->name, &pclcf->name); |
2187 return NGX_CONF_ERROR; | |
2188 } | |
2189 | |
2190 if (clcf->named) { | |
2191 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
2192 "named location \"%V\" must be " | |
2193 "on server level only", | |
2194 &clcf->name); | |
2230 return NGX_CONF_ERROR; | 2195 return NGX_CONF_ERROR; |
2231 } | 2196 } |
2232 | 2197 |
2233 #if (NGX_PCRE) | 2198 #if (NGX_PCRE) |
2234 if (clcf->regex == NULL | 2199 if (clcf->regex == NULL |
2242 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | 2207 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
2243 "location \"%V\" is outside location \"%V\"", | 2208 "location \"%V\" is outside location \"%V\"", |
2244 &clcf->name, &pclcf->name); | 2209 &clcf->name, &pclcf->name); |
2245 return NGX_CONF_ERROR; | 2210 return NGX_CONF_ERROR; |
2246 } | 2211 } |
2247 | 2212 } |
2248 if (pclcf->locations == NULL) { | 2213 |
2249 pclcf->locations = ngx_array_create(cf->pool, 2, sizeof(void *)); | 2214 if (ngx_http_add_location(cf, &pclcf->locations, clcf) != NGX_OK) { |
2250 | 2215 return NGX_CONF_ERROR; |
2251 if (pclcf->locations == NULL) { | 2216 } |
2252 return NGX_CONF_ERROR; | |
2253 } | |
2254 } | |
2255 | |
2256 clcfp = ngx_array_push(pclcf->locations); | |
2257 if (clcfp == NULL) { | |
2258 return NGX_CONF_ERROR; | |
2259 } | |
2260 } | |
2261 | |
2262 *clcfp = clcf; | |
2263 | 2217 |
2264 save = *cf; | 2218 save = *cf; |
2265 cf->ctx = ctx; | 2219 cf->ctx = ctx; |
2266 cf->cmd_type = NGX_HTTP_LOC_CONF; | 2220 cf->cmd_type = NGX_HTTP_LOC_CONF; |
2267 | 2221 |
2268 rv = ngx_conf_parse(cf, NULL); | 2222 rv = ngx_conf_parse(cf, NULL); |
2269 | 2223 |
2270 *cf = save; | 2224 *cf = save; |
2271 | 2225 |
2272 if (rv != NGX_CONF_OK) { | |
2273 return rv; | |
2274 } | |
2275 | |
2276 if (clcf->locations == NULL) { | |
2277 return rv; | |
2278 } | |
2279 | |
2280 ngx_sort(clcf->locations->elts, (size_t) clcf->locations->nelts, | |
2281 sizeof(ngx_http_core_loc_conf_t *), ngx_http_core_cmp_locations); | |
2282 | |
2283 #if (NGX_PCRE) | |
2284 | |
2285 clcf->regex_start = clcf->locations->nelts; | |
2286 clcfp = clcf->locations->elts; | |
2287 | |
2288 for (i = 0; i < clcf->locations->nelts; i++) { | |
2289 if (clcfp[i]->regex) { | |
2290 clcf->regex_start = i; | |
2291 break; | |
2292 } | |
2293 } | |
2294 | |
2295 #endif | |
2296 | |
2297 return rv; | 2226 return rv; |
2298 } | |
2299 | |
2300 | |
2301 static ngx_int_t | |
2302 ngx_http_core_cmp_locations(const void *one, const void *two) | |
2303 { | |
2304 ngx_int_t rc; | |
2305 ngx_http_core_loc_conf_t *first, *second; | |
2306 | |
2307 first = *(ngx_http_core_loc_conf_t **) one; | |
2308 second = *(ngx_http_core_loc_conf_t **) two; | |
2309 | |
2310 if (first->named && !second->named) { | |
2311 /* shift named locations to the end */ | |
2312 return 1; | |
2313 } | |
2314 | |
2315 if (!first->named && second->named) { | |
2316 /* shift named locations to the end */ | |
2317 return -1; | |
2318 } | |
2319 | |
2320 if (first->named && second->named) { | |
2321 return ngx_strcmp(first->name.data, second->name.data); | |
2322 } | |
2323 | |
2324 if (first->noname && !second->noname) { | |
2325 /* shift no named locations to the end */ | |
2326 return 1; | |
2327 } | |
2328 | |
2329 if (!first->noname && second->noname) { | |
2330 /* shift no named locations to the end */ | |
2331 return -1; | |
2332 } | |
2333 | |
2334 if (first->noname || second->noname) { | |
2335 /* do not sort no named locations */ | |
2336 return 0; | |
2337 } | |
2338 | |
2339 #if (NGX_PCRE) | |
2340 | |
2341 if (first->regex && !second->regex) { | |
2342 /* shift the regex matches to the end */ | |
2343 return 1; | |
2344 } | |
2345 | |
2346 if (!first->regex && second->regex) { | |
2347 /* shift the regex matches to the end */ | |
2348 return -1; | |
2349 } | |
2350 | |
2351 if (first->regex || second->regex) { | |
2352 /* do not sort the regex matches */ | |
2353 return 0; | |
2354 } | |
2355 | |
2356 #endif | |
2357 | |
2358 rc = ngx_strcmp(first->name.data, second->name.data); | |
2359 | |
2360 if (rc == 0 && second->exact_match) { | |
2361 /* an exact match must be before the same inclusive one */ | |
2362 return 1; | |
2363 } | |
2364 | |
2365 return rc; | |
2366 } | 2227 } |
2367 | 2228 |
2368 | 2229 |
2369 static char * | 2230 static char * |
2370 ngx_http_core_types(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | 2231 ngx_http_core_types(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
2538 /* | 2399 /* |
2539 * set by ngx_pcalloc(): | 2400 * set by ngx_pcalloc(): |
2540 * | 2401 * |
2541 * conf->client_large_buffers.num = 0; | 2402 * conf->client_large_buffers.num = 0; |
2542 */ | 2403 */ |
2543 | |
2544 if (ngx_array_init(&cscf->locations, cf->pool, 4, sizeof(void *)) | |
2545 == NGX_ERROR) | |
2546 { | |
2547 return NGX_CONF_ERROR; | |
2548 } | |
2549 | 2404 |
2550 if (ngx_array_init(&cscf->listen, cf->pool, 4, sizeof(ngx_http_listen_t)) | 2405 if (ngx_array_init(&cscf->listen, cf->pool, 4, sizeof(ngx_http_listen_t)) |
2551 == NGX_ERROR) | 2406 == NGX_ERROR) |
2552 { | 2407 { |
2553 return NGX_CONF_ERROR; | 2408 return NGX_CONF_ERROR; |
3343 | 3198 |
3344 | 3199 |
3345 static char * | 3200 static char * |
3346 ngx_http_core_limit_except(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | 3201 ngx_http_core_limit_except(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
3347 { | 3202 { |
3348 ngx_http_core_loc_conf_t *clcf = conf; | 3203 ngx_http_core_loc_conf_t *pclcf = conf; |
3349 | 3204 |
3350 char *rv; | 3205 char *rv; |
3351 void *mconf; | 3206 void *mconf; |
3352 ngx_str_t *value; | 3207 ngx_str_t *value; |
3353 ngx_uint_t i; | 3208 ngx_uint_t i; |
3354 ngx_conf_t save; | 3209 ngx_conf_t save; |
3355 ngx_http_module_t *module; | 3210 ngx_http_module_t *module; |
3356 ngx_http_conf_ctx_t *ctx, *pctx; | 3211 ngx_http_conf_ctx_t *ctx, *pctx; |
3357 ngx_http_method_name_t *name; | 3212 ngx_http_method_name_t *name; |
3358 ngx_http_core_loc_conf_t *lcf, **clcfp; | 3213 ngx_http_core_loc_conf_t *clcf; |
3359 | 3214 |
3360 if (clcf->limit_except) { | 3215 if (pclcf->limit_except) { |
3361 return "duplicate"; | 3216 return "duplicate"; |
3362 } | 3217 } |
3363 | 3218 |
3364 clcf->limit_except = 0xffffffff; | 3219 pclcf->limit_except = 0xffffffff; |
3365 | 3220 |
3366 value = cf->args->elts; | 3221 value = cf->args->elts; |
3367 | 3222 |
3368 for (i = 1; i < cf->args->nelts; i++) { | 3223 for (i = 1; i < cf->args->nelts; i++) { |
3369 for (name = ngx_methods_names; name->name; name++) { | 3224 for (name = ngx_methods_names; name->name; name++) { |
3370 | 3225 |
3371 if (ngx_strcasecmp(value[i].data, name->name) == 0) { | 3226 if (ngx_strcasecmp(value[i].data, name->name) == 0) { |
3372 clcf->limit_except &= name->method; | 3227 pclcf->limit_except &= name->method; |
3373 goto next; | 3228 goto next; |
3374 } | 3229 } |
3375 } | 3230 } |
3376 | 3231 |
3377 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | 3232 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
3380 | 3235 |
3381 next: | 3236 next: |
3382 continue; | 3237 continue; |
3383 } | 3238 } |
3384 | 3239 |
3385 if (!(clcf->limit_except & NGX_HTTP_GET)) { | 3240 if (!(pclcf->limit_except & NGX_HTTP_GET)) { |
3386 clcf->limit_except &= (uint32_t) ~NGX_HTTP_HEAD; | 3241 pclcf->limit_except &= (uint32_t) ~NGX_HTTP_HEAD; |
3387 } | 3242 } |
3388 | 3243 |
3389 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)); | 3244 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)); |
3390 if (ctx == NULL) { | 3245 if (ctx == NULL) { |
3391 return NGX_CONF_ERROR; | 3246 return NGX_CONF_ERROR; |
3417 ctx->loc_conf[ngx_modules[i]->ctx_index] = mconf; | 3272 ctx->loc_conf[ngx_modules[i]->ctx_index] = mconf; |
3418 } | 3273 } |
3419 } | 3274 } |
3420 | 3275 |
3421 | 3276 |
3422 lcf = ctx->loc_conf[ngx_http_core_module.ctx_index]; | 3277 clcf = ctx->loc_conf[ngx_http_core_module.ctx_index]; |
3423 clcf->limit_except_loc_conf = ctx->loc_conf; | 3278 pclcf->limit_except_loc_conf = ctx->loc_conf; |
3424 lcf->loc_conf = ctx->loc_conf; | 3279 clcf->loc_conf = ctx->loc_conf; |
3425 lcf->name = clcf->name; | 3280 clcf->name = pclcf->name; |
3426 lcf->noname = 1; | 3281 clcf->noname = 1; |
3427 | 3282 |
3428 if (clcf->locations == NULL) { | 3283 if (ngx_http_add_location(cf, &pclcf->locations, clcf) != NGX_OK) { |
3429 clcf->locations = ngx_array_create(cf->pool, 2, sizeof(void *)); | |
3430 if (clcf->locations == NULL) { | |
3431 return NGX_CONF_ERROR; | |
3432 } | |
3433 } | |
3434 | |
3435 clcfp = ngx_array_push(clcf->locations); | |
3436 if (clcfp == NULL) { | |
3437 return NGX_CONF_ERROR; | 3284 return NGX_CONF_ERROR; |
3438 } | 3285 } |
3439 | |
3440 *clcfp = lcf; | |
3441 | |
3442 | 3286 |
3443 save = *cf; | 3287 save = *cf; |
3444 cf->ctx = ctx; | 3288 cf->ctx = ctx; |
3445 cf->cmd_type = NGX_HTTP_LMT_CONF; | 3289 cf->cmd_type = NGX_HTTP_LMT_CONF; |
3446 | 3290 |