comparison src/http/ngx_http_core_module.c @ 7071:cce6936ed2f4

Precontent phase. The phase is added instead of the try_files phase. Unlike the old phase, the new one supports registering multiple handlers. The try_files implementation is moved to a separate ngx_http_try_files_module, which now registers a precontent phase handler.
author Roman Arutyunyan <arut@nginx.com>
date Thu, 20 Jul 2017 15:51:11 +0300
parents 1b068a4e82d8
children 46ebff8c6396
comparison
equal deleted inserted replaced
7070:f583559aadc7 7071:cce6936ed2f4
58 static char *ngx_http_core_set_aio(ngx_conf_t *cf, ngx_command_t *cmd, 58 static char *ngx_http_core_set_aio(ngx_conf_t *cf, ngx_command_t *cmd,
59 void *conf); 59 void *conf);
60 static char *ngx_http_core_directio(ngx_conf_t *cf, ngx_command_t *cmd, 60 static char *ngx_http_core_directio(ngx_conf_t *cf, ngx_command_t *cmd,
61 void *conf); 61 void *conf);
62 static char *ngx_http_core_error_page(ngx_conf_t *cf, ngx_command_t *cmd, 62 static char *ngx_http_core_error_page(ngx_conf_t *cf, ngx_command_t *cmd,
63 void *conf);
64 static char *ngx_http_core_try_files(ngx_conf_t *cf, ngx_command_t *cmd,
65 void *conf); 63 void *conf);
66 static char *ngx_http_core_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd, 64 static char *ngx_http_core_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd,
67 void *conf); 65 void *conf);
68 static char *ngx_http_core_error_log(ngx_conf_t *cf, ngx_command_t *cmd, 66 static char *ngx_http_core_error_log(ngx_conf_t *cf, ngx_command_t *cmd,
69 void *conf); 67 void *conf);
647 ngx_http_core_error_page, 645 ngx_http_core_error_page,
648 NGX_HTTP_LOC_CONF_OFFSET, 646 NGX_HTTP_LOC_CONF_OFFSET,
649 0, 647 0,
650 NULL }, 648 NULL },
651 649
652 { ngx_string("try_files"),
653 NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_2MORE,
654 ngx_http_core_try_files,
655 NGX_HTTP_LOC_CONF_OFFSET,
656 0,
657 NULL },
658
659 { ngx_string("post_action"), 650 { ngx_string("post_action"),
660 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF 651 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
661 |NGX_CONF_TAKE1, 652 |NGX_CONF_TAKE1,
662 ngx_conf_set_str_slot, 653 ngx_conf_set_str_slot,
663 NGX_HTTP_LOC_CONF_OFFSET, 654 NGX_HTTP_LOC_CONF_OFFSET,
1157 return NGX_AGAIN; 1148 return NGX_AGAIN;
1158 } 1149 }
1159 1150
1160 1151
1161 ngx_int_t 1152 ngx_int_t
1162 ngx_http_core_try_files_phase(ngx_http_request_t *r,
1163 ngx_http_phase_handler_t *ph)
1164 {
1165 size_t len, root, alias, reserve, allocated;
1166 u_char *p, *name;
1167 ngx_str_t path, args;
1168 ngx_uint_t test_dir;
1169 ngx_http_try_file_t *tf;
1170 ngx_open_file_info_t of;
1171 ngx_http_script_code_pt code;
1172 ngx_http_script_engine_t e;
1173 ngx_http_core_loc_conf_t *clcf;
1174 ngx_http_script_len_code_pt lcode;
1175
1176 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1177 "try files phase: %ui", r->phase_handler);
1178
1179 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1180
1181 if (clcf->try_files == NULL) {
1182 r->phase_handler++;
1183 return NGX_AGAIN;
1184 }
1185
1186 allocated = 0;
1187 root = 0;
1188 name = NULL;
1189 /* suppress MSVC warning */
1190 path.data = NULL;
1191
1192 tf = clcf->try_files;
1193
1194 alias = clcf->alias;
1195
1196 for ( ;; ) {
1197
1198 if (tf->lengths) {
1199 ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
1200
1201 e.ip = tf->lengths->elts;
1202 e.request = r;
1203
1204 /* 1 is for terminating '\0' as in static names */
1205 len = 1;
1206
1207 while (*(uintptr_t *) e.ip) {
1208 lcode = *(ngx_http_script_len_code_pt *) e.ip;
1209 len += lcode(&e);
1210 }
1211
1212 } else {
1213 len = tf->name.len;
1214 }
1215
1216 if (!alias) {
1217 reserve = len > r->uri.len ? len - r->uri.len : 0;
1218
1219 } else if (alias == NGX_MAX_SIZE_T_VALUE) {
1220 reserve = len;
1221
1222 } else {
1223 reserve = len > r->uri.len - alias ? len - (r->uri.len - alias) : 0;
1224 }
1225
1226 if (reserve > allocated || !allocated) {
1227
1228 /* 16 bytes are preallocation */
1229 allocated = reserve + 16;
1230
1231 if (ngx_http_map_uri_to_path(r, &path, &root, allocated) == NULL) {
1232 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1233 return NGX_OK;
1234 }
1235
1236 name = path.data + root;
1237 }
1238
1239 if (tf->values == NULL) {
1240
1241 /* tf->name.len includes the terminating '\0' */
1242
1243 ngx_memcpy(name, tf->name.data, tf->name.len);
1244
1245 path.len = (name + tf->name.len - 1) - path.data;
1246
1247 } else {
1248 e.ip = tf->values->elts;
1249 e.pos = name;
1250 e.flushed = 1;
1251
1252 while (*(uintptr_t *) e.ip) {
1253 code = *(ngx_http_script_code_pt *) e.ip;
1254 code((ngx_http_script_engine_t *) &e);
1255 }
1256
1257 path.len = e.pos - path.data;
1258
1259 *e.pos = '\0';
1260
1261 if (alias && alias != NGX_MAX_SIZE_T_VALUE
1262 && ngx_strncmp(name, r->uri.data, alias) == 0)
1263 {
1264 ngx_memmove(name, name + alias, len - alias);
1265 path.len -= alias;
1266 }
1267 }
1268
1269 test_dir = tf->test_dir;
1270
1271 tf++;
1272
1273 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1274 "trying to use %s: \"%s\" \"%s\"",
1275 test_dir ? "dir" : "file", name, path.data);
1276
1277 if (tf->lengths == NULL && tf->name.len == 0) {
1278
1279 if (tf->code) {
1280 ngx_http_finalize_request(r, tf->code);
1281 return NGX_OK;
1282 }
1283
1284 path.len -= root;
1285 path.data += root;
1286
1287 if (path.data[0] == '@') {
1288 (void) ngx_http_named_location(r, &path);
1289
1290 } else {
1291 ngx_http_split_args(r, &path, &args);
1292
1293 (void) ngx_http_internal_redirect(r, &path, &args);
1294 }
1295
1296 ngx_http_finalize_request(r, NGX_DONE);
1297 return NGX_OK;
1298 }
1299
1300 ngx_memzero(&of, sizeof(ngx_open_file_info_t));
1301
1302 of.read_ahead = clcf->read_ahead;
1303 of.directio = clcf->directio;
1304 of.valid = clcf->open_file_cache_valid;
1305 of.min_uses = clcf->open_file_cache_min_uses;
1306 of.test_only = 1;
1307 of.errors = clcf->open_file_cache_errors;
1308 of.events = clcf->open_file_cache_events;
1309
1310 if (ngx_http_set_disable_symlinks(r, clcf, &path, &of) != NGX_OK) {
1311 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1312 return NGX_OK;
1313 }
1314
1315 if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
1316 != NGX_OK)
1317 {
1318 if (of.err == 0) {
1319 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1320 return NGX_OK;
1321 }
1322
1323 if (of.err != NGX_ENOENT
1324 && of.err != NGX_ENOTDIR
1325 && of.err != NGX_ENAMETOOLONG)
1326 {
1327 ngx_log_error(NGX_LOG_CRIT, r->connection->log, of.err,
1328 "%s \"%s\" failed", of.failed, path.data);
1329 }
1330
1331 continue;
1332 }
1333
1334 if (of.is_dir != test_dir) {
1335 continue;
1336 }
1337
1338 path.len -= root;
1339 path.data += root;
1340
1341 if (!alias) {
1342 r->uri = path;
1343
1344 } else if (alias == NGX_MAX_SIZE_T_VALUE) {
1345 if (!test_dir) {
1346 r->uri = path;
1347 r->add_uri_to_alias = 1;
1348 }
1349
1350 } else {
1351 name = r->uri.data;
1352
1353 r->uri.len = alias + path.len;
1354 r->uri.data = ngx_pnalloc(r->pool, r->uri.len);
1355 if (r->uri.data == NULL) {
1356 r->uri.len = 0;
1357 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1358 return NGX_OK;
1359 }
1360
1361 p = ngx_copy(r->uri.data, name, alias);
1362 ngx_memcpy(p, path.data, path.len);
1363 }
1364
1365 ngx_http_set_exten(r);
1366
1367 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1368 "try file uri: \"%V\"", &r->uri);
1369
1370 r->phase_handler++;
1371 return NGX_AGAIN;
1372 }
1373
1374 /* not reached */
1375 }
1376
1377
1378 ngx_int_t
1379 ngx_http_core_content_phase(ngx_http_request_t *r, 1153 ngx_http_core_content_phase(ngx_http_request_t *r,
1380 ngx_http_phase_handler_t *ph) 1154 ngx_http_phase_handler_t *ph)
1381 { 1155 {
1382 size_t root; 1156 size_t root;
1383 ngx_int_t rc; 1157 ngx_int_t rc;
3559 * clcf->post_action = { 0, NULL }; 3333 * clcf->post_action = { 0, NULL };
3560 * clcf->types = NULL; 3334 * clcf->types = NULL;
3561 * clcf->default_type = { 0, NULL }; 3335 * clcf->default_type = { 0, NULL };
3562 * clcf->error_log = NULL; 3336 * clcf->error_log = NULL;
3563 * clcf->error_pages = NULL; 3337 * clcf->error_pages = NULL;
3564 * clcf->try_files = NULL;
3565 * clcf->client_body_path = NULL; 3338 * clcf->client_body_path = NULL;
3566 * clcf->regex = NULL; 3339 * clcf->regex = NULL;
3567 * clcf->exact_match = 0; 3340 * clcf->exact_match = 0;
3568 * clcf->auto_redirect = 0; 3341 * clcf->auto_redirect = 0;
3569 * clcf->alias = 0; 3342 * clcf->alias = 0;
4883 return NGX_CONF_OK; 4656 return NGX_CONF_OK;
4884 } 4657 }
4885 4658
4886 4659
4887 static char * 4660 static char *
4888 ngx_http_core_try_files(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
4889 {
4890 ngx_http_core_loc_conf_t *clcf = conf;
4891
4892 ngx_str_t *value;
4893 ngx_int_t code;
4894 ngx_uint_t i, n;
4895 ngx_http_try_file_t *tf;
4896 ngx_http_script_compile_t sc;
4897 ngx_http_core_main_conf_t *cmcf;
4898
4899 if (clcf->try_files) {
4900 return "is duplicate";
4901 }
4902
4903 cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
4904
4905 cmcf->try_files = 1;
4906
4907 tf = ngx_pcalloc(cf->pool, cf->args->nelts * sizeof(ngx_http_try_file_t));
4908 if (tf == NULL) {
4909 return NGX_CONF_ERROR;
4910 }
4911
4912 clcf->try_files = tf;
4913
4914 value = cf->args->elts;
4915
4916 for (i = 0; i < cf->args->nelts - 1; i++) {
4917
4918 tf[i].name = value[i + 1];
4919
4920 if (tf[i].name.len > 0
4921 && tf[i].name.data[tf[i].name.len - 1] == '/'
4922 && i + 2 < cf->args->nelts)
4923 {
4924 tf[i].test_dir = 1;
4925 tf[i].name.len--;
4926 tf[i].name.data[tf[i].name.len] = '\0';
4927 }
4928
4929 n = ngx_http_script_variables_count(&tf[i].name);
4930
4931 if (n) {
4932 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
4933
4934 sc.cf = cf;
4935 sc.source = &tf[i].name;
4936 sc.lengths = &tf[i].lengths;
4937 sc.values = &tf[i].values;
4938 sc.variables = n;
4939 sc.complete_lengths = 1;
4940 sc.complete_values = 1;
4941
4942 if (ngx_http_script_compile(&sc) != NGX_OK) {
4943 return NGX_CONF_ERROR;
4944 }
4945
4946 } else {
4947 /* add trailing '\0' to length */
4948 tf[i].name.len++;
4949 }
4950 }
4951
4952 if (tf[i - 1].name.data[0] == '=') {
4953
4954 code = ngx_atoi(tf[i - 1].name.data + 1, tf[i - 1].name.len - 2);
4955
4956 if (code == NGX_ERROR || code > 999) {
4957 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4958 "invalid code \"%*s\"",
4959 tf[i - 1].name.len - 1, tf[i - 1].name.data);
4960 return NGX_CONF_ERROR;
4961 }
4962
4963 tf[i].code = code;
4964 }
4965
4966 return NGX_CONF_OK;
4967 }
4968
4969
4970 static char *
4971 ngx_http_core_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 4661 ngx_http_core_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
4972 { 4662 {
4973 ngx_http_core_loc_conf_t *clcf = conf; 4663 ngx_http_core_loc_conf_t *clcf = conf;
4974 4664
4975 time_t inactive; 4665 time_t inactive;