11183Svbart@nginx.com 21183Svbart@nginx.com /* 31183Svbart@nginx.com * Copyright (C) NGINX, Inc. 41183Svbart@nginx.com */ 51183Svbart@nginx.com 61183Svbart@nginx.com #include <nxt_router.h> 71183Svbart@nginx.com #include <nxt_http.h> 81183Svbart@nginx.com 91183Svbart@nginx.com 101923Sz.hong@f5.com typedef struct { 11*1959Sz.hong@f5.com nxt_str_t share; 12*1959Sz.hong@f5.com #if (NXT_HAVE_OPENAT2) 13*1959Sz.hong@f5.com nxt_var_t *chroot; 14*1959Sz.hong@f5.com nxt_uint_t resolve; 15*1959Sz.hong@f5.com #endif 16*1959Sz.hong@f5.com nxt_http_route_rule_t *types; 17*1959Sz.hong@f5.com uint8_t is_const; /* 1 bit */ 181923Sz.hong@f5.com } nxt_http_static_conf_t; 191923Sz.hong@f5.com 201923Sz.hong@f5.com 21*1959Sz.hong@f5.com typedef struct { 22*1959Sz.hong@f5.com nxt_http_action_t *action; 23*1959Sz.hong@f5.com #if (NXT_HAVE_OPENAT2) 24*1959Sz.hong@f5.com nxt_str_t chroot; 25*1959Sz.hong@f5.com #endif 26*1959Sz.hong@f5.com uint8_t need_body; /* 1 bit */ 27*1959Sz.hong@f5.com } nxt_http_static_ctx_t; 28*1959Sz.hong@f5.com 29*1959Sz.hong@f5.com 301183Svbart@nginx.com #define NXT_HTTP_STATIC_BUF_COUNT 2 311183Svbart@nginx.com #define NXT_HTTP_STATIC_BUF_SIZE (128 * 1024) 321183Svbart@nginx.com 331183Svbart@nginx.com 341923Sz.hong@f5.com static nxt_http_action_t *nxt_http_static(nxt_task_t *task, 351923Sz.hong@f5.com nxt_http_request_t *r, nxt_http_action_t *action); 36*1959Sz.hong@f5.com static void nxt_http_static_send_ready(nxt_task_t *task, void *obj, void *data); 37*1959Sz.hong@f5.com static void nxt_http_static_var_error(nxt_task_t *task, void *obj, void *data); 38*1959Sz.hong@f5.com #if (NXT_HAVE_OPENAT2) 39*1959Sz.hong@f5.com static u_char *nxt_http_static_chroot_match(u_char *chr, u_char *shr); 40*1959Sz.hong@f5.com #endif 411183Svbart@nginx.com static void nxt_http_static_extract_extension(nxt_str_t *path, 421923Sz.hong@f5.com nxt_str_t *exten); 431183Svbart@nginx.com static void nxt_http_static_body_handler(nxt_task_t *task, void *obj, 441183Svbart@nginx.com void *data); 451183Svbart@nginx.com static void nxt_http_static_buf_completion(nxt_task_t *task, void *obj, 461183Svbart@nginx.com void *data); 471183Svbart@nginx.com 481183Svbart@nginx.com static nxt_int_t nxt_http_static_mtypes_hash_test(nxt_lvlhsh_query_t *lhq, 491183Svbart@nginx.com void *data); 501183Svbart@nginx.com static void *nxt_http_static_mtypes_hash_alloc(void *data, size_t size); 511183Svbart@nginx.com static void nxt_http_static_mtypes_hash_free(void *data, void *p); 521183Svbart@nginx.com 531183Svbart@nginx.com 541183Svbart@nginx.com static const nxt_http_request_state_t nxt_http_static_send_state; 551183Svbart@nginx.com 561183Svbart@nginx.com 571923Sz.hong@f5.com nxt_int_t 581923Sz.hong@f5.com nxt_http_static_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 591923Sz.hong@f5.com nxt_http_action_t *action, nxt_http_action_conf_t *acf) 601923Sz.hong@f5.com { 611923Sz.hong@f5.com nxt_mp_t *mp; 621923Sz.hong@f5.com nxt_str_t *str, value; 631923Sz.hong@f5.com nxt_http_static_conf_t *conf; 641923Sz.hong@f5.com 651923Sz.hong@f5.com mp = tmcf->router_conf->mem_pool; 661923Sz.hong@f5.com 671923Sz.hong@f5.com conf = nxt_mp_zget(mp, sizeof(nxt_http_static_conf_t)); 681923Sz.hong@f5.com if (nxt_slow_path(conf == NULL)) { 691923Sz.hong@f5.com return NXT_ERROR; 701923Sz.hong@f5.com } 711923Sz.hong@f5.com 721923Sz.hong@f5.com action->handler = nxt_http_static; 731923Sz.hong@f5.com action->u.conf = conf; 741923Sz.hong@f5.com 751923Sz.hong@f5.com nxt_conf_get_string(acf->share, &value); 761923Sz.hong@f5.com 771923Sz.hong@f5.com str = nxt_str_dup(mp, &conf->share, &value); 781923Sz.hong@f5.com if (nxt_slow_path(str == NULL)) { 791923Sz.hong@f5.com return NXT_ERROR; 801923Sz.hong@f5.com } 811923Sz.hong@f5.com 82*1959Sz.hong@f5.com conf->is_const = 1; 83*1959Sz.hong@f5.com 841923Sz.hong@f5.com #if (NXT_HAVE_OPENAT2) 851923Sz.hong@f5.com if (acf->chroot.length > 0) { 86*1959Sz.hong@f5.com if (nxt_is_var(&acf->chroot)) { 87*1959Sz.hong@f5.com conf->is_const = 0; 881923Sz.hong@f5.com } 891923Sz.hong@f5.com 90*1959Sz.hong@f5.com conf->chroot = nxt_var_compile(&acf->chroot, mp, 1); 91*1959Sz.hong@f5.com if (nxt_slow_path(conf->chroot == NULL)) { 921923Sz.hong@f5.com return NXT_ERROR; 931923Sz.hong@f5.com } 941923Sz.hong@f5.com } 951923Sz.hong@f5.com 961923Sz.hong@f5.com if (acf->follow_symlinks != NULL 971923Sz.hong@f5.com && !nxt_conf_get_boolean(acf->follow_symlinks)) 981923Sz.hong@f5.com { 991923Sz.hong@f5.com conf->resolve |= RESOLVE_NO_SYMLINKS; 1001923Sz.hong@f5.com } 1011923Sz.hong@f5.com 1021923Sz.hong@f5.com if (acf->traverse_mounts != NULL 1031923Sz.hong@f5.com && !nxt_conf_get_boolean(acf->traverse_mounts)) 1041923Sz.hong@f5.com { 1051923Sz.hong@f5.com conf->resolve |= RESOLVE_NO_XDEV; 1061923Sz.hong@f5.com } 1071923Sz.hong@f5.com #endif 1081923Sz.hong@f5.com 1091923Sz.hong@f5.com if (acf->types != NULL) { 1101923Sz.hong@f5.com conf->types = nxt_http_route_types_rule_create(task, mp, acf->types); 1111923Sz.hong@f5.com if (nxt_slow_path(conf->types == NULL)) { 1121923Sz.hong@f5.com return NXT_ERROR; 1131923Sz.hong@f5.com } 1141923Sz.hong@f5.com } 1151923Sz.hong@f5.com 1161923Sz.hong@f5.com if (acf->fallback != NULL) { 1171923Sz.hong@f5.com action->fallback = nxt_mp_alloc(mp, sizeof(nxt_http_action_t)); 1181923Sz.hong@f5.com if (nxt_slow_path(action->fallback == NULL)) { 1191923Sz.hong@f5.com return NXT_ERROR; 1201923Sz.hong@f5.com } 1211923Sz.hong@f5.com 1221923Sz.hong@f5.com return nxt_http_action_init(task, tmcf, acf->fallback, 1231923Sz.hong@f5.com action->fallback); 1241923Sz.hong@f5.com } 1251923Sz.hong@f5.com 1261923Sz.hong@f5.com return NXT_OK; 1271923Sz.hong@f5.com } 1281923Sz.hong@f5.com 1291923Sz.hong@f5.com 1301923Sz.hong@f5.com static nxt_http_action_t * 1311923Sz.hong@f5.com nxt_http_static(nxt_task_t *task, nxt_http_request_t *r, 1321264Sigor@sysoev.ru nxt_http_action_t *action) 1331183Svbart@nginx.com { 1341923Sz.hong@f5.com nxt_int_t ret; 1351923Sz.hong@f5.com nxt_bool_t need_body; 136*1959Sz.hong@f5.com nxt_http_static_ctx_t *ctx; 1371923Sz.hong@f5.com nxt_http_static_conf_t *conf; 1381923Sz.hong@f5.com 1391183Svbart@nginx.com if (nxt_slow_path(!nxt_str_eq(r->method, "GET", 3))) { 1401183Svbart@nginx.com 1411183Svbart@nginx.com if (!nxt_str_eq(r->method, "HEAD", 4)) { 1421923Sz.hong@f5.com if (action->fallback != NULL) { 1431923Sz.hong@f5.com return action->fallback; 1441378Svbart@nginx.com } 1451378Svbart@nginx.com 1461183Svbart@nginx.com nxt_http_request_error(task, r, NXT_HTTP_METHOD_NOT_ALLOWED); 1471183Svbart@nginx.com return NULL; 1481183Svbart@nginx.com } 1491183Svbart@nginx.com 1501183Svbart@nginx.com need_body = 0; 1511183Svbart@nginx.com 1521183Svbart@nginx.com } else { 1531183Svbart@nginx.com need_body = 1; 1541183Svbart@nginx.com } 1551183Svbart@nginx.com 156*1959Sz.hong@f5.com conf = action->u.conf; 157*1959Sz.hong@f5.com 158*1959Sz.hong@f5.com #if (NXT_DEBUG && NXT_HAVE_OPENAT2) 159*1959Sz.hong@f5.com nxt_str_t chr; 160*1959Sz.hong@f5.com 161*1959Sz.hong@f5.com if (conf->chroot != NULL) { 162*1959Sz.hong@f5.com nxt_var_raw(conf->chroot, &chr); 163*1959Sz.hong@f5.com 164*1959Sz.hong@f5.com } else { 165*1959Sz.hong@f5.com nxt_str_set(&chr, ""); 166*1959Sz.hong@f5.com } 167*1959Sz.hong@f5.com 168*1959Sz.hong@f5.com nxt_debug(task, "http static: \"%V\" (chroot: \"%V\")", &conf->share, &chr); 169*1959Sz.hong@f5.com 170*1959Sz.hong@f5.com #else 171*1959Sz.hong@f5.com nxt_debug(task, "http static: \"%V\"", &conf->share); 172*1959Sz.hong@f5.com #endif 173*1959Sz.hong@f5.com 174*1959Sz.hong@f5.com ctx = nxt_mp_zget(r->mem_pool, sizeof(nxt_http_static_ctx_t)); 175*1959Sz.hong@f5.com if (nxt_slow_path(ctx == NULL)) { 176*1959Sz.hong@f5.com goto fail; 177*1959Sz.hong@f5.com } 178*1959Sz.hong@f5.com 179*1959Sz.hong@f5.com ctx->action = action; 180*1959Sz.hong@f5.com ctx->need_body = need_body; 181*1959Sz.hong@f5.com 182*1959Sz.hong@f5.com if (conf->is_const) { 183*1959Sz.hong@f5.com #if (NXT_HAVE_OPENAT2) 184*1959Sz.hong@f5.com if (conf->chroot != NULL) { 185*1959Sz.hong@f5.com nxt_var_raw(conf->chroot, &ctx->chroot); 186*1959Sz.hong@f5.com } 187*1959Sz.hong@f5.com #endif 188*1959Sz.hong@f5.com 189*1959Sz.hong@f5.com nxt_http_static_send_ready(task, r, ctx); 190*1959Sz.hong@f5.com 191*1959Sz.hong@f5.com } else { 192*1959Sz.hong@f5.com ret = nxt_var_query_init(&r->var_query, r, r->mem_pool); 193*1959Sz.hong@f5.com if (nxt_slow_path(ret != NXT_OK)) { 194*1959Sz.hong@f5.com goto fail; 195*1959Sz.hong@f5.com } 196*1959Sz.hong@f5.com 197*1959Sz.hong@f5.com #if (NXT_HAVE_OPENAT2) 198*1959Sz.hong@f5.com nxt_var_query(task, r->var_query, conf->chroot, &ctx->chroot); 199*1959Sz.hong@f5.com #endif 200*1959Sz.hong@f5.com 201*1959Sz.hong@f5.com nxt_var_query_resolve(task, r->var_query, ctx, 202*1959Sz.hong@f5.com nxt_http_static_send_ready, 203*1959Sz.hong@f5.com nxt_http_static_var_error); 204*1959Sz.hong@f5.com } 205*1959Sz.hong@f5.com 206*1959Sz.hong@f5.com return NULL; 207*1959Sz.hong@f5.com 208*1959Sz.hong@f5.com fail: 209*1959Sz.hong@f5.com 210*1959Sz.hong@f5.com nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); 211*1959Sz.hong@f5.com return NULL; 212*1959Sz.hong@f5.com } 213*1959Sz.hong@f5.com 214*1959Sz.hong@f5.com 215*1959Sz.hong@f5.com static void 216*1959Sz.hong@f5.com nxt_http_static_send_ready(nxt_task_t *task, void *obj, void *data) 217*1959Sz.hong@f5.com { 218*1959Sz.hong@f5.com size_t length, encode; 219*1959Sz.hong@f5.com u_char *p, *fname; 220*1959Sz.hong@f5.com struct tm tm; 221*1959Sz.hong@f5.com nxt_buf_t *fb; 222*1959Sz.hong@f5.com nxt_int_t ret; 223*1959Sz.hong@f5.com nxt_str_t index, exten, *mtype; 224*1959Sz.hong@f5.com nxt_uint_t level; 225*1959Sz.hong@f5.com nxt_file_t *f, file; 226*1959Sz.hong@f5.com nxt_file_info_t fi; 227*1959Sz.hong@f5.com nxt_http_field_t *field; 228*1959Sz.hong@f5.com nxt_http_status_t status; 229*1959Sz.hong@f5.com nxt_router_conf_t *rtcf; 230*1959Sz.hong@f5.com nxt_http_action_t *action; 231*1959Sz.hong@f5.com nxt_http_request_t *r; 232*1959Sz.hong@f5.com nxt_work_handler_t body_handler; 233*1959Sz.hong@f5.com nxt_http_static_ctx_t *ctx; 234*1959Sz.hong@f5.com nxt_http_static_conf_t *conf; 235*1959Sz.hong@f5.com 236*1959Sz.hong@f5.com r = obj; 237*1959Sz.hong@f5.com ctx = data; 238*1959Sz.hong@f5.com action = ctx->action; 239*1959Sz.hong@f5.com conf = action->u.conf; 240*1959Sz.hong@f5.com 2411183Svbart@nginx.com if (r->path->start[r->path->length - 1] == '/') { 2421183Svbart@nginx.com /* TODO: dynamic index setting. */ 2431183Svbart@nginx.com nxt_str_set(&index, "index.html"); 2441923Sz.hong@f5.com nxt_str_set(&exten, ".html"); 2451183Svbart@nginx.com 2461183Svbart@nginx.com } else { 2471483Svbart@nginx.com nxt_str_set(&index, ""); 2481923Sz.hong@f5.com nxt_str_null(&exten); 2491183Svbart@nginx.com } 2501183Svbart@nginx.com 2511855Sz.hong@f5.com f = NULL; 252*1959Sz.hong@f5.com status = NXT_HTTP_INTERNAL_SERVER_ERROR; 2531183Svbart@nginx.com 2541859So.canty@f5.com rtcf = r->conf->socket_conf->router_conf; 2551859So.canty@f5.com 2561859So.canty@f5.com mtype = NULL; 2571859So.canty@f5.com 2581923Sz.hong@f5.com if (conf->types != NULL && exten.start == NULL) { 2591923Sz.hong@f5.com nxt_http_static_extract_extension(r->path, &exten); 2601923Sz.hong@f5.com mtype = nxt_http_static_mtype_get(&rtcf->mtypes_hash, &exten); 2611859So.canty@f5.com 2621923Sz.hong@f5.com ret = nxt_http_route_test_rule(r, conf->types, mtype->start, 2631923Sz.hong@f5.com mtype->length); 2641883So.canty@f5.com if (nxt_slow_path(ret == NXT_ERROR)) { 2651883So.canty@f5.com goto fail; 2661883So.canty@f5.com } 2671883So.canty@f5.com 2681883So.canty@f5.com if (ret == 0) { 269*1959Sz.hong@f5.com status = NXT_HTTP_FORBIDDEN; 270*1959Sz.hong@f5.com goto fail; 2711859So.canty@f5.com } 2721859So.canty@f5.com } 2731859So.canty@f5.com 2741923Sz.hong@f5.com length = conf->share.length + r->path->length + index.length; 2751855Sz.hong@f5.com 2761855Sz.hong@f5.com fname = nxt_mp_nget(r->mem_pool, length + 1); 2771855Sz.hong@f5.com if (nxt_slow_path(fname == NULL)) { 2781183Svbart@nginx.com goto fail; 2791183Svbart@nginx.com } 2801183Svbart@nginx.com 2811855Sz.hong@f5.com p = fname; 2821923Sz.hong@f5.com p = nxt_cpymem(p, conf->share.start, conf->share.length); 2831183Svbart@nginx.com p = nxt_cpymem(p, r->path->start, r->path->length); 2841183Svbart@nginx.com p = nxt_cpymem(p, index.start, index.length); 2851183Svbart@nginx.com *p = '\0'; 2861183Svbart@nginx.com 2871855Sz.hong@f5.com nxt_memzero(&file, sizeof(nxt_file_t)); 2881855Sz.hong@f5.com 2891855Sz.hong@f5.com file.name = fname; 2901855Sz.hong@f5.com 291*1959Sz.hong@f5.com #if (NXT_HAVE_OPENAT2) 292*1959Sz.hong@f5.com if (conf->resolve != 0 || ctx->chroot.length > 0) { 293*1959Sz.hong@f5.com nxt_str_t *chr; 294*1959Sz.hong@f5.com nxt_uint_t resolve; 2951855Sz.hong@f5.com 296*1959Sz.hong@f5.com resolve = conf->resolve; 297*1959Sz.hong@f5.com chr = &ctx->chroot; 2981855Sz.hong@f5.com 299*1959Sz.hong@f5.com if (chr->length > 0) { 300*1959Sz.hong@f5.com resolve |= RESOLVE_IN_ROOT; 3011855Sz.hong@f5.com 302*1959Sz.hong@f5.com fname = nxt_http_static_chroot_match(chr->start, file.name); 303*1959Sz.hong@f5.com 304*1959Sz.hong@f5.com if (fname != NULL) { 305*1959Sz.hong@f5.com file.name = chr->start; 3061855Sz.hong@f5.com ret = nxt_file_open(task, &file, NXT_FILE_SEARCH, NXT_FILE_OPEN, 3071855Sz.hong@f5.com 0); 3081855Sz.hong@f5.com 3091855Sz.hong@f5.com } else { 3101855Sz.hong@f5.com file.error = NXT_EACCES; 3111855Sz.hong@f5.com ret = NXT_ERROR; 3121855Sz.hong@f5.com } 3131855Sz.hong@f5.com 3141855Sz.hong@f5.com } else if (fname[0] == '/') { 3151855Sz.hong@f5.com file.name = (u_char *) "/"; 3161855Sz.hong@f5.com ret = nxt_file_open(task, &file, NXT_FILE_SEARCH, NXT_FILE_OPEN, 0); 3171855Sz.hong@f5.com 3181855Sz.hong@f5.com } else { 3191855Sz.hong@f5.com file.name = (u_char *) "."; 3201855Sz.hong@f5.com file.fd = AT_FDCWD; 3211855Sz.hong@f5.com ret = NXT_OK; 3221855Sz.hong@f5.com } 3231855Sz.hong@f5.com 3241855Sz.hong@f5.com if (nxt_fast_path(ret == NXT_OK)) { 3251856Sz.hong@f5.com nxt_file_t af; 3261856Sz.hong@f5.com 3271855Sz.hong@f5.com af = file; 3281855Sz.hong@f5.com nxt_memzero(&file, sizeof(nxt_file_t)); 3291855Sz.hong@f5.com file.name = fname; 3301855Sz.hong@f5.com 3311855Sz.hong@f5.com ret = nxt_file_openat2(task, &file, NXT_FILE_RDONLY, 332*1959Sz.hong@f5.com NXT_FILE_OPEN, 0, af.fd, resolve); 3331855Sz.hong@f5.com 3341855Sz.hong@f5.com if (af.fd != AT_FDCWD) { 3351855Sz.hong@f5.com nxt_file_close(task, &af); 3361855Sz.hong@f5.com } 3371855Sz.hong@f5.com } 3381855Sz.hong@f5.com 3391855Sz.hong@f5.com } else { 3401855Sz.hong@f5.com ret = nxt_file_open(task, &file, NXT_FILE_RDONLY, NXT_FILE_OPEN, 0); 3411855Sz.hong@f5.com } 3421855Sz.hong@f5.com 3431855Sz.hong@f5.com #else 3441855Sz.hong@f5.com ret = nxt_file_open(task, &file, NXT_FILE_RDONLY, NXT_FILE_OPEN, 0); 3451855Sz.hong@f5.com #endif 3461183Svbart@nginx.com 3471183Svbart@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 3481855Sz.hong@f5.com 3491855Sz.hong@f5.com switch (file.error) { 3501183Svbart@nginx.com 3511200Svbart@nginx.com /* 3521200Svbart@nginx.com * For Unix domain sockets "errno" is set to: 3531200Svbart@nginx.com * - ENXIO on Linux; 3541200Svbart@nginx.com * - EOPNOTSUPP on *BSD, MacOSX, and Solaris. 3551200Svbart@nginx.com */ 3561200Svbart@nginx.com 3571183Svbart@nginx.com case NXT_ENOENT: 3581183Svbart@nginx.com case NXT_ENOTDIR: 3591183Svbart@nginx.com case NXT_ENAMETOOLONG: 3601200Svbart@nginx.com #if (NXT_LINUX) 3611200Svbart@nginx.com case NXT_ENXIO: 3621200Svbart@nginx.com #else 3631200Svbart@nginx.com case NXT_EOPNOTSUPP: 3641200Svbart@nginx.com #endif 3651183Svbart@nginx.com level = NXT_LOG_ERR; 3661183Svbart@nginx.com status = NXT_HTTP_NOT_FOUND; 3671183Svbart@nginx.com break; 3681183Svbart@nginx.com 3691183Svbart@nginx.com case NXT_EACCES: 3701855Sz.hong@f5.com #if (NXT_HAVE_OPENAT2) 3711855Sz.hong@f5.com case NXT_ELOOP: 3721855Sz.hong@f5.com case NXT_EXDEV: 3731855Sz.hong@f5.com #endif 3741183Svbart@nginx.com level = NXT_LOG_ERR; 3751183Svbart@nginx.com status = NXT_HTTP_FORBIDDEN; 3761183Svbart@nginx.com break; 3771183Svbart@nginx.com 3781183Svbart@nginx.com default: 3791183Svbart@nginx.com level = NXT_LOG_ALERT; 3801183Svbart@nginx.com status = NXT_HTTP_INTERNAL_SERVER_ERROR; 3811183Svbart@nginx.com break; 3821183Svbart@nginx.com } 3831183Svbart@nginx.com 3841923Sz.hong@f5.com if (level == NXT_LOG_ERR && action->fallback != NULL) { 385*1959Sz.hong@f5.com goto fail; 3861378Svbart@nginx.com } 3871378Svbart@nginx.com 3881183Svbart@nginx.com if (status != NXT_HTTP_NOT_FOUND) { 389*1959Sz.hong@f5.com #if (NXT_HAVE_OPENAT2) 390*1959Sz.hong@f5.com nxt_str_t *chr = &ctx->chroot; 391*1959Sz.hong@f5.com 392*1959Sz.hong@f5.com if (chr->length > 0) { 3931857Sz.hong@f5.com nxt_log(task, level, "opening \"%s\" at \"%V\" failed %E", 394*1959Sz.hong@f5.com fname, chr, file.error); 3951855Sz.hong@f5.com 3961855Sz.hong@f5.com } else { 3971857Sz.hong@f5.com nxt_log(task, level, "opening \"%s\" failed %E", 3981855Sz.hong@f5.com fname, file.error); 3991855Sz.hong@f5.com } 400*1959Sz.hong@f5.com 401*1959Sz.hong@f5.com #else 402*1959Sz.hong@f5.com nxt_log(task, level, "opening \"%s\" failed %E", fname, file.error); 403*1959Sz.hong@f5.com #endif 4041183Svbart@nginx.com } 4051183Svbart@nginx.com 406*1959Sz.hong@f5.com goto fail; 4071183Svbart@nginx.com } 4081183Svbart@nginx.com 4091855Sz.hong@f5.com f = nxt_mp_get(r->mem_pool, sizeof(nxt_file_t)); 4101855Sz.hong@f5.com if (nxt_slow_path(f == NULL)) { 4111855Sz.hong@f5.com goto fail; 4121855Sz.hong@f5.com } 4131855Sz.hong@f5.com 4141855Sz.hong@f5.com *f = file; 4151855Sz.hong@f5.com 4161183Svbart@nginx.com ret = nxt_file_info(f, &fi); 4171183Svbart@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 4181183Svbart@nginx.com goto fail; 4191183Svbart@nginx.com } 4201183Svbart@nginx.com 4211183Svbart@nginx.com if (nxt_fast_path(nxt_is_file(&fi))) { 4221183Svbart@nginx.com r->status = NXT_HTTP_OK; 4231183Svbart@nginx.com r->resp.content_length_n = nxt_file_size(&fi); 4241183Svbart@nginx.com 4251183Svbart@nginx.com field = nxt_list_zero_add(r->resp.fields); 4261183Svbart@nginx.com if (nxt_slow_path(field == NULL)) { 4271183Svbart@nginx.com goto fail; 4281183Svbart@nginx.com } 4291183Svbart@nginx.com 4301183Svbart@nginx.com nxt_http_field_name_set(field, "Last-Modified"); 4311183Svbart@nginx.com 4321183Svbart@nginx.com p = nxt_mp_nget(r->mem_pool, NXT_HTTP_DATE_LEN); 4331183Svbart@nginx.com if (nxt_slow_path(p == NULL)) { 4341183Svbart@nginx.com goto fail; 4351183Svbart@nginx.com } 4361183Svbart@nginx.com 4371183Svbart@nginx.com nxt_localtime(nxt_file_mtime(&fi), &tm); 4381183Svbart@nginx.com 4391183Svbart@nginx.com field->value = p; 4401183Svbart@nginx.com field->value_length = nxt_http_date(p, &tm) - p; 4411183Svbart@nginx.com 4421183Svbart@nginx.com field = nxt_list_zero_add(r->resp.fields); 4431183Svbart@nginx.com if (nxt_slow_path(field == NULL)) { 4441183Svbart@nginx.com goto fail; 4451183Svbart@nginx.com } 4461183Svbart@nginx.com 4471183Svbart@nginx.com nxt_http_field_name_set(field, "ETag"); 4481183Svbart@nginx.com 4491855Sz.hong@f5.com length = NXT_TIME_T_HEXLEN + NXT_OFF_T_HEXLEN + 3; 4501183Svbart@nginx.com 4511855Sz.hong@f5.com p = nxt_mp_nget(r->mem_pool, length); 4521183Svbart@nginx.com if (nxt_slow_path(p == NULL)) { 4531183Svbart@nginx.com goto fail; 4541183Svbart@nginx.com } 4551183Svbart@nginx.com 4561183Svbart@nginx.com field->value = p; 4571855Sz.hong@f5.com field->value_length = nxt_sprintf(p, p + length, "\"%xT-%xO\"", 4581183Svbart@nginx.com nxt_file_mtime(&fi), 4591183Svbart@nginx.com nxt_file_size(&fi)) 4601183Svbart@nginx.com - p; 4611183Svbart@nginx.com 4621923Sz.hong@f5.com if (exten.start == NULL) { 4631923Sz.hong@f5.com nxt_http_static_extract_extension(r->path, &exten); 4641183Svbart@nginx.com } 4651183Svbart@nginx.com 4661859So.canty@f5.com if (mtype == NULL) { 4671923Sz.hong@f5.com mtype = nxt_http_static_mtype_get(&rtcf->mtypes_hash, &exten); 4681859So.canty@f5.com } 4691183Svbart@nginx.com 4701883So.canty@f5.com if (mtype->length != 0) { 4711183Svbart@nginx.com field = nxt_list_zero_add(r->resp.fields); 4721183Svbart@nginx.com if (nxt_slow_path(field == NULL)) { 4731183Svbart@nginx.com goto fail; 4741183Svbart@nginx.com } 4751183Svbart@nginx.com 4761183Svbart@nginx.com nxt_http_field_name_set(field, "Content-Type"); 4771183Svbart@nginx.com 4781183Svbart@nginx.com field->value = mtype->start; 4791183Svbart@nginx.com field->value_length = mtype->length; 4801183Svbart@nginx.com } 4811183Svbart@nginx.com 482*1959Sz.hong@f5.com if (ctx->need_body && nxt_file_size(&fi) > 0) { 4831183Svbart@nginx.com fb = nxt_mp_zget(r->mem_pool, NXT_BUF_FILE_SIZE); 4841183Svbart@nginx.com if (nxt_slow_path(fb == NULL)) { 4851183Svbart@nginx.com goto fail; 4861183Svbart@nginx.com } 4871183Svbart@nginx.com 4881183Svbart@nginx.com fb->file = f; 4891183Svbart@nginx.com fb->file_end = nxt_file_size(&fi); 4901183Svbart@nginx.com 4911183Svbart@nginx.com r->out = fb; 4921183Svbart@nginx.com 4931183Svbart@nginx.com body_handler = &nxt_http_static_body_handler; 4941183Svbart@nginx.com 4951183Svbart@nginx.com } else { 4961183Svbart@nginx.com nxt_file_close(task, f); 4971183Svbart@nginx.com body_handler = NULL; 4981183Svbart@nginx.com } 4991183Svbart@nginx.com 5001183Svbart@nginx.com } else { 5011183Svbart@nginx.com /* Not a file. */ 5021183Svbart@nginx.com 5031183Svbart@nginx.com if (nxt_slow_path(!nxt_is_dir(&fi))) { 504*1959Sz.hong@f5.com if (action->fallback == NULL) { 505*1959Sz.hong@f5.com nxt_log(task, NXT_LOG_ERR, "\"%FN\" is not a regular file", 506*1959Sz.hong@f5.com f->name); 5071378Svbart@nginx.com } 5081378Svbart@nginx.com 509*1959Sz.hong@f5.com status = NXT_HTTP_NOT_FOUND; 510*1959Sz.hong@f5.com goto fail; 5111183Svbart@nginx.com } 5121183Svbart@nginx.com 513*1959Sz.hong@f5.com nxt_file_close(task, f); 5141198Svbart@nginx.com f = NULL; 5151198Svbart@nginx.com 5161183Svbart@nginx.com r->status = NXT_HTTP_MOVED_PERMANENTLY; 5171183Svbart@nginx.com r->resp.content_length_n = 0; 5181183Svbart@nginx.com 5191183Svbart@nginx.com field = nxt_list_zero_add(r->resp.fields); 5201183Svbart@nginx.com if (nxt_slow_path(field == NULL)) { 5211183Svbart@nginx.com goto fail; 5221183Svbart@nginx.com } 5231183Svbart@nginx.com 5241183Svbart@nginx.com nxt_http_field_name_set(field, "Location"); 5251183Svbart@nginx.com 5261183Svbart@nginx.com encode = nxt_encode_uri(NULL, r->path->start, r->path->length); 5271855Sz.hong@f5.com length = r->path->length + encode * 2 + 1; 5281183Svbart@nginx.com 5291183Svbart@nginx.com if (r->args->length > 0) { 5301855Sz.hong@f5.com length += 1 + r->args->length; 5311183Svbart@nginx.com } 5321183Svbart@nginx.com 5331855Sz.hong@f5.com p = nxt_mp_nget(r->mem_pool, length); 5341183Svbart@nginx.com if (nxt_slow_path(p == NULL)) { 5351183Svbart@nginx.com goto fail; 5361183Svbart@nginx.com } 5371183Svbart@nginx.com 5381183Svbart@nginx.com field->value = p; 5391855Sz.hong@f5.com field->value_length = length; 5401183Svbart@nginx.com 5411183Svbart@nginx.com if (encode > 0) { 5421183Svbart@nginx.com p = (u_char *) nxt_encode_uri(p, r->path->start, r->path->length); 5431183Svbart@nginx.com 5441183Svbart@nginx.com } else { 5451183Svbart@nginx.com p = nxt_cpymem(p, r->path->start, r->path->length); 5461183Svbart@nginx.com } 5471183Svbart@nginx.com 5481183Svbart@nginx.com *p++ = '/'; 5491183Svbart@nginx.com 5501183Svbart@nginx.com if (r->args->length > 0) { 5511183Svbart@nginx.com *p++ = '?'; 5521183Svbart@nginx.com nxt_memcpy(p, r->args->start, r->args->length); 5531183Svbart@nginx.com } 5541183Svbart@nginx.com 5551183Svbart@nginx.com body_handler = NULL; 5561183Svbart@nginx.com } 5571183Svbart@nginx.com 5581270Sigor@sysoev.ru nxt_http_request_header_send(task, r, body_handler, NULL); 5591183Svbart@nginx.com 5601183Svbart@nginx.com r->state = &nxt_http_static_send_state; 561*1959Sz.hong@f5.com return; 5621183Svbart@nginx.com 5631183Svbart@nginx.com fail: 5641183Svbart@nginx.com 5651855Sz.hong@f5.com if (f != NULL) { 5661183Svbart@nginx.com nxt_file_close(task, f); 5671183Svbart@nginx.com } 5681183Svbart@nginx.com 569*1959Sz.hong@f5.com if (status != NXT_HTTP_INTERNAL_SERVER_ERROR 570*1959Sz.hong@f5.com && action->fallback != NULL) 571*1959Sz.hong@f5.com { 572*1959Sz.hong@f5.com nxt_http_request_action(task, r, action->fallback); 573*1959Sz.hong@f5.com return; 574*1959Sz.hong@f5.com } 575*1959Sz.hong@f5.com 576*1959Sz.hong@f5.com nxt_http_request_error(task, r, status); 577*1959Sz.hong@f5.com } 578*1959Sz.hong@f5.com 579*1959Sz.hong@f5.com 580*1959Sz.hong@f5.com static void 581*1959Sz.hong@f5.com nxt_http_static_var_error(nxt_task_t *task, void *obj, void *data) 582*1959Sz.hong@f5.com { 583*1959Sz.hong@f5.com nxt_http_request_t *r; 584*1959Sz.hong@f5.com 585*1959Sz.hong@f5.com r = obj; 586*1959Sz.hong@f5.com 587*1959Sz.hong@f5.com nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); 5881183Svbart@nginx.com } 5891183Svbart@nginx.com 5901183Svbart@nginx.com 591*1959Sz.hong@f5.com #if (NXT_HAVE_OPENAT2) 592*1959Sz.hong@f5.com 593*1959Sz.hong@f5.com static u_char * 594*1959Sz.hong@f5.com nxt_http_static_chroot_match(u_char *chr, u_char *shr) 595*1959Sz.hong@f5.com { 596*1959Sz.hong@f5.com if (*chr != *shr) { 597*1959Sz.hong@f5.com return NULL; 598*1959Sz.hong@f5.com } 599*1959Sz.hong@f5.com 600*1959Sz.hong@f5.com chr++; 601*1959Sz.hong@f5.com shr++; 602*1959Sz.hong@f5.com 603*1959Sz.hong@f5.com for ( ;; ) { 604*1959Sz.hong@f5.com if (*shr == '\0') { 605*1959Sz.hong@f5.com return NULL; 606*1959Sz.hong@f5.com } 607*1959Sz.hong@f5.com 608*1959Sz.hong@f5.com if (*chr == *shr) { 609*1959Sz.hong@f5.com chr++; 610*1959Sz.hong@f5.com shr++; 611*1959Sz.hong@f5.com continue; 612*1959Sz.hong@f5.com } 613*1959Sz.hong@f5.com 614*1959Sz.hong@f5.com if (*chr == '\0') { 615*1959Sz.hong@f5.com break; 616*1959Sz.hong@f5.com } 617*1959Sz.hong@f5.com 618*1959Sz.hong@f5.com if (*chr == '/') { 619*1959Sz.hong@f5.com if (chr[-1] == '/') { 620*1959Sz.hong@f5.com chr++; 621*1959Sz.hong@f5.com continue; 622*1959Sz.hong@f5.com } 623*1959Sz.hong@f5.com 624*1959Sz.hong@f5.com } else if (*shr == '/') { 625*1959Sz.hong@f5.com if (shr[-1] == '/') { 626*1959Sz.hong@f5.com shr++; 627*1959Sz.hong@f5.com continue; 628*1959Sz.hong@f5.com } 629*1959Sz.hong@f5.com } 630*1959Sz.hong@f5.com 631*1959Sz.hong@f5.com return NULL; 632*1959Sz.hong@f5.com } 633*1959Sz.hong@f5.com 634*1959Sz.hong@f5.com if (shr[-1] != '/' && *shr != '/') { 635*1959Sz.hong@f5.com return NULL; 636*1959Sz.hong@f5.com } 637*1959Sz.hong@f5.com 638*1959Sz.hong@f5.com while (*shr == '/') { 639*1959Sz.hong@f5.com shr++; 640*1959Sz.hong@f5.com } 641*1959Sz.hong@f5.com 642*1959Sz.hong@f5.com return (*shr != '\0') ? shr : NULL; 643*1959Sz.hong@f5.com } 644*1959Sz.hong@f5.com 645*1959Sz.hong@f5.com #endif 646*1959Sz.hong@f5.com 647*1959Sz.hong@f5.com 6481183Svbart@nginx.com static void 6491923Sz.hong@f5.com nxt_http_static_extract_extension(nxt_str_t *path, nxt_str_t *exten) 6501183Svbart@nginx.com { 6511183Svbart@nginx.com u_char ch, *p, *end; 6521183Svbart@nginx.com 6531183Svbart@nginx.com end = path->start + path->length; 6541183Svbart@nginx.com p = end; 6551183Svbart@nginx.com 6561183Svbart@nginx.com for ( ;; ) { 6571183Svbart@nginx.com /* There's always '/' in the beginning of the request path. */ 6581183Svbart@nginx.com 6591183Svbart@nginx.com p--; 6601183Svbart@nginx.com ch = *p; 6611183Svbart@nginx.com 6621183Svbart@nginx.com switch (ch) { 6631183Svbart@nginx.com case '/': 6641183Svbart@nginx.com p++; 6651183Svbart@nginx.com /* Fall through. */ 6661183Svbart@nginx.com case '.': 6671923Sz.hong@f5.com exten->length = end - p; 6681923Sz.hong@f5.com exten->start = p; 6691183Svbart@nginx.com return; 6701183Svbart@nginx.com } 6711183Svbart@nginx.com } 6721183Svbart@nginx.com } 6731183Svbart@nginx.com 6741183Svbart@nginx.com 6751183Svbart@nginx.com static void 6761183Svbart@nginx.com nxt_http_static_body_handler(nxt_task_t *task, void *obj, void *data) 6771183Svbart@nginx.com { 6781183Svbart@nginx.com size_t alloc; 6791183Svbart@nginx.com nxt_buf_t *fb, *b, **next, *out; 6801183Svbart@nginx.com nxt_off_t rest; 6811183Svbart@nginx.com nxt_int_t n; 6821183Svbart@nginx.com nxt_work_queue_t *wq; 6831183Svbart@nginx.com nxt_http_request_t *r; 6841183Svbart@nginx.com 6851183Svbart@nginx.com r = obj; 6861183Svbart@nginx.com fb = r->out; 6871183Svbart@nginx.com 6881183Svbart@nginx.com rest = fb->file_end - fb->file_pos; 6891183Svbart@nginx.com out = NULL; 6901183Svbart@nginx.com next = &out; 6911183Svbart@nginx.com n = 0; 6921183Svbart@nginx.com 6931183Svbart@nginx.com do { 6941183Svbart@nginx.com alloc = nxt_min(rest, NXT_HTTP_STATIC_BUF_SIZE); 6951183Svbart@nginx.com 6961183Svbart@nginx.com b = nxt_buf_mem_alloc(r->mem_pool, alloc, 0); 6971183Svbart@nginx.com if (nxt_slow_path(b == NULL)) { 6981183Svbart@nginx.com goto fail; 6991183Svbart@nginx.com } 7001183Svbart@nginx.com 7011183Svbart@nginx.com b->completion_handler = nxt_http_static_buf_completion; 7021183Svbart@nginx.com b->parent = r; 7031183Svbart@nginx.com 7041183Svbart@nginx.com nxt_mp_retain(r->mem_pool); 7051183Svbart@nginx.com 7061183Svbart@nginx.com *next = b; 7071183Svbart@nginx.com next = &b->next; 7081183Svbart@nginx.com 7091183Svbart@nginx.com rest -= alloc; 7101183Svbart@nginx.com 7111183Svbart@nginx.com } while (rest > 0 && ++n < NXT_HTTP_STATIC_BUF_COUNT); 7121183Svbart@nginx.com 7131183Svbart@nginx.com wq = &task->thread->engine->fast_work_queue; 7141183Svbart@nginx.com 7151183Svbart@nginx.com nxt_sendbuf_drain(task, wq, out); 7161183Svbart@nginx.com return; 7171183Svbart@nginx.com 7181183Svbart@nginx.com fail: 7191183Svbart@nginx.com 7201183Svbart@nginx.com while (out != NULL) { 7211183Svbart@nginx.com b = out; 7221183Svbart@nginx.com out = b->next; 7231183Svbart@nginx.com 7241183Svbart@nginx.com nxt_mp_free(r->mem_pool, b); 7251183Svbart@nginx.com nxt_mp_release(r->mem_pool); 7261183Svbart@nginx.com } 7271183Svbart@nginx.com } 7281183Svbart@nginx.com 7291183Svbart@nginx.com 7301183Svbart@nginx.com static const nxt_http_request_state_t nxt_http_static_send_state 7311183Svbart@nginx.com nxt_aligned(64) = 7321183Svbart@nginx.com { 7331183Svbart@nginx.com .error_handler = nxt_http_request_error_handler, 7341183Svbart@nginx.com }; 7351183Svbart@nginx.com 7361183Svbart@nginx.com 7371183Svbart@nginx.com static void 7381183Svbart@nginx.com nxt_http_static_buf_completion(nxt_task_t *task, void *obj, void *data) 7391183Svbart@nginx.com { 7401183Svbart@nginx.com ssize_t n, size; 7411760Smax.romanov@nginx.com nxt_buf_t *b, *fb, *next; 7421183Svbart@nginx.com nxt_off_t rest; 7431183Svbart@nginx.com nxt_http_request_t *r; 7441183Svbart@nginx.com 7451183Svbart@nginx.com b = obj; 7461183Svbart@nginx.com r = data; 7471760Smax.romanov@nginx.com 7481760Smax.romanov@nginx.com complete_buf: 7491760Smax.romanov@nginx.com 7501183Svbart@nginx.com fb = r->out; 7511183Svbart@nginx.com 7521183Svbart@nginx.com if (nxt_slow_path(fb == NULL || r->error)) { 7531183Svbart@nginx.com goto clean; 7541183Svbart@nginx.com } 7551183Svbart@nginx.com 7561183Svbart@nginx.com rest = fb->file_end - fb->file_pos; 7571183Svbart@nginx.com size = nxt_buf_mem_size(&b->mem); 7581183Svbart@nginx.com 7591183Svbart@nginx.com size = nxt_min(rest, (nxt_off_t) size); 7601183Svbart@nginx.com 7611183Svbart@nginx.com n = nxt_file_read(fb->file, b->mem.start, size, fb->file_pos); 7621183Svbart@nginx.com 7631183Svbart@nginx.com if (n != size) { 7641183Svbart@nginx.com if (n >= 0) { 7651183Svbart@nginx.com nxt_log(task, NXT_LOG_ERR, "file \"%FN\" has changed " 7661183Svbart@nginx.com "while sending response to a client", fb->file->name); 7671183Svbart@nginx.com } 7681183Svbart@nginx.com 7691183Svbart@nginx.com nxt_http_request_error_handler(task, r, r->proto.any); 7701183Svbart@nginx.com goto clean; 7711183Svbart@nginx.com } 7721183Svbart@nginx.com 7731760Smax.romanov@nginx.com next = b->next; 7741760Smax.romanov@nginx.com 7751183Svbart@nginx.com if (n == rest) { 7761183Svbart@nginx.com nxt_file_close(task, fb->file); 7771183Svbart@nginx.com r->out = NULL; 7781183Svbart@nginx.com 7791183Svbart@nginx.com b->next = nxt_http_buf_last(r); 7801183Svbart@nginx.com 7811183Svbart@nginx.com } else { 7821183Svbart@nginx.com fb->file_pos += n; 7831183Svbart@nginx.com b->next = NULL; 7841183Svbart@nginx.com } 7851183Svbart@nginx.com 7861183Svbart@nginx.com b->mem.pos = b->mem.start; 7871183Svbart@nginx.com b->mem.free = b->mem.pos + n; 7881183Svbart@nginx.com 7891183Svbart@nginx.com nxt_http_request_send(task, r, b); 7901760Smax.romanov@nginx.com 7911760Smax.romanov@nginx.com if (next != NULL) { 7921760Smax.romanov@nginx.com b = next; 7931760Smax.romanov@nginx.com goto complete_buf; 7941760Smax.romanov@nginx.com } 7951760Smax.romanov@nginx.com 7961183Svbart@nginx.com return; 7971183Svbart@nginx.com 7981183Svbart@nginx.com clean: 7991183Svbart@nginx.com 8001760Smax.romanov@nginx.com do { 8011760Smax.romanov@nginx.com next = b->next; 8021760Smax.romanov@nginx.com 8031760Smax.romanov@nginx.com nxt_mp_free(r->mem_pool, b); 8041760Smax.romanov@nginx.com nxt_mp_release(r->mem_pool); 8051760Smax.romanov@nginx.com 8061760Smax.romanov@nginx.com b = next; 8071760Smax.romanov@nginx.com } while (b != NULL); 8081183Svbart@nginx.com 8091183Svbart@nginx.com if (fb != NULL) { 8101183Svbart@nginx.com nxt_file_close(task, fb->file); 8111183Svbart@nginx.com r->out = NULL; 8121183Svbart@nginx.com } 8131183Svbart@nginx.com } 8141183Svbart@nginx.com 8151183Svbart@nginx.com 8161183Svbart@nginx.com nxt_int_t 8171183Svbart@nginx.com nxt_http_static_mtypes_init(nxt_mp_t *mp, nxt_lvlhsh_t *hash) 8181183Svbart@nginx.com { 8191923Sz.hong@f5.com nxt_str_t *type, exten; 8201183Svbart@nginx.com nxt_int_t ret; 8211183Svbart@nginx.com nxt_uint_t i; 8221183Svbart@nginx.com 8231183Svbart@nginx.com static const struct { 8241183Svbart@nginx.com nxt_str_t type; 8251923Sz.hong@f5.com const char *exten; 8261183Svbart@nginx.com } default_types[] = { 8271183Svbart@nginx.com 8281183Svbart@nginx.com { nxt_string("text/html"), ".html" }, 8291183Svbart@nginx.com { nxt_string("text/html"), ".htm" }, 8301183Svbart@nginx.com { nxt_string("text/css"), ".css" }, 8311183Svbart@nginx.com 8321183Svbart@nginx.com { nxt_string("image/svg+xml"), ".svg" }, 8331183Svbart@nginx.com { nxt_string("image/webp"), ".webp" }, 8341183Svbart@nginx.com { nxt_string("image/png"), ".png" }, 8351617Svbart@nginx.com { nxt_string("image/apng"), ".apng" }, 8361183Svbart@nginx.com { nxt_string("image/jpeg"), ".jpeg" }, 8371183Svbart@nginx.com { nxt_string("image/jpeg"), ".jpg" }, 8381183Svbart@nginx.com { nxt_string("image/gif"), ".gif" }, 8391183Svbart@nginx.com { nxt_string("image/x-icon"), ".ico" }, 8401183Svbart@nginx.com 8411617Svbart@nginx.com { nxt_string("image/avif"), ".avif" }, 8421617Svbart@nginx.com { nxt_string("image/avif-sequence"), ".avifs" }, 8431617Svbart@nginx.com 8441183Svbart@nginx.com { nxt_string("font/woff"), ".woff" }, 8451183Svbart@nginx.com { nxt_string("font/woff2"), ".woff2" }, 8461183Svbart@nginx.com { nxt_string("font/otf"), ".otf" }, 8471183Svbart@nginx.com { nxt_string("font/ttf"), ".ttf" }, 8481183Svbart@nginx.com 8491183Svbart@nginx.com { nxt_string("text/plain"), ".txt" }, 8501183Svbart@nginx.com { nxt_string("text/markdown"), ".md" }, 8511183Svbart@nginx.com { nxt_string("text/x-rst"), ".rst" }, 8521183Svbart@nginx.com 8531183Svbart@nginx.com { nxt_string("application/javascript"), ".js" }, 8541183Svbart@nginx.com { nxt_string("application/json"), ".json" }, 8551183Svbart@nginx.com { nxt_string("application/xml"), ".xml" }, 8561183Svbart@nginx.com { nxt_string("application/rss+xml"), ".rss" }, 8571183Svbart@nginx.com { nxt_string("application/atom+xml"), ".atom" }, 8581183Svbart@nginx.com { nxt_string("application/pdf"), ".pdf" }, 8591183Svbart@nginx.com 8601183Svbart@nginx.com { nxt_string("application/zip"), ".zip" }, 8611183Svbart@nginx.com 8621183Svbart@nginx.com { nxt_string("audio/mpeg"), ".mp3" }, 8631183Svbart@nginx.com { nxt_string("audio/ogg"), ".ogg" }, 8641183Svbart@nginx.com { nxt_string("audio/midi"), ".midi" }, 8651183Svbart@nginx.com { nxt_string("audio/midi"), ".mid" }, 8661183Svbart@nginx.com { nxt_string("audio/flac"), ".flac" }, 8671183Svbart@nginx.com { nxt_string("audio/aac"), ".aac" }, 8681183Svbart@nginx.com { nxt_string("audio/wav"), ".wav" }, 8691183Svbart@nginx.com 8701183Svbart@nginx.com { nxt_string("video/mpeg"), ".mpeg" }, 8711183Svbart@nginx.com { nxt_string("video/mpeg"), ".mpg" }, 8721183Svbart@nginx.com { nxt_string("video/mp4"), ".mp4" }, 8731183Svbart@nginx.com { nxt_string("video/webm"), ".webm" }, 8741183Svbart@nginx.com { nxt_string("video/x-msvideo"), ".avi" }, 8751183Svbart@nginx.com 8761183Svbart@nginx.com { nxt_string("application/octet-stream"), ".exe" }, 8771183Svbart@nginx.com { nxt_string("application/octet-stream"), ".bin" }, 8781183Svbart@nginx.com { nxt_string("application/octet-stream"), ".dll" }, 8791183Svbart@nginx.com { nxt_string("application/octet-stream"), ".iso" }, 8801183Svbart@nginx.com { nxt_string("application/octet-stream"), ".img" }, 8811183Svbart@nginx.com { nxt_string("application/octet-stream"), ".msi" }, 8821183Svbart@nginx.com 8831183Svbart@nginx.com { nxt_string("application/octet-stream"), ".deb" }, 8841183Svbart@nginx.com { nxt_string("application/octet-stream"), ".rpm" }, 8851882So.canty@f5.com 8861882So.canty@f5.com { nxt_string("application/x-httpd-php"), ".php" }, 8871183Svbart@nginx.com }; 8881183Svbart@nginx.com 8891183Svbart@nginx.com for (i = 0; i < nxt_nitems(default_types); i++) { 8901183Svbart@nginx.com type = (nxt_str_t *) &default_types[i].type; 8911183Svbart@nginx.com 8921923Sz.hong@f5.com exten.start = (u_char *) default_types[i].exten; 8931923Sz.hong@f5.com exten.length = nxt_strlen(exten.start); 8941183Svbart@nginx.com 8951923Sz.hong@f5.com ret = nxt_http_static_mtypes_hash_add(mp, hash, &exten, type); 8961183Svbart@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 8971183Svbart@nginx.com return NXT_ERROR; 8981183Svbart@nginx.com } 8991183Svbart@nginx.com } 9001183Svbart@nginx.com 9011183Svbart@nginx.com return NXT_OK; 9021183Svbart@nginx.com } 9031183Svbart@nginx.com 9041183Svbart@nginx.com 9051183Svbart@nginx.com static const nxt_lvlhsh_proto_t nxt_http_static_mtypes_hash_proto 9061183Svbart@nginx.com nxt_aligned(64) = 9071183Svbart@nginx.com { 9081183Svbart@nginx.com NXT_LVLHSH_DEFAULT, 9091183Svbart@nginx.com nxt_http_static_mtypes_hash_test, 9101183Svbart@nginx.com nxt_http_static_mtypes_hash_alloc, 9111183Svbart@nginx.com nxt_http_static_mtypes_hash_free, 9121183Svbart@nginx.com }; 9131183Svbart@nginx.com 9141183Svbart@nginx.com 9151183Svbart@nginx.com typedef struct { 9161923Sz.hong@f5.com nxt_str_t exten; 9171183Svbart@nginx.com nxt_str_t *type; 9181183Svbart@nginx.com } nxt_http_static_mtype_t; 9191183Svbart@nginx.com 9201183Svbart@nginx.com 9211183Svbart@nginx.com nxt_int_t 9221183Svbart@nginx.com nxt_http_static_mtypes_hash_add(nxt_mp_t *mp, nxt_lvlhsh_t *hash, 9231923Sz.hong@f5.com nxt_str_t *exten, nxt_str_t *type) 9241183Svbart@nginx.com { 9251183Svbart@nginx.com nxt_lvlhsh_query_t lhq; 9261183Svbart@nginx.com nxt_http_static_mtype_t *mtype; 9271183Svbart@nginx.com 9281183Svbart@nginx.com mtype = nxt_mp_get(mp, sizeof(nxt_http_static_mtype_t)); 9291183Svbart@nginx.com if (nxt_slow_path(mtype == NULL)) { 9301183Svbart@nginx.com return NXT_ERROR; 9311183Svbart@nginx.com } 9321183Svbart@nginx.com 9331923Sz.hong@f5.com mtype->exten = *exten; 9341183Svbart@nginx.com mtype->type = type; 9351183Svbart@nginx.com 9361923Sz.hong@f5.com lhq.key = *exten; 9371183Svbart@nginx.com lhq.key_hash = nxt_djb_hash_lowcase(lhq.key.start, lhq.key.length); 9381183Svbart@nginx.com lhq.replace = 1; 9391183Svbart@nginx.com lhq.value = mtype; 9401183Svbart@nginx.com lhq.proto = &nxt_http_static_mtypes_hash_proto; 9411183Svbart@nginx.com lhq.pool = mp; 9421183Svbart@nginx.com 9431183Svbart@nginx.com return nxt_lvlhsh_insert(hash, &lhq); 9441183Svbart@nginx.com } 9451183Svbart@nginx.com 9461183Svbart@nginx.com 9471183Svbart@nginx.com nxt_str_t * 9481923Sz.hong@f5.com nxt_http_static_mtype_get(nxt_lvlhsh_t *hash, nxt_str_t *exten) 9491183Svbart@nginx.com { 9501183Svbart@nginx.com nxt_lvlhsh_query_t lhq; 9511183Svbart@nginx.com nxt_http_static_mtype_t *mtype; 9521183Svbart@nginx.com 9531883So.canty@f5.com static nxt_str_t empty = nxt_string(""); 9541883So.canty@f5.com 9551923Sz.hong@f5.com lhq.key = *exten; 9561183Svbart@nginx.com lhq.key_hash = nxt_djb_hash_lowcase(lhq.key.start, lhq.key.length); 9571183Svbart@nginx.com lhq.proto = &nxt_http_static_mtypes_hash_proto; 9581183Svbart@nginx.com 9591183Svbart@nginx.com if (nxt_lvlhsh_find(hash, &lhq) == NXT_OK) { 9601183Svbart@nginx.com mtype = lhq.value; 9611183Svbart@nginx.com return mtype->type; 9621183Svbart@nginx.com } 9631183Svbart@nginx.com 9641883So.canty@f5.com return ∅ 9651183Svbart@nginx.com } 9661183Svbart@nginx.com 9671183Svbart@nginx.com 9681183Svbart@nginx.com static nxt_int_t 9691183Svbart@nginx.com nxt_http_static_mtypes_hash_test(nxt_lvlhsh_query_t *lhq, void *data) 9701183Svbart@nginx.com { 9711183Svbart@nginx.com nxt_http_static_mtype_t *mtype; 9721183Svbart@nginx.com 9731183Svbart@nginx.com mtype = data; 9741183Svbart@nginx.com 9751923Sz.hong@f5.com return nxt_strcasestr_eq(&lhq->key, &mtype->exten) ? NXT_OK : NXT_DECLINED; 9761183Svbart@nginx.com } 9771183Svbart@nginx.com 9781183Svbart@nginx.com 9791183Svbart@nginx.com static void * 9801183Svbart@nginx.com nxt_http_static_mtypes_hash_alloc(void *data, size_t size) 9811183Svbart@nginx.com { 9821183Svbart@nginx.com return nxt_mp_align(data, size, size); 9831183Svbart@nginx.com } 9841183Svbart@nginx.com 9851183Svbart@nginx.com 9861183Svbart@nginx.com static void 9871183Svbart@nginx.com nxt_http_static_mtypes_hash_free(void *data, void *p) 9881183Svbart@nginx.com { 9891183Svbart@nginx.com nxt_mp_free(data, p); 9901183Svbart@nginx.com } 991