Mercurial > hg > nginx
comparison src/http/ngx_http_core_module.c @ 2407:16d1236bc298
try_files
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Mon, 15 Dec 2008 10:56:48 +0000 |
parents | dca164c4a868 |
children | 4876c3966fbd |
comparison
equal
deleted
inserted
replaced
2406:008777fa59e0 | 2407:16d1236bc298 |
---|---|
55 static char *ngx_http_core_limit_except(ngx_conf_t *cf, ngx_command_t *cmd, | 55 static char *ngx_http_core_limit_except(ngx_conf_t *cf, ngx_command_t *cmd, |
56 void *conf); | 56 void *conf); |
57 static char *ngx_http_core_directio(ngx_conf_t *cf, ngx_command_t *cmd, | 57 static char *ngx_http_core_directio(ngx_conf_t *cf, ngx_command_t *cmd, |
58 void *conf); | 58 void *conf); |
59 static char *ngx_http_core_error_page(ngx_conf_t *cf, ngx_command_t *cmd, | 59 static char *ngx_http_core_error_page(ngx_conf_t *cf, ngx_command_t *cmd, |
60 void *conf); | |
61 static char *ngx_http_core_try_files(ngx_conf_t *cf, ngx_command_t *cmd, | |
60 void *conf); | 62 void *conf); |
61 static char *ngx_http_core_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd, | 63 static char *ngx_http_core_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd, |
62 void *conf); | 64 void *conf); |
63 static char *ngx_http_core_error_log(ngx_conf_t *cf, ngx_command_t *cmd, | 65 static char *ngx_http_core_error_log(ngx_conf_t *cf, ngx_command_t *cmd, |
64 void *conf); | 66 void *conf); |
537 ngx_http_core_error_page, | 539 ngx_http_core_error_page, |
538 NGX_HTTP_LOC_CONF_OFFSET, | 540 NGX_HTTP_LOC_CONF_OFFSET, |
539 0, | 541 0, |
540 NULL }, | 542 NULL }, |
541 | 543 |
544 { ngx_string("try_files"), | |
545 NGX_HTTP_LOC_CONF|NGX_CONF_2MORE, | |
546 ngx_http_core_try_files, | |
547 NGX_HTTP_LOC_CONF_OFFSET, | |
548 0, | |
549 NULL }, | |
550 | |
542 { ngx_string("post_action"), | 551 { ngx_string("post_action"), |
543 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF | 552 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF |
544 |NGX_CONF_TAKE1, | 553 |NGX_CONF_TAKE1, |
545 ngx_conf_set_str_slot, | 554 ngx_conf_set_str_slot, |
546 NGX_HTTP_LOC_CONF_OFFSET, | 555 NGX_HTTP_LOC_CONF_OFFSET, |
1030 return NGX_AGAIN; | 1039 return NGX_AGAIN; |
1031 } | 1040 } |
1032 | 1041 |
1033 | 1042 |
1034 ngx_int_t | 1043 ngx_int_t |
1044 ngx_http_core_try_files_phase(ngx_http_request_t *r, | |
1045 ngx_http_phase_handler_t *ph) | |
1046 { | |
1047 size_t len, root, alias; | |
1048 ssize_t reserve, allocated; | |
1049 u_char *p, *name; | |
1050 ngx_str_t path; | |
1051 ngx_http_try_file_t *tf; | |
1052 ngx_open_file_info_t of; | |
1053 ngx_http_script_code_pt code; | |
1054 ngx_http_script_engine_t e; | |
1055 ngx_http_core_loc_conf_t *clcf; | |
1056 ngx_http_script_len_code_pt lcode; | |
1057 | |
1058 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
1059 "try files phase: %ui", r->phase_handler); | |
1060 | |
1061 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | |
1062 | |
1063 if (clcf->try_files == NULL) { | |
1064 r->phase_handler++; | |
1065 return NGX_AGAIN; | |
1066 } | |
1067 | |
1068 allocated = 0; | |
1069 root = 0; | |
1070 name = NULL; | |
1071 path.len = 0; | |
1072 path.data = NULL; | |
1073 | |
1074 tf = clcf->try_files; | |
1075 | |
1076 alias = clcf->alias ? clcf->name.len : 0; | |
1077 | |
1078 for ( ;; ) { | |
1079 | |
1080 if (tf->lengths) { | |
1081 ngx_memzero(&e, sizeof(ngx_http_script_engine_t)); | |
1082 | |
1083 e.ip = tf->lengths->elts; | |
1084 e.request = r; | |
1085 e.flushed = 1; | |
1086 | |
1087 /* 1 is for terminating '\0' as in static names */ | |
1088 len = 1; | |
1089 | |
1090 while (*(uintptr_t *) e.ip) { | |
1091 lcode = *(ngx_http_script_len_code_pt *) e.ip; | |
1092 len += lcode(&e); | |
1093 } | |
1094 | |
1095 } else { | |
1096 len = tf->name.len; | |
1097 } | |
1098 | |
1099 reserve = len - r->uri.len; | |
1100 | |
1101 /* 16 bytes are preallocation */ | |
1102 reserve = reserve < 16 ? 16 : reserve + 16; | |
1103 | |
1104 reserve += alias; | |
1105 | |
1106 if (reserve > allocated) { | |
1107 | |
1108 /* we just need to allocate path and to copy a root */ | |
1109 | |
1110 if (ngx_http_map_uri_to_path(r, &path, &root, reserve) == NULL) { | |
1111 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
1112 return NGX_OK; | |
1113 } | |
1114 | |
1115 name = path.data + root; | |
1116 allocated = path.len - root - (r->uri.len - alias); | |
1117 } | |
1118 | |
1119 if (tf->values == NULL) { | |
1120 | |
1121 /* tf->name.len includes the terminating '\0' */ | |
1122 | |
1123 ngx_memcpy(name, tf->name.data, tf->name.len); | |
1124 | |
1125 path.len = (name + tf->name.len - 1) - path.data; | |
1126 | |
1127 } else { | |
1128 e.ip = tf->values->elts; | |
1129 e.pos = name; | |
1130 | |
1131 while (*(uintptr_t *) e.ip) { | |
1132 code = *(ngx_http_script_code_pt *) e.ip; | |
1133 code((ngx_http_script_engine_t *) &e); | |
1134 } | |
1135 | |
1136 path.len = e.pos - path.data; | |
1137 | |
1138 *e.pos++ = '\0'; | |
1139 | |
1140 if (alias && ngx_strncmp(name, clcf->name.data, alias) == 0) { | |
1141 ngx_memcpy(name, name + alias, len - alias); | |
1142 path.len -= alias; | |
1143 } | |
1144 } | |
1145 | |
1146 tf++; | |
1147 | |
1148 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
1149 "try to use file: \"%s\"", name); | |
1150 | |
1151 if (tf->lengths == NULL && tf->name.len == 0) { | |
1152 | |
1153 path.len -= root; | |
1154 path.data += root; | |
1155 | |
1156 if (path.data[0] == '@') { | |
1157 (void) ngx_http_named_location(r, &path); | |
1158 | |
1159 } else { | |
1160 (void) ngx_http_internal_redirect(r, &path, NULL); | |
1161 } | |
1162 | |
1163 return NGX_OK; | |
1164 } | |
1165 | |
1166 ngx_memzero(&of, sizeof(ngx_open_file_info_t)); | |
1167 | |
1168 of.directio = clcf->directio; | |
1169 of.valid = clcf->open_file_cache_valid; | |
1170 of.min_uses = clcf->open_file_cache_min_uses; | |
1171 of.errors = clcf->open_file_cache_errors; | |
1172 of.events = clcf->open_file_cache_events; | |
1173 | |
1174 if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool) | |
1175 != NGX_OK) | |
1176 { | |
1177 if (of.err != NGX_ENOENT && of.err != NGX_ENOTDIR) { | |
1178 ngx_log_error(NGX_LOG_CRIT, r->connection->log, of.err, | |
1179 ngx_open_file_n " \"%s\" failed", path.data); | |
1180 } | |
1181 | |
1182 continue; | |
1183 } | |
1184 | |
1185 path.len -= root; | |
1186 path.data += root; | |
1187 | |
1188 if (!alias) { | |
1189 r->uri = path; | |
1190 | |
1191 } else { | |
1192 r->uri.len = alias + path.len; | |
1193 r->uri.data = ngx_pnalloc(r->pool, r->uri.len); | |
1194 if (r->uri.data == NULL) { | |
1195 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
1196 return NGX_OK; | |
1197 } | |
1198 | |
1199 p = ngx_copy(r->uri.data, clcf->name.data, alias); | |
1200 ngx_memcpy(p, name, path.len); | |
1201 } | |
1202 | |
1203 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
1204 "try file uri: \"%V\"", &r->uri); | |
1205 | |
1206 r->phase_handler++; | |
1207 return NGX_AGAIN; | |
1208 } | |
1209 | |
1210 /* not reached */ | |
1211 } | |
1212 | |
1213 | |
1214 ngx_int_t | |
1035 ngx_http_core_content_phase(ngx_http_request_t *r, | 1215 ngx_http_core_content_phase(ngx_http_request_t *r, |
1036 ngx_http_phase_handler_t *ph) | 1216 ngx_http_phase_handler_t *ph) |
1037 { | 1217 { |
1038 size_t root; | 1218 size_t root; |
1039 ngx_int_t rc; | 1219 ngx_int_t rc; |
2708 * lcf->post_action = { 0, NULL }; | 2888 * lcf->post_action = { 0, NULL }; |
2709 * lcf->types = NULL; | 2889 * lcf->types = NULL; |
2710 * lcf->default_type = { 0, NULL }; | 2890 * lcf->default_type = { 0, NULL }; |
2711 * lcf->err_log = NULL; | 2891 * lcf->err_log = NULL; |
2712 * lcf->error_pages = NULL; | 2892 * lcf->error_pages = NULL; |
2893 * lcf->try_files = NULL; | |
2713 * lcf->client_body_path = NULL; | 2894 * lcf->client_body_path = NULL; |
2714 * lcf->regex = NULL; | 2895 * lcf->regex = NULL; |
2715 * lcf->exact_match = 0; | 2896 * lcf->exact_match = 0; |
2716 * lcf->auto_redirect = 0; | 2897 * lcf->auto_redirect = 0; |
2717 * lcf->alias = 0; | 2898 * lcf->alias = 0; |
3683 return NGX_CONF_OK; | 3864 return NGX_CONF_OK; |
3684 } | 3865 } |
3685 | 3866 |
3686 | 3867 |
3687 static char * | 3868 static char * |
3869 ngx_http_core_try_files(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
3870 { | |
3871 ngx_http_core_loc_conf_t *clcf = conf; | |
3872 | |
3873 ngx_str_t *value; | |
3874 ngx_uint_t i, n; | |
3875 ngx_http_try_file_t *tf; | |
3876 ngx_http_script_compile_t sc; | |
3877 ngx_http_core_main_conf_t *cmcf; | |
3878 | |
3879 if (clcf->try_files) { | |
3880 return "is duplicate"; | |
3881 } | |
3882 | |
3883 cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); | |
3884 | |
3885 cmcf->try_files = 1; | |
3886 | |
3887 tf = ngx_pcalloc(cf->pool, cf->args->nelts * sizeof(ngx_http_try_file_t)); | |
3888 if (tf == NULL) { | |
3889 return NGX_CONF_ERROR; | |
3890 } | |
3891 | |
3892 clcf->try_files = tf; | |
3893 | |
3894 value = cf->args->elts; | |
3895 | |
3896 for (i = 0; i < cf->args->nelts - 1; i++) { | |
3897 | |
3898 tf[i].name = value[i + 1]; | |
3899 | |
3900 n = ngx_http_script_variables_count(&tf[i].name); | |
3901 | |
3902 if (n) { | |
3903 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); | |
3904 | |
3905 sc.cf = cf; | |
3906 sc.source = &tf[i].name; | |
3907 sc.lengths = &tf[i].lengths; | |
3908 sc.values = &tf[i].values; | |
3909 sc.variables = n; | |
3910 sc.complete_lengths = 1; | |
3911 sc.complete_values = 1; | |
3912 | |
3913 if (ngx_http_script_compile(&sc) != NGX_OK) { | |
3914 return NGX_CONF_ERROR; | |
3915 } | |
3916 | |
3917 } else { | |
3918 /* add trailing '\0' to length */ | |
3919 tf[i].name.len++; | |
3920 } | |
3921 } | |
3922 | |
3923 return NGX_CONF_OK; | |
3924 } | |
3925 | |
3926 | |
3927 static char * | |
3688 ngx_http_core_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | 3928 ngx_http_core_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
3689 { | 3929 { |
3690 ngx_http_core_loc_conf_t *lcf = conf; | 3930 ngx_http_core_loc_conf_t *lcf = conf; |
3691 | 3931 |
3692 time_t inactive; | 3932 time_t inactive; |