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