Mercurial > hg > nginx
comparison src/http/ngx_http_core_module.c @ 2655:87e1fcd9b604 stable-0.6
r2202, r2408, r2425, r2454, r2459, r2482, r2504, r2542, r2565, r2579,
r2580, r2585, r2586, r2587, r2591, r2626 merge:
try_files
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Thu, 02 Apr 2009 06:44:45 +0000 |
parents | a69e3766f698 |
children | 7a10334d4bce |
comparison
equal
deleted
inserted
replaced
2654:96b878c984f4 | 2655:87e1fcd9b604 |
---|---|
59 void *conf); | 59 void *conf); |
60 static char *ngx_http_core_root(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); | 60 static char *ngx_http_core_root(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); |
61 static char *ngx_http_core_limit_except(ngx_conf_t *cf, ngx_command_t *cmd, | 61 static char *ngx_http_core_limit_except(ngx_conf_t *cf, ngx_command_t *cmd, |
62 void *conf); | 62 void *conf); |
63 static char *ngx_http_core_error_page(ngx_conf_t *cf, ngx_command_t *cmd, | 63 static char *ngx_http_core_error_page(ngx_conf_t *cf, ngx_command_t *cmd, |
64 void *conf); | |
65 static char *ngx_http_core_try_files(ngx_conf_t *cf, ngx_command_t *cmd, | |
64 void *conf); | 66 void *conf); |
65 static char *ngx_http_core_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd, | 67 static char *ngx_http_core_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd, |
66 void *conf); | 68 void *conf); |
67 static char *ngx_http_core_error_log(ngx_conf_t *cf, ngx_command_t *cmd, | 69 static char *ngx_http_core_error_log(ngx_conf_t *cf, ngx_command_t *cmd, |
68 void *conf); | 70 void *conf); |
528 ngx_http_core_error_page, | 530 ngx_http_core_error_page, |
529 NGX_HTTP_LOC_CONF_OFFSET, | 531 NGX_HTTP_LOC_CONF_OFFSET, |
530 0, | 532 0, |
531 NULL }, | 533 NULL }, |
532 | 534 |
535 { ngx_string("try_files"), | |
536 NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_2MORE, | |
537 ngx_http_core_try_files, | |
538 NGX_HTTP_LOC_CONF_OFFSET, | |
539 0, | |
540 NULL }, | |
541 | |
533 { ngx_string("post_action"), | 542 { ngx_string("post_action"), |
534 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF | 543 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF |
535 |NGX_CONF_TAKE1, | 544 |NGX_CONF_TAKE1, |
536 ngx_conf_set_str_slot, | 545 ngx_conf_set_str_slot, |
537 NGX_HTTP_LOC_CONF_OFFSET, | 546 NGX_HTTP_LOC_CONF_OFFSET, |
1010 return NGX_AGAIN; | 1019 return NGX_AGAIN; |
1011 } | 1020 } |
1012 | 1021 |
1013 | 1022 |
1014 ngx_int_t | 1023 ngx_int_t |
1024 ngx_http_core_try_files_phase(ngx_http_request_t *r, | |
1025 ngx_http_phase_handler_t *ph) | |
1026 { | |
1027 size_t len, root, alias, reserve, allocated; | |
1028 u_char *p, *name; | |
1029 ngx_str_t path, args; | |
1030 ngx_uint_t test_dir; | |
1031 ngx_http_try_file_t *tf; | |
1032 ngx_open_file_info_t of; | |
1033 ngx_http_script_code_pt code; | |
1034 ngx_http_script_engine_t e; | |
1035 ngx_http_core_loc_conf_t *clcf; | |
1036 ngx_http_script_len_code_pt lcode; | |
1037 | |
1038 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
1039 "try files phase: %ui", r->phase_handler); | |
1040 | |
1041 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | |
1042 | |
1043 if (clcf->try_files == NULL) { | |
1044 r->phase_handler++; | |
1045 return NGX_AGAIN; | |
1046 } | |
1047 | |
1048 allocated = 0; | |
1049 root = 0; | |
1050 name = NULL; | |
1051 /* suppress MSVC warning */ | |
1052 path.data = NULL; | |
1053 | |
1054 tf = clcf->try_files; | |
1055 | |
1056 alias = clcf->alias ? clcf->name.len : 0; | |
1057 | |
1058 for ( ;; ) { | |
1059 | |
1060 if (tf->lengths) { | |
1061 ngx_memzero(&e, sizeof(ngx_http_script_engine_t)); | |
1062 | |
1063 e.ip = tf->lengths->elts; | |
1064 e.request = r; | |
1065 | |
1066 /* 1 is for terminating '\0' as in static names */ | |
1067 len = 1; | |
1068 | |
1069 while (*(uintptr_t *) e.ip) { | |
1070 lcode = *(ngx_http_script_len_code_pt *) e.ip; | |
1071 len += lcode(&e); | |
1072 } | |
1073 | |
1074 } else { | |
1075 len = tf->name.len; | |
1076 } | |
1077 | |
1078 /* 16 bytes are preallocation */ | |
1079 reserve = ngx_abs((ssize_t) (len - r->uri.len)) + alias + 16; | |
1080 | |
1081 if (reserve > allocated) { | |
1082 | |
1083 /* we just need to allocate path and to copy a root */ | |
1084 | |
1085 if (ngx_http_map_uri_to_path(r, &path, &root, reserve) == NULL) { | |
1086 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
1087 return NGX_OK; | |
1088 } | |
1089 | |
1090 name = path.data + root; | |
1091 allocated = path.len - root - (r->uri.len - alias); | |
1092 } | |
1093 | |
1094 if (tf->values == NULL) { | |
1095 | |
1096 /* tf->name.len includes the terminating '\0' */ | |
1097 | |
1098 ngx_memcpy(name, tf->name.data, tf->name.len); | |
1099 | |
1100 path.len = (name + tf->name.len - 1) - path.data; | |
1101 | |
1102 } else { | |
1103 e.ip = tf->values->elts; | |
1104 e.pos = name; | |
1105 e.flushed = 1; | |
1106 | |
1107 while (*(uintptr_t *) e.ip) { | |
1108 code = *(ngx_http_script_code_pt *) e.ip; | |
1109 code((ngx_http_script_engine_t *) &e); | |
1110 } | |
1111 | |
1112 path.len = e.pos - path.data; | |
1113 | |
1114 *e.pos = '\0'; | |
1115 | |
1116 if (alias && ngx_strncmp(name, clcf->name.data, alias) == 0) { | |
1117 ngx_memcpy(name, name + alias, len - alias); | |
1118 path.len -= alias; | |
1119 } | |
1120 } | |
1121 | |
1122 test_dir = tf->test_dir; | |
1123 | |
1124 tf++; | |
1125 | |
1126 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
1127 "try to use file: \"%s\" \"%s\"", name, path.data); | |
1128 | |
1129 if (tf->lengths == NULL && tf->name.len == 0) { | |
1130 | |
1131 path.len -= root; | |
1132 path.data += root; | |
1133 | |
1134 if (path.data[0] == '@') { | |
1135 (void) ngx_http_named_location(r, &path); | |
1136 | |
1137 } else { | |
1138 ngx_http_split_args(r, &path, &args); | |
1139 | |
1140 (void) ngx_http_internal_redirect(r, &path, &args); | |
1141 } | |
1142 | |
1143 return NGX_OK; | |
1144 } | |
1145 | |
1146 ngx_memzero(&of, sizeof(ngx_open_file_info_t)); | |
1147 | |
1148 of.valid = clcf->open_file_cache_valid; | |
1149 of.min_uses = clcf->open_file_cache_min_uses; | |
1150 of.errors = clcf->open_file_cache_errors; | |
1151 of.events = clcf->open_file_cache_events; | |
1152 | |
1153 if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool) | |
1154 != NGX_OK) | |
1155 { | |
1156 if (of.err != NGX_ENOENT && of.err != NGX_ENOTDIR) { | |
1157 ngx_log_error(NGX_LOG_CRIT, r->connection->log, of.err, | |
1158 ngx_open_file_n " \"%s\" failed", path.data); | |
1159 } | |
1160 | |
1161 continue; | |
1162 } | |
1163 | |
1164 if (of.is_dir && !test_dir) { | |
1165 continue; | |
1166 } | |
1167 | |
1168 path.len -= root; | |
1169 path.data += root; | |
1170 | |
1171 if (!alias) { | |
1172 r->uri = path; | |
1173 | |
1174 } else { | |
1175 r->uri.len = alias + path.len; | |
1176 r->uri.data = ngx_palloc(r->pool, r->uri.len); | |
1177 if (r->uri.data == NULL) { | |
1178 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
1179 return NGX_OK; | |
1180 } | |
1181 | |
1182 p = ngx_copy(r->uri.data, clcf->name.data, alias); | |
1183 ngx_memcpy(p, name, path.len); | |
1184 } | |
1185 | |
1186 if (ngx_http_set_exten(r) != NGX_OK) { | |
1187 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
1188 return NGX_OK; | |
1189 } | |
1190 | |
1191 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
1192 "try file uri: \"%V\"", &r->uri); | |
1193 | |
1194 r->phase_handler++; | |
1195 return NGX_AGAIN; | |
1196 } | |
1197 | |
1198 /* not reached */ | |
1199 } | |
1200 | |
1201 | |
1202 ngx_int_t | |
1015 ngx_http_core_content_phase(ngx_http_request_t *r, | 1203 ngx_http_core_content_phase(ngx_http_request_t *r, |
1016 ngx_http_phase_handler_t *ph) | 1204 ngx_http_phase_handler_t *ph) |
1017 { | 1205 { |
1018 size_t root; | 1206 size_t root; |
1019 ngx_int_t rc; | 1207 ngx_int_t rc; |
2685 * lcf->post_action = { 0, NULL }; | 2873 * lcf->post_action = { 0, NULL }; |
2686 * lcf->types = NULL; | 2874 * lcf->types = NULL; |
2687 * lcf->default_type = { 0, NULL }; | 2875 * lcf->default_type = { 0, NULL }; |
2688 * lcf->err_log = NULL; | 2876 * lcf->err_log = NULL; |
2689 * lcf->error_pages = NULL; | 2877 * lcf->error_pages = NULL; |
2878 * lcf->try_files = NULL; | |
2690 * lcf->client_body_path = NULL; | 2879 * lcf->client_body_path = NULL; |
2691 * lcf->regex = NULL; | 2880 * lcf->regex = NULL; |
2692 * lcf->exact_match = 0; | 2881 * lcf->exact_match = 0; |
2693 * lcf->auto_redirect = 0; | 2882 * lcf->auto_redirect = 0; |
2694 * lcf->alias = 0; | 2883 * lcf->alias = 0; |
3604 return NGX_CONF_OK; | 3793 return NGX_CONF_OK; |
3605 } | 3794 } |
3606 | 3795 |
3607 | 3796 |
3608 static char * | 3797 static char * |
3798 ngx_http_core_try_files(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
3799 { | |
3800 ngx_http_core_loc_conf_t *clcf = conf; | |
3801 | |
3802 ngx_str_t *value; | |
3803 ngx_uint_t i, n; | |
3804 ngx_http_try_file_t *tf; | |
3805 ngx_http_script_compile_t sc; | |
3806 ngx_http_core_main_conf_t *cmcf; | |
3807 | |
3808 if (clcf->try_files) { | |
3809 return "is duplicate"; | |
3810 } | |
3811 | |
3812 cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); | |
3813 | |
3814 cmcf->try_files = 1; | |
3815 | |
3816 tf = ngx_pcalloc(cf->pool, cf->args->nelts * sizeof(ngx_http_try_file_t)); | |
3817 if (tf == NULL) { | |
3818 return NGX_CONF_ERROR; | |
3819 } | |
3820 | |
3821 clcf->try_files = tf; | |
3822 | |
3823 value = cf->args->elts; | |
3824 | |
3825 for (i = 0; i < cf->args->nelts - 1; i++) { | |
3826 | |
3827 tf[i].name = value[i + 1]; | |
3828 | |
3829 if (tf[i].name.data[tf[i].name.len - 1] == '/') { | |
3830 tf[i].test_dir = 1; | |
3831 tf[i].name.len--; | |
3832 tf[i].name.data[tf[i].name.len] = '\0'; | |
3833 } | |
3834 | |
3835 n = ngx_http_script_variables_count(&tf[i].name); | |
3836 | |
3837 if (n) { | |
3838 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); | |
3839 | |
3840 sc.cf = cf; | |
3841 sc.source = &tf[i].name; | |
3842 sc.lengths = &tf[i].lengths; | |
3843 sc.values = &tf[i].values; | |
3844 sc.variables = n; | |
3845 sc.complete_lengths = 1; | |
3846 sc.complete_values = 1; | |
3847 | |
3848 if (ngx_http_script_compile(&sc) != NGX_OK) { | |
3849 return NGX_CONF_ERROR; | |
3850 } | |
3851 | |
3852 } else { | |
3853 /* add trailing '\0' to length */ | |
3854 tf[i].name.len++; | |
3855 } | |
3856 } | |
3857 | |
3858 return NGX_CONF_OK; | |
3859 } | |
3860 | |
3861 | |
3862 static char * | |
3609 ngx_http_core_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | 3863 ngx_http_core_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
3610 { | 3864 { |
3611 ngx_http_core_loc_conf_t *lcf = conf; | 3865 ngx_http_core_loc_conf_t *lcf = conf; |
3612 | 3866 |
3613 time_t inactive; | 3867 time_t inactive; |