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 { 111961Sz.hong@f5.com nxt_var_t *var; 121961Sz.hong@f5.com #if (NXT_HAVE_OPENAT2) 131961Sz.hong@f5.com u_char *fname; 141961Sz.hong@f5.com #endif 151961Sz.hong@f5.com uint8_t is_const; /* 1 bit */ 161961Sz.hong@f5.com } nxt_http_static_share_t; 171961Sz.hong@f5.com 181961Sz.hong@f5.com 191961Sz.hong@f5.com typedef struct { 201961Sz.hong@f5.com nxt_uint_t nshares; 211961Sz.hong@f5.com nxt_http_static_share_t *shares; 221959Sz.hong@f5.com #if (NXT_HAVE_OPENAT2) 231959Sz.hong@f5.com nxt_var_t *chroot; 241959Sz.hong@f5.com nxt_uint_t resolve; 251959Sz.hong@f5.com #endif 261959Sz.hong@f5.com nxt_http_route_rule_t *types; 271923Sz.hong@f5.com } nxt_http_static_conf_t; 281923Sz.hong@f5.com 291923Sz.hong@f5.com 301959Sz.hong@f5.com typedef struct { 311959Sz.hong@f5.com nxt_http_action_t *action; 321960Sz.hong@f5.com nxt_str_t share; 331959Sz.hong@f5.com #if (NXT_HAVE_OPENAT2) 341959Sz.hong@f5.com nxt_str_t chroot; 351959Sz.hong@f5.com #endif 361961Sz.hong@f5.com uint32_t index; 371959Sz.hong@f5.com uint8_t need_body; /* 1 bit */ 381959Sz.hong@f5.com } nxt_http_static_ctx_t; 391959Sz.hong@f5.com 401959Sz.hong@f5.com 411183Svbart@nginx.com #define NXT_HTTP_STATIC_BUF_COUNT 2 421183Svbart@nginx.com #define NXT_HTTP_STATIC_BUF_SIZE (128 * 1024) 431183Svbart@nginx.com 441183Svbart@nginx.com 451923Sz.hong@f5.com static nxt_http_action_t *nxt_http_static(nxt_task_t *task, 461923Sz.hong@f5.com nxt_http_request_t *r, nxt_http_action_t *action); 471961Sz.hong@f5.com static void nxt_http_static_iterate(nxt_task_t *task, nxt_http_request_t *r, 481961Sz.hong@f5.com nxt_http_static_ctx_t *ctx); 491959Sz.hong@f5.com static void nxt_http_static_send_ready(nxt_task_t *task, void *obj, void *data); 501959Sz.hong@f5.com static void nxt_http_static_var_error(nxt_task_t *task, void *obj, void *data); 511961Sz.hong@f5.com static void nxt_http_static_next(nxt_task_t *task, nxt_http_request_t *r, 521961Sz.hong@f5.com nxt_http_static_ctx_t *ctx, nxt_http_status_t status); 531959Sz.hong@f5.com #if (NXT_HAVE_OPENAT2) 541959Sz.hong@f5.com static u_char *nxt_http_static_chroot_match(u_char *chr, u_char *shr); 551959Sz.hong@f5.com #endif 561183Svbart@nginx.com static void nxt_http_static_extract_extension(nxt_str_t *path, 571923Sz.hong@f5.com nxt_str_t *exten); 581183Svbart@nginx.com static void nxt_http_static_body_handler(nxt_task_t *task, void *obj, 591183Svbart@nginx.com void *data); 601183Svbart@nginx.com static void nxt_http_static_buf_completion(nxt_task_t *task, void *obj, 611183Svbart@nginx.com void *data); 621183Svbart@nginx.com 631183Svbart@nginx.com static nxt_int_t nxt_http_static_mtypes_hash_test(nxt_lvlhsh_query_t *lhq, 641183Svbart@nginx.com void *data); 651183Svbart@nginx.com static void *nxt_http_static_mtypes_hash_alloc(void *data, size_t size); 661183Svbart@nginx.com static void nxt_http_static_mtypes_hash_free(void *data, void *p); 671183Svbart@nginx.com 681183Svbart@nginx.com 691183Svbart@nginx.com static const nxt_http_request_state_t nxt_http_static_send_state; 701183Svbart@nginx.com 711183Svbart@nginx.com 721923Sz.hong@f5.com nxt_int_t 731923Sz.hong@f5.com nxt_http_static_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 741923Sz.hong@f5.com nxt_http_action_t *action, nxt_http_action_conf_t *acf) 751923Sz.hong@f5.com { 761961Sz.hong@f5.com uint32_t i; 771923Sz.hong@f5.com nxt_mp_t *mp; 781960Sz.hong@f5.com nxt_str_t str; 791961Sz.hong@f5.com nxt_var_t *var; 801961Sz.hong@f5.com nxt_conf_value_t *cv; 811923Sz.hong@f5.com nxt_http_static_conf_t *conf; 821923Sz.hong@f5.com 831923Sz.hong@f5.com mp = tmcf->router_conf->mem_pool; 841923Sz.hong@f5.com 851923Sz.hong@f5.com conf = nxt_mp_zget(mp, sizeof(nxt_http_static_conf_t)); 861923Sz.hong@f5.com if (nxt_slow_path(conf == NULL)) { 871923Sz.hong@f5.com return NXT_ERROR; 881923Sz.hong@f5.com } 891923Sz.hong@f5.com 901923Sz.hong@f5.com action->handler = nxt_http_static; 911923Sz.hong@f5.com action->u.conf = conf; 921923Sz.hong@f5.com 93*2077Salx.manpages@gmail.com conf->nshares = nxt_conf_array_elements_count_or_1(acf->share); 941961Sz.hong@f5.com conf->shares = nxt_mp_zget(mp, sizeof(nxt_http_static_share_t) 951961Sz.hong@f5.com * conf->nshares); 961961Sz.hong@f5.com if (nxt_slow_path(conf->shares == NULL)) { 971923Sz.hong@f5.com return NXT_ERROR; 981923Sz.hong@f5.com } 991923Sz.hong@f5.com 100*2077Salx.manpages@gmail.com for (i = 0; i < conf->nshares; i++) { 101*2077Salx.manpages@gmail.com cv = nxt_conf_get_array_element_or_itself(acf->share, i); 102*2077Salx.manpages@gmail.com nxt_conf_get_string(cv, &str); 1031961Sz.hong@f5.com 1041961Sz.hong@f5.com var = nxt_var_compile(&str, mp, 1); 1051961Sz.hong@f5.com if (nxt_slow_path(var == NULL)) { 1061961Sz.hong@f5.com return NXT_ERROR; 1071961Sz.hong@f5.com } 1081961Sz.hong@f5.com 109*2077Salx.manpages@gmail.com conf->shares[i].var = var; 110*2077Salx.manpages@gmail.com conf->shares[i].is_const = nxt_var_is_const(var); 1111961Sz.hong@f5.com } 1121959Sz.hong@f5.com 1131923Sz.hong@f5.com #if (NXT_HAVE_OPENAT2) 1141923Sz.hong@f5.com if (acf->chroot.length > 0) { 1151961Sz.hong@f5.com nxt_str_t chr, shr; 1161961Sz.hong@f5.com nxt_bool_t is_const; 1171923Sz.hong@f5.com 1181959Sz.hong@f5.com conf->chroot = nxt_var_compile(&acf->chroot, mp, 1); 1191959Sz.hong@f5.com if (nxt_slow_path(conf->chroot == NULL)) { 1201923Sz.hong@f5.com return NXT_ERROR; 1211923Sz.hong@f5.com } 1221960Sz.hong@f5.com 1231961Sz.hong@f5.com is_const = nxt_var_is_const(conf->chroot); 1241961Sz.hong@f5.com 1251961Sz.hong@f5.com for (i = 0; i < conf->nshares; i++) { 1261961Sz.hong@f5.com conf->shares[i].is_const &= is_const; 1271960Sz.hong@f5.com 1281961Sz.hong@f5.com if (conf->shares[i].is_const) { 1291961Sz.hong@f5.com nxt_var_raw(conf->chroot, &chr); 1301961Sz.hong@f5.com nxt_var_raw(conf->shares[i].var, &shr); 1311961Sz.hong@f5.com 1321961Sz.hong@f5.com conf->shares[i].fname = nxt_http_static_chroot_match(chr.start, 1331961Sz.hong@f5.com shr.start); 1341961Sz.hong@f5.com } 1351960Sz.hong@f5.com } 1361923Sz.hong@f5.com } 1371923Sz.hong@f5.com 1381923Sz.hong@f5.com if (acf->follow_symlinks != NULL 1391923Sz.hong@f5.com && !nxt_conf_get_boolean(acf->follow_symlinks)) 1401923Sz.hong@f5.com { 1411923Sz.hong@f5.com conf->resolve |= RESOLVE_NO_SYMLINKS; 1421923Sz.hong@f5.com } 1431923Sz.hong@f5.com 1441923Sz.hong@f5.com if (acf->traverse_mounts != NULL 1451923Sz.hong@f5.com && !nxt_conf_get_boolean(acf->traverse_mounts)) 1461923Sz.hong@f5.com { 1471923Sz.hong@f5.com conf->resolve |= RESOLVE_NO_XDEV; 1481923Sz.hong@f5.com } 1491923Sz.hong@f5.com #endif 1501923Sz.hong@f5.com 1511923Sz.hong@f5.com if (acf->types != NULL) { 1521923Sz.hong@f5.com conf->types = nxt_http_route_types_rule_create(task, mp, acf->types); 1531923Sz.hong@f5.com if (nxt_slow_path(conf->types == NULL)) { 1541923Sz.hong@f5.com return NXT_ERROR; 1551923Sz.hong@f5.com } 1561923Sz.hong@f5.com } 1571923Sz.hong@f5.com 1581923Sz.hong@f5.com if (acf->fallback != NULL) { 1591923Sz.hong@f5.com action->fallback = nxt_mp_alloc(mp, sizeof(nxt_http_action_t)); 1601923Sz.hong@f5.com if (nxt_slow_path(action->fallback == NULL)) { 1611923Sz.hong@f5.com return NXT_ERROR; 1621923Sz.hong@f5.com } 1631923Sz.hong@f5.com 1641923Sz.hong@f5.com return nxt_http_action_init(task, tmcf, acf->fallback, 1651923Sz.hong@f5.com action->fallback); 1661923Sz.hong@f5.com } 1671923Sz.hong@f5.com 1681923Sz.hong@f5.com return NXT_OK; 1691923Sz.hong@f5.com } 1701923Sz.hong@f5.com 1711923Sz.hong@f5.com 1721923Sz.hong@f5.com static nxt_http_action_t * 1731923Sz.hong@f5.com nxt_http_static(nxt_task_t *task, nxt_http_request_t *r, 1741264Sigor@sysoev.ru nxt_http_action_t *action) 1751183Svbart@nginx.com { 1761961Sz.hong@f5.com nxt_bool_t need_body; 1771961Sz.hong@f5.com nxt_http_static_ctx_t *ctx; 1781923Sz.hong@f5.com 1791183Svbart@nginx.com if (nxt_slow_path(!nxt_str_eq(r->method, "GET", 3))) { 1801183Svbart@nginx.com 1811183Svbart@nginx.com if (!nxt_str_eq(r->method, "HEAD", 4)) { 1821923Sz.hong@f5.com if (action->fallback != NULL) { 1831923Sz.hong@f5.com return action->fallback; 1841378Svbart@nginx.com } 1851378Svbart@nginx.com 1861183Svbart@nginx.com nxt_http_request_error(task, r, NXT_HTTP_METHOD_NOT_ALLOWED); 1871183Svbart@nginx.com return NULL; 1881183Svbart@nginx.com } 1891183Svbart@nginx.com 1901183Svbart@nginx.com need_body = 0; 1911183Svbart@nginx.com 1921183Svbart@nginx.com } else { 1931183Svbart@nginx.com need_body = 1; 1941183Svbart@nginx.com } 1951183Svbart@nginx.com 1961961Sz.hong@f5.com ctx = nxt_mp_zget(r->mem_pool, sizeof(nxt_http_static_ctx_t)); 1971961Sz.hong@f5.com if (nxt_slow_path(ctx == NULL)) { 1981961Sz.hong@f5.com nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); 1991961Sz.hong@f5.com return NULL; 2001961Sz.hong@f5.com } 2011961Sz.hong@f5.com 2021961Sz.hong@f5.com ctx->action = action; 2031961Sz.hong@f5.com ctx->need_body = need_body; 2041961Sz.hong@f5.com 2051961Sz.hong@f5.com nxt_http_static_iterate(task, r, ctx); 2061961Sz.hong@f5.com 2071961Sz.hong@f5.com return NULL; 2081961Sz.hong@f5.com } 2091961Sz.hong@f5.com 2101961Sz.hong@f5.com 2111961Sz.hong@f5.com static void 2121961Sz.hong@f5.com nxt_http_static_iterate(nxt_task_t *task, nxt_http_request_t *r, 2131961Sz.hong@f5.com nxt_http_static_ctx_t *ctx) 2141961Sz.hong@f5.com { 2151961Sz.hong@f5.com nxt_int_t ret; 2161961Sz.hong@f5.com nxt_http_static_conf_t *conf; 2171961Sz.hong@f5.com nxt_http_static_share_t *share; 2181961Sz.hong@f5.com 2191961Sz.hong@f5.com conf = ctx->action->u.conf; 2201961Sz.hong@f5.com 2211961Sz.hong@f5.com share = &conf->shares[ctx->index]; 2221959Sz.hong@f5.com 2231960Sz.hong@f5.com #if (NXT_DEBUG) 2241960Sz.hong@f5.com nxt_str_t shr; 2251960Sz.hong@f5.com 2261961Sz.hong@f5.com nxt_var_raw(share->var, &shr); 2271960Sz.hong@f5.com 2281960Sz.hong@f5.com #if (NXT_HAVE_OPENAT2) 2291959Sz.hong@f5.com nxt_str_t chr; 2301959Sz.hong@f5.com 2311959Sz.hong@f5.com if (conf->chroot != NULL) { 2321959Sz.hong@f5.com nxt_var_raw(conf->chroot, &chr); 2331959Sz.hong@f5.com 2341959Sz.hong@f5.com } else { 2351959Sz.hong@f5.com nxt_str_set(&chr, ""); 2361959Sz.hong@f5.com } 2371959Sz.hong@f5.com 2381960Sz.hong@f5.com nxt_debug(task, "http static: \"%V\" (chroot: \"%V\")", &shr, &chr); 2391959Sz.hong@f5.com #else 2401960Sz.hong@f5.com nxt_debug(task, "http static: \"%V\"", &shr); 2411959Sz.hong@f5.com #endif 2421960Sz.hong@f5.com #endif /* NXT_DEBUG */ 2431959Sz.hong@f5.com 2441961Sz.hong@f5.com if (share->is_const) { 2451961Sz.hong@f5.com nxt_var_raw(share->var, &ctx->share); 2461960Sz.hong@f5.com 2471959Sz.hong@f5.com #if (NXT_HAVE_OPENAT2) 2481961Sz.hong@f5.com if (conf->chroot != NULL && ctx->index == 0) { 2491959Sz.hong@f5.com nxt_var_raw(conf->chroot, &ctx->chroot); 2501959Sz.hong@f5.com } 2511959Sz.hong@f5.com #endif 2521959Sz.hong@f5.com 2531959Sz.hong@f5.com nxt_http_static_send_ready(task, r, ctx); 2541959Sz.hong@f5.com 2551959Sz.hong@f5.com } else { 2561959Sz.hong@f5.com ret = nxt_var_query_init(&r->var_query, r, r->mem_pool); 2571959Sz.hong@f5.com if (nxt_slow_path(ret != NXT_OK)) { 2581961Sz.hong@f5.com nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); 2591961Sz.hong@f5.com return; 2601959Sz.hong@f5.com } 2611959Sz.hong@f5.com 2621961Sz.hong@f5.com nxt_var_query(task, r->var_query, share->var, &ctx->share); 2631960Sz.hong@f5.com 2641959Sz.hong@f5.com #if (NXT_HAVE_OPENAT2) 2651961Sz.hong@f5.com if (conf->chroot != NULL && ctx->index == 0) { 2661960Sz.hong@f5.com nxt_var_query(task, r->var_query, conf->chroot, &ctx->chroot); 2671960Sz.hong@f5.com } 2681959Sz.hong@f5.com #endif 2691959Sz.hong@f5.com 2701959Sz.hong@f5.com nxt_var_query_resolve(task, r->var_query, ctx, 2711959Sz.hong@f5.com nxt_http_static_send_ready, 2721959Sz.hong@f5.com nxt_http_static_var_error); 2731961Sz.hong@f5.com } 2741959Sz.hong@f5.com } 2751959Sz.hong@f5.com 2761959Sz.hong@f5.com 2771959Sz.hong@f5.com static void 2781959Sz.hong@f5.com nxt_http_static_send_ready(nxt_task_t *task, void *obj, void *data) 2791959Sz.hong@f5.com { 2801959Sz.hong@f5.com size_t length, encode; 2811959Sz.hong@f5.com u_char *p, *fname; 2821959Sz.hong@f5.com struct tm tm; 2831959Sz.hong@f5.com nxt_buf_t *fb; 2841959Sz.hong@f5.com nxt_int_t ret; 2851960Sz.hong@f5.com nxt_str_t *shr, exten, *mtype; 2861959Sz.hong@f5.com nxt_uint_t level; 2871959Sz.hong@f5.com nxt_file_t *f, file; 2881959Sz.hong@f5.com nxt_file_info_t fi; 2891959Sz.hong@f5.com nxt_http_field_t *field; 2901959Sz.hong@f5.com nxt_http_status_t status; 2911959Sz.hong@f5.com nxt_router_conf_t *rtcf; 2921959Sz.hong@f5.com nxt_http_action_t *action; 2931959Sz.hong@f5.com nxt_http_request_t *r; 2941959Sz.hong@f5.com nxt_work_handler_t body_handler; 2951959Sz.hong@f5.com nxt_http_static_ctx_t *ctx; 2961959Sz.hong@f5.com nxt_http_static_conf_t *conf; 2971959Sz.hong@f5.com 2981961Sz.hong@f5.com static const nxt_str_t index = nxt_string("index.html"); 2991960Sz.hong@f5.com 3001959Sz.hong@f5.com r = obj; 3011959Sz.hong@f5.com ctx = data; 3021959Sz.hong@f5.com action = ctx->action; 3031959Sz.hong@f5.com conf = action->u.conf; 3041960Sz.hong@f5.com rtcf = r->conf->socket_conf->router_conf; 3051183Svbart@nginx.com 3061855Sz.hong@f5.com f = NULL; 3071960Sz.hong@f5.com mtype = NULL; 3081183Svbart@nginx.com 3091960Sz.hong@f5.com shr = &ctx->share; 3101859So.canty@f5.com 3111960Sz.hong@f5.com if (shr->start[shr->length - 1] == '/') { 3121960Sz.hong@f5.com /* TODO: dynamic index setting. */ 3131960Sz.hong@f5.com nxt_str_set(&exten, ".html"); 3141859So.canty@f5.com 3151960Sz.hong@f5.com length = shr->length + index.length; 3161960Sz.hong@f5.com 3171960Sz.hong@f5.com fname = nxt_mp_nget(r->mem_pool, length + 1); 3181960Sz.hong@f5.com if (nxt_slow_path(fname == NULL)) { 3191883So.canty@f5.com goto fail; 3201883So.canty@f5.com } 3211883So.canty@f5.com 3221960Sz.hong@f5.com p = fname; 3231960Sz.hong@f5.com p = nxt_cpymem(p, shr->start, shr->length); 3241960Sz.hong@f5.com p = nxt_cpymem(p, index.start, index.length); 3251960Sz.hong@f5.com *p = '\0'; 3261859So.canty@f5.com 3271960Sz.hong@f5.com } else { 3281960Sz.hong@f5.com if (conf->types == NULL) { 3291960Sz.hong@f5.com nxt_str_null(&exten); 3301960Sz.hong@f5.com 3311960Sz.hong@f5.com } else { 3321960Sz.hong@f5.com nxt_http_static_extract_extension(shr, &exten); 3331960Sz.hong@f5.com mtype = nxt_http_static_mtype_get(&rtcf->mtypes_hash, &exten); 3341855Sz.hong@f5.com 3351960Sz.hong@f5.com ret = nxt_http_route_test_rule(r, conf->types, mtype->start, 3361960Sz.hong@f5.com mtype->length); 3371960Sz.hong@f5.com if (nxt_slow_path(ret == NXT_ERROR)) { 3381960Sz.hong@f5.com goto fail; 3391960Sz.hong@f5.com } 3401183Svbart@nginx.com 3411960Sz.hong@f5.com if (ret == 0) { 3421961Sz.hong@f5.com nxt_http_static_next(task, r, ctx, NXT_HTTP_FORBIDDEN); 3431961Sz.hong@f5.com return; 3441960Sz.hong@f5.com } 3451960Sz.hong@f5.com } 3461960Sz.hong@f5.com 3471960Sz.hong@f5.com fname = ctx->share.start; 3481960Sz.hong@f5.com } 3491183Svbart@nginx.com 3501855Sz.hong@f5.com nxt_memzero(&file, sizeof(nxt_file_t)); 3511855Sz.hong@f5.com 3521855Sz.hong@f5.com file.name = fname; 3531855Sz.hong@f5.com 3541959Sz.hong@f5.com #if (NXT_HAVE_OPENAT2) 3551959Sz.hong@f5.com if (conf->resolve != 0 || ctx->chroot.length > 0) { 3561961Sz.hong@f5.com nxt_str_t *chr; 3571961Sz.hong@f5.com nxt_uint_t resolve; 3581961Sz.hong@f5.com nxt_http_static_share_t *share; 3591961Sz.hong@f5.com 3601961Sz.hong@f5.com share = &conf->shares[ctx->index]; 3611855Sz.hong@f5.com 3621959Sz.hong@f5.com resolve = conf->resolve; 3631959Sz.hong@f5.com chr = &ctx->chroot; 3641855Sz.hong@f5.com 3651959Sz.hong@f5.com if (chr->length > 0) { 3661959Sz.hong@f5.com resolve |= RESOLVE_IN_ROOT; 3671855Sz.hong@f5.com 3681961Sz.hong@f5.com fname = share->is_const 3691961Sz.hong@f5.com ? share->fname 3701960Sz.hong@f5.com : nxt_http_static_chroot_match(chr->start, file.name); 3711959Sz.hong@f5.com 3721959Sz.hong@f5.com if (fname != NULL) { 3731959Sz.hong@f5.com file.name = chr->start; 3741855Sz.hong@f5.com ret = nxt_file_open(task, &file, NXT_FILE_SEARCH, NXT_FILE_OPEN, 3751855Sz.hong@f5.com 0); 3761855Sz.hong@f5.com 3771855Sz.hong@f5.com } else { 3781855Sz.hong@f5.com file.error = NXT_EACCES; 3791855Sz.hong@f5.com ret = NXT_ERROR; 3801855Sz.hong@f5.com } 3811855Sz.hong@f5.com 3821855Sz.hong@f5.com } else if (fname[0] == '/') { 3831855Sz.hong@f5.com file.name = (u_char *) "/"; 3841855Sz.hong@f5.com ret = nxt_file_open(task, &file, NXT_FILE_SEARCH, NXT_FILE_OPEN, 0); 3851855Sz.hong@f5.com 3861855Sz.hong@f5.com } else { 3871855Sz.hong@f5.com file.name = (u_char *) "."; 3881855Sz.hong@f5.com file.fd = AT_FDCWD; 3891855Sz.hong@f5.com ret = NXT_OK; 3901855Sz.hong@f5.com } 3911855Sz.hong@f5.com 3921855Sz.hong@f5.com if (nxt_fast_path(ret == NXT_OK)) { 3931856Sz.hong@f5.com nxt_file_t af; 3941856Sz.hong@f5.com 3951855Sz.hong@f5.com af = file; 3961855Sz.hong@f5.com nxt_memzero(&file, sizeof(nxt_file_t)); 3971855Sz.hong@f5.com file.name = fname; 3981855Sz.hong@f5.com 3991855Sz.hong@f5.com ret = nxt_file_openat2(task, &file, NXT_FILE_RDONLY, 4001959Sz.hong@f5.com NXT_FILE_OPEN, 0, af.fd, resolve); 4011855Sz.hong@f5.com 4021855Sz.hong@f5.com if (af.fd != AT_FDCWD) { 4031855Sz.hong@f5.com nxt_file_close(task, &af); 4041855Sz.hong@f5.com } 4051855Sz.hong@f5.com } 4061855Sz.hong@f5.com 4071855Sz.hong@f5.com } else { 4081855Sz.hong@f5.com ret = nxt_file_open(task, &file, NXT_FILE_RDONLY, NXT_FILE_OPEN, 0); 4091855Sz.hong@f5.com } 4101855Sz.hong@f5.com 4111855Sz.hong@f5.com #else 4121855Sz.hong@f5.com ret = nxt_file_open(task, &file, NXT_FILE_RDONLY, NXT_FILE_OPEN, 0); 4131855Sz.hong@f5.com #endif 4141183Svbart@nginx.com 4151183Svbart@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 4161855Sz.hong@f5.com 4171855Sz.hong@f5.com switch (file.error) { 4181183Svbart@nginx.com 4191200Svbart@nginx.com /* 4201200Svbart@nginx.com * For Unix domain sockets "errno" is set to: 4211200Svbart@nginx.com * - ENXIO on Linux; 4221200Svbart@nginx.com * - EOPNOTSUPP on *BSD, MacOSX, and Solaris. 4231200Svbart@nginx.com */ 4241200Svbart@nginx.com 4251183Svbart@nginx.com case NXT_ENOENT: 4261183Svbart@nginx.com case NXT_ENOTDIR: 4271183Svbart@nginx.com case NXT_ENAMETOOLONG: 4281200Svbart@nginx.com #if (NXT_LINUX) 4291200Svbart@nginx.com case NXT_ENXIO: 4301200Svbart@nginx.com #else 4311200Svbart@nginx.com case NXT_EOPNOTSUPP: 4321200Svbart@nginx.com #endif 4331183Svbart@nginx.com level = NXT_LOG_ERR; 4341183Svbart@nginx.com status = NXT_HTTP_NOT_FOUND; 4351183Svbart@nginx.com break; 4361183Svbart@nginx.com 4371183Svbart@nginx.com case NXT_EACCES: 4381855Sz.hong@f5.com #if (NXT_HAVE_OPENAT2) 4391855Sz.hong@f5.com case NXT_ELOOP: 4401855Sz.hong@f5.com case NXT_EXDEV: 4411855Sz.hong@f5.com #endif 4421183Svbart@nginx.com level = NXT_LOG_ERR; 4431183Svbart@nginx.com status = NXT_HTTP_FORBIDDEN; 4441183Svbart@nginx.com break; 4451183Svbart@nginx.com 4461183Svbart@nginx.com default: 4471183Svbart@nginx.com level = NXT_LOG_ALERT; 4481183Svbart@nginx.com status = NXT_HTTP_INTERNAL_SERVER_ERROR; 4491183Svbart@nginx.com break; 4501183Svbart@nginx.com } 4511183Svbart@nginx.com 4521183Svbart@nginx.com if (status != NXT_HTTP_NOT_FOUND) { 4531959Sz.hong@f5.com #if (NXT_HAVE_OPENAT2) 4541959Sz.hong@f5.com nxt_str_t *chr = &ctx->chroot; 4551959Sz.hong@f5.com 4561959Sz.hong@f5.com if (chr->length > 0) { 4571857Sz.hong@f5.com nxt_log(task, level, "opening \"%s\" at \"%V\" failed %E", 4581959Sz.hong@f5.com fname, chr, file.error); 4591855Sz.hong@f5.com 4601855Sz.hong@f5.com } else { 4611857Sz.hong@f5.com nxt_log(task, level, "opening \"%s\" failed %E", 4621855Sz.hong@f5.com fname, file.error); 4631855Sz.hong@f5.com } 4641959Sz.hong@f5.com 4651959Sz.hong@f5.com #else 4661959Sz.hong@f5.com nxt_log(task, level, "opening \"%s\" failed %E", fname, file.error); 4671959Sz.hong@f5.com #endif 4681183Svbart@nginx.com } 4691183Svbart@nginx.com 4701961Sz.hong@f5.com if (level == NXT_LOG_ERR) { 4711961Sz.hong@f5.com nxt_http_static_next(task, r, ctx, status); 4721961Sz.hong@f5.com return; 4731961Sz.hong@f5.com } 4741961Sz.hong@f5.com 4751959Sz.hong@f5.com goto fail; 4761183Svbart@nginx.com } 4771183Svbart@nginx.com 4781855Sz.hong@f5.com f = nxt_mp_get(r->mem_pool, sizeof(nxt_file_t)); 4791855Sz.hong@f5.com if (nxt_slow_path(f == NULL)) { 4801962Svbart@nginx.com nxt_file_close(task, &file); 4811855Sz.hong@f5.com goto fail; 4821855Sz.hong@f5.com } 4831855Sz.hong@f5.com 4841855Sz.hong@f5.com *f = file; 4851855Sz.hong@f5.com 4861183Svbart@nginx.com ret = nxt_file_info(f, &fi); 4871183Svbart@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 4881183Svbart@nginx.com goto fail; 4891183Svbart@nginx.com } 4901183Svbart@nginx.com 4911183Svbart@nginx.com if (nxt_fast_path(nxt_is_file(&fi))) { 4921183Svbart@nginx.com r->status = NXT_HTTP_OK; 4931183Svbart@nginx.com r->resp.content_length_n = nxt_file_size(&fi); 4941183Svbart@nginx.com 4951183Svbart@nginx.com field = nxt_list_zero_add(r->resp.fields); 4961183Svbart@nginx.com if (nxt_slow_path(field == NULL)) { 4971183Svbart@nginx.com goto fail; 4981183Svbart@nginx.com } 4991183Svbart@nginx.com 5001183Svbart@nginx.com nxt_http_field_name_set(field, "Last-Modified"); 5011183Svbart@nginx.com 5021183Svbart@nginx.com p = nxt_mp_nget(r->mem_pool, NXT_HTTP_DATE_LEN); 5031183Svbart@nginx.com if (nxt_slow_path(p == NULL)) { 5041183Svbart@nginx.com goto fail; 5051183Svbart@nginx.com } 5061183Svbart@nginx.com 5071183Svbart@nginx.com nxt_localtime(nxt_file_mtime(&fi), &tm); 5081183Svbart@nginx.com 5091183Svbart@nginx.com field->value = p; 5101183Svbart@nginx.com field->value_length = nxt_http_date(p, &tm) - p; 5111183Svbart@nginx.com 5121183Svbart@nginx.com field = nxt_list_zero_add(r->resp.fields); 5131183Svbart@nginx.com if (nxt_slow_path(field == NULL)) { 5141183Svbart@nginx.com goto fail; 5151183Svbart@nginx.com } 5161183Svbart@nginx.com 5171183Svbart@nginx.com nxt_http_field_name_set(field, "ETag"); 5181183Svbart@nginx.com 5191855Sz.hong@f5.com length = NXT_TIME_T_HEXLEN + NXT_OFF_T_HEXLEN + 3; 5201183Svbart@nginx.com 5211855Sz.hong@f5.com p = nxt_mp_nget(r->mem_pool, length); 5221183Svbart@nginx.com if (nxt_slow_path(p == NULL)) { 5231183Svbart@nginx.com goto fail; 5241183Svbart@nginx.com } 5251183Svbart@nginx.com 5261183Svbart@nginx.com field->value = p; 5271855Sz.hong@f5.com field->value_length = nxt_sprintf(p, p + length, "\"%xT-%xO\"", 5281183Svbart@nginx.com nxt_file_mtime(&fi), 5291183Svbart@nginx.com nxt_file_size(&fi)) 5301183Svbart@nginx.com - p; 5311183Svbart@nginx.com 5321923Sz.hong@f5.com if (exten.start == NULL) { 5331960Sz.hong@f5.com nxt_http_static_extract_extension(shr, &exten); 5341183Svbart@nginx.com } 5351183Svbart@nginx.com 5361859So.canty@f5.com if (mtype == NULL) { 5371923Sz.hong@f5.com mtype = nxt_http_static_mtype_get(&rtcf->mtypes_hash, &exten); 5381859So.canty@f5.com } 5391183Svbart@nginx.com 5401883So.canty@f5.com if (mtype->length != 0) { 5411183Svbart@nginx.com field = nxt_list_zero_add(r->resp.fields); 5421183Svbart@nginx.com if (nxt_slow_path(field == NULL)) { 5431183Svbart@nginx.com goto fail; 5441183Svbart@nginx.com } 5451183Svbart@nginx.com 5461183Svbart@nginx.com nxt_http_field_name_set(field, "Content-Type"); 5471183Svbart@nginx.com 5481183Svbart@nginx.com field->value = mtype->start; 5491183Svbart@nginx.com field->value_length = mtype->length; 5501183Svbart@nginx.com } 5511183Svbart@nginx.com 5521959Sz.hong@f5.com if (ctx->need_body && nxt_file_size(&fi) > 0) { 5531183Svbart@nginx.com fb = nxt_mp_zget(r->mem_pool, NXT_BUF_FILE_SIZE); 5541183Svbart@nginx.com if (nxt_slow_path(fb == NULL)) { 5551183Svbart@nginx.com goto fail; 5561183Svbart@nginx.com } 5571183Svbart@nginx.com 5581183Svbart@nginx.com fb->file = f; 5591183Svbart@nginx.com fb->file_end = nxt_file_size(&fi); 5601183Svbart@nginx.com 5611183Svbart@nginx.com r->out = fb; 5621183Svbart@nginx.com 5631183Svbart@nginx.com body_handler = &nxt_http_static_body_handler; 5641183Svbart@nginx.com 5651183Svbart@nginx.com } else { 5661183Svbart@nginx.com nxt_file_close(task, f); 5671183Svbart@nginx.com body_handler = NULL; 5681183Svbart@nginx.com } 5691183Svbart@nginx.com 5701183Svbart@nginx.com } else { 5711183Svbart@nginx.com /* Not a file. */ 5721961Sz.hong@f5.com nxt_file_close(task, f); 5731183Svbart@nginx.com 5741183Svbart@nginx.com if (nxt_slow_path(!nxt_is_dir(&fi))) { 5751961Sz.hong@f5.com nxt_log(task, NXT_LOG_ERR, "\"%FN\" is not a regular file", 5761961Sz.hong@f5.com f->name); 5771378Svbart@nginx.com 5781961Sz.hong@f5.com nxt_http_static_next(task, r, ctx, NXT_HTTP_NOT_FOUND); 5791961Sz.hong@f5.com return; 5801183Svbart@nginx.com } 5811183Svbart@nginx.com 5821198Svbart@nginx.com f = NULL; 5831198Svbart@nginx.com 5841183Svbart@nginx.com r->status = NXT_HTTP_MOVED_PERMANENTLY; 5851183Svbart@nginx.com r->resp.content_length_n = 0; 5861183Svbart@nginx.com 5871183Svbart@nginx.com field = nxt_list_zero_add(r->resp.fields); 5881183Svbart@nginx.com if (nxt_slow_path(field == NULL)) { 5891183Svbart@nginx.com goto fail; 5901183Svbart@nginx.com } 5911183Svbart@nginx.com 5921183Svbart@nginx.com nxt_http_field_name_set(field, "Location"); 5931183Svbart@nginx.com 5941183Svbart@nginx.com encode = nxt_encode_uri(NULL, r->path->start, r->path->length); 5951855Sz.hong@f5.com length = r->path->length + encode * 2 + 1; 5961183Svbart@nginx.com 5971183Svbart@nginx.com if (r->args->length > 0) { 5981855Sz.hong@f5.com length += 1 + r->args->length; 5991183Svbart@nginx.com } 6001183Svbart@nginx.com 6011855Sz.hong@f5.com p = nxt_mp_nget(r->mem_pool, length); 6021183Svbart@nginx.com if (nxt_slow_path(p == NULL)) { 6031183Svbart@nginx.com goto fail; 6041183Svbart@nginx.com } 6051183Svbart@nginx.com 6061183Svbart@nginx.com field->value = p; 6071855Sz.hong@f5.com field->value_length = length; 6081183Svbart@nginx.com 6091183Svbart@nginx.com if (encode > 0) { 6101183Svbart@nginx.com p = (u_char *) nxt_encode_uri(p, r->path->start, r->path->length); 6111183Svbart@nginx.com 6121183Svbart@nginx.com } else { 6131183Svbart@nginx.com p = nxt_cpymem(p, r->path->start, r->path->length); 6141183Svbart@nginx.com } 6151183Svbart@nginx.com 6161183Svbart@nginx.com *p++ = '/'; 6171183Svbart@nginx.com 6181183Svbart@nginx.com if (r->args->length > 0) { 6191183Svbart@nginx.com *p++ = '?'; 6201183Svbart@nginx.com nxt_memcpy(p, r->args->start, r->args->length); 6211183Svbart@nginx.com } 6221183Svbart@nginx.com 6231183Svbart@nginx.com body_handler = NULL; 6241183Svbart@nginx.com } 6251183Svbart@nginx.com 6261270Sigor@sysoev.ru nxt_http_request_header_send(task, r, body_handler, NULL); 6271183Svbart@nginx.com 6281183Svbart@nginx.com r->state = &nxt_http_static_send_state; 6291959Sz.hong@f5.com return; 6301183Svbart@nginx.com 6311183Svbart@nginx.com fail: 6321183Svbart@nginx.com 6331855Sz.hong@f5.com if (f != NULL) { 6341183Svbart@nginx.com nxt_file_close(task, f); 6351183Svbart@nginx.com } 6361183Svbart@nginx.com 6371961Sz.hong@f5.com nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); 6381959Sz.hong@f5.com } 6391959Sz.hong@f5.com 6401959Sz.hong@f5.com 6411959Sz.hong@f5.com static void 6421959Sz.hong@f5.com nxt_http_static_var_error(nxt_task_t *task, void *obj, void *data) 6431959Sz.hong@f5.com { 6441959Sz.hong@f5.com nxt_http_request_t *r; 6451959Sz.hong@f5.com 6461959Sz.hong@f5.com r = obj; 6471959Sz.hong@f5.com 6481959Sz.hong@f5.com nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR); 6491183Svbart@nginx.com } 6501183Svbart@nginx.com 6511183Svbart@nginx.com 6521961Sz.hong@f5.com static void 6531961Sz.hong@f5.com nxt_http_static_next(nxt_task_t *task, nxt_http_request_t *r, 6541961Sz.hong@f5.com nxt_http_static_ctx_t *ctx, nxt_http_status_t status) 6551961Sz.hong@f5.com { 6561961Sz.hong@f5.com nxt_http_action_t *action; 6571961Sz.hong@f5.com nxt_http_static_conf_t *conf; 6581961Sz.hong@f5.com 6591961Sz.hong@f5.com action = ctx->action; 6601961Sz.hong@f5.com conf = action->u.conf; 6611961Sz.hong@f5.com 6621961Sz.hong@f5.com ctx->index++; 6631961Sz.hong@f5.com 6641961Sz.hong@f5.com if (ctx->index < conf->nshares) { 6651961Sz.hong@f5.com nxt_http_static_iterate(task, r, ctx); 6661961Sz.hong@f5.com return; 6671961Sz.hong@f5.com } 6681961Sz.hong@f5.com 6691961Sz.hong@f5.com if (action->fallback != NULL) { 6701961Sz.hong@f5.com nxt_http_request_action(task, r, action->fallback); 6711961Sz.hong@f5.com return; 6721961Sz.hong@f5.com } 6731961Sz.hong@f5.com 6741961Sz.hong@f5.com nxt_http_request_error(task, r, status); 6751961Sz.hong@f5.com } 6761961Sz.hong@f5.com 6771961Sz.hong@f5.com 6781959Sz.hong@f5.com #if (NXT_HAVE_OPENAT2) 6791959Sz.hong@f5.com 6801959Sz.hong@f5.com static u_char * 6811959Sz.hong@f5.com nxt_http_static_chroot_match(u_char *chr, u_char *shr) 6821959Sz.hong@f5.com { 6831959Sz.hong@f5.com if (*chr != *shr) { 6841959Sz.hong@f5.com return NULL; 6851959Sz.hong@f5.com } 6861959Sz.hong@f5.com 6871959Sz.hong@f5.com chr++; 6881959Sz.hong@f5.com shr++; 6891959Sz.hong@f5.com 6901959Sz.hong@f5.com for ( ;; ) { 6911959Sz.hong@f5.com if (*shr == '\0') { 6921959Sz.hong@f5.com return NULL; 6931959Sz.hong@f5.com } 6941959Sz.hong@f5.com 6951959Sz.hong@f5.com if (*chr == *shr) { 6961959Sz.hong@f5.com chr++; 6971959Sz.hong@f5.com shr++; 6981959Sz.hong@f5.com continue; 6991959Sz.hong@f5.com } 7001959Sz.hong@f5.com 7011959Sz.hong@f5.com if (*chr == '\0') { 7021959Sz.hong@f5.com break; 7031959Sz.hong@f5.com } 7041959Sz.hong@f5.com 7051959Sz.hong@f5.com if (*chr == '/') { 7061959Sz.hong@f5.com if (chr[-1] == '/') { 7071959Sz.hong@f5.com chr++; 7081959Sz.hong@f5.com continue; 7091959Sz.hong@f5.com } 7101959Sz.hong@f5.com 7111959Sz.hong@f5.com } else if (*shr == '/') { 7121959Sz.hong@f5.com if (shr[-1] == '/') { 7131959Sz.hong@f5.com shr++; 7141959Sz.hong@f5.com continue; 7151959Sz.hong@f5.com } 7161959Sz.hong@f5.com } 7171959Sz.hong@f5.com 7181959Sz.hong@f5.com return NULL; 7191959Sz.hong@f5.com } 7201959Sz.hong@f5.com 7211959Sz.hong@f5.com if (shr[-1] != '/' && *shr != '/') { 7221959Sz.hong@f5.com return NULL; 7231959Sz.hong@f5.com } 7241959Sz.hong@f5.com 7251959Sz.hong@f5.com while (*shr == '/') { 7261959Sz.hong@f5.com shr++; 7271959Sz.hong@f5.com } 7281959Sz.hong@f5.com 7291959Sz.hong@f5.com return (*shr != '\0') ? shr : NULL; 7301959Sz.hong@f5.com } 7311959Sz.hong@f5.com 7321959Sz.hong@f5.com #endif 7331959Sz.hong@f5.com 7341959Sz.hong@f5.com 7351183Svbart@nginx.com static void 7361923Sz.hong@f5.com nxt_http_static_extract_extension(nxt_str_t *path, nxt_str_t *exten) 7371183Svbart@nginx.com { 7381183Svbart@nginx.com u_char ch, *p, *end; 7391183Svbart@nginx.com 7401183Svbart@nginx.com end = path->start + path->length; 7411183Svbart@nginx.com p = end; 7421183Svbart@nginx.com 7431183Svbart@nginx.com for ( ;; ) { 7441183Svbart@nginx.com /* There's always '/' in the beginning of the request path. */ 7451183Svbart@nginx.com 7461183Svbart@nginx.com p--; 7471183Svbart@nginx.com ch = *p; 7481183Svbart@nginx.com 7491183Svbart@nginx.com switch (ch) { 7501183Svbart@nginx.com case '/': 7511183Svbart@nginx.com p++; 7521183Svbart@nginx.com /* Fall through. */ 7531183Svbart@nginx.com case '.': 7541923Sz.hong@f5.com exten->length = end - p; 7551923Sz.hong@f5.com exten->start = p; 7561183Svbart@nginx.com return; 7571183Svbart@nginx.com } 7581183Svbart@nginx.com } 7591183Svbart@nginx.com } 7601183Svbart@nginx.com 7611183Svbart@nginx.com 7621183Svbart@nginx.com static void 7631183Svbart@nginx.com nxt_http_static_body_handler(nxt_task_t *task, void *obj, void *data) 7641183Svbart@nginx.com { 7651183Svbart@nginx.com size_t alloc; 7661183Svbart@nginx.com nxt_buf_t *fb, *b, **next, *out; 7671183Svbart@nginx.com nxt_off_t rest; 7681183Svbart@nginx.com nxt_int_t n; 7691183Svbart@nginx.com nxt_work_queue_t *wq; 7701183Svbart@nginx.com nxt_http_request_t *r; 7711183Svbart@nginx.com 7721183Svbart@nginx.com r = obj; 7731183Svbart@nginx.com fb = r->out; 7741183Svbart@nginx.com 7751183Svbart@nginx.com rest = fb->file_end - fb->file_pos; 7761183Svbart@nginx.com out = NULL; 7771183Svbart@nginx.com next = &out; 7781183Svbart@nginx.com n = 0; 7791183Svbart@nginx.com 7801183Svbart@nginx.com do { 7811183Svbart@nginx.com alloc = nxt_min(rest, NXT_HTTP_STATIC_BUF_SIZE); 7821183Svbart@nginx.com 7831183Svbart@nginx.com b = nxt_buf_mem_alloc(r->mem_pool, alloc, 0); 7841183Svbart@nginx.com if (nxt_slow_path(b == NULL)) { 7851183Svbart@nginx.com goto fail; 7861183Svbart@nginx.com } 7871183Svbart@nginx.com 7881183Svbart@nginx.com b->completion_handler = nxt_http_static_buf_completion; 7891183Svbart@nginx.com b->parent = r; 7901183Svbart@nginx.com 7911183Svbart@nginx.com nxt_mp_retain(r->mem_pool); 7921183Svbart@nginx.com 7931183Svbart@nginx.com *next = b; 7941183Svbart@nginx.com next = &b->next; 7951183Svbart@nginx.com 7961183Svbart@nginx.com rest -= alloc; 7971183Svbart@nginx.com 7981183Svbart@nginx.com } while (rest > 0 && ++n < NXT_HTTP_STATIC_BUF_COUNT); 7991183Svbart@nginx.com 8001183Svbart@nginx.com wq = &task->thread->engine->fast_work_queue; 8011183Svbart@nginx.com 8021183Svbart@nginx.com nxt_sendbuf_drain(task, wq, out); 8031183Svbart@nginx.com return; 8041183Svbart@nginx.com 8051183Svbart@nginx.com fail: 8061183Svbart@nginx.com 8071183Svbart@nginx.com while (out != NULL) { 8081183Svbart@nginx.com b = out; 8091183Svbart@nginx.com out = b->next; 8101183Svbart@nginx.com 8111183Svbart@nginx.com nxt_mp_free(r->mem_pool, b); 8121183Svbart@nginx.com nxt_mp_release(r->mem_pool); 8131183Svbart@nginx.com } 8141183Svbart@nginx.com } 8151183Svbart@nginx.com 8161183Svbart@nginx.com 8171183Svbart@nginx.com static const nxt_http_request_state_t nxt_http_static_send_state 8181183Svbart@nginx.com nxt_aligned(64) = 8191183Svbart@nginx.com { 8201183Svbart@nginx.com .error_handler = nxt_http_request_error_handler, 8211183Svbart@nginx.com }; 8221183Svbart@nginx.com 8231183Svbart@nginx.com 8241183Svbart@nginx.com static void 8251183Svbart@nginx.com nxt_http_static_buf_completion(nxt_task_t *task, void *obj, void *data) 8261183Svbart@nginx.com { 8271183Svbart@nginx.com ssize_t n, size; 8281760Smax.romanov@nginx.com nxt_buf_t *b, *fb, *next; 8291183Svbart@nginx.com nxt_off_t rest; 8301183Svbart@nginx.com nxt_http_request_t *r; 8311183Svbart@nginx.com 8321183Svbart@nginx.com b = obj; 8331183Svbart@nginx.com r = data; 8341760Smax.romanov@nginx.com 8351760Smax.romanov@nginx.com complete_buf: 8361760Smax.romanov@nginx.com 8371183Svbart@nginx.com fb = r->out; 8381183Svbart@nginx.com 8391183Svbart@nginx.com if (nxt_slow_path(fb == NULL || r->error)) { 8401183Svbart@nginx.com goto clean; 8411183Svbart@nginx.com } 8421183Svbart@nginx.com 8431183Svbart@nginx.com rest = fb->file_end - fb->file_pos; 8441183Svbart@nginx.com size = nxt_buf_mem_size(&b->mem); 8451183Svbart@nginx.com 8461183Svbart@nginx.com size = nxt_min(rest, (nxt_off_t) size); 8471183Svbart@nginx.com 8481183Svbart@nginx.com n = nxt_file_read(fb->file, b->mem.start, size, fb->file_pos); 8491183Svbart@nginx.com 8501183Svbart@nginx.com if (n != size) { 8511183Svbart@nginx.com if (n >= 0) { 8521183Svbart@nginx.com nxt_log(task, NXT_LOG_ERR, "file \"%FN\" has changed " 8531183Svbart@nginx.com "while sending response to a client", fb->file->name); 8541183Svbart@nginx.com } 8551183Svbart@nginx.com 8561183Svbart@nginx.com nxt_http_request_error_handler(task, r, r->proto.any); 8571183Svbart@nginx.com goto clean; 8581183Svbart@nginx.com } 8591183Svbart@nginx.com 8601760Smax.romanov@nginx.com next = b->next; 8611760Smax.romanov@nginx.com 8621183Svbart@nginx.com if (n == rest) { 8631183Svbart@nginx.com nxt_file_close(task, fb->file); 8641183Svbart@nginx.com r->out = NULL; 8651183Svbart@nginx.com 8661183Svbart@nginx.com b->next = nxt_http_buf_last(r); 8671183Svbart@nginx.com 8681183Svbart@nginx.com } else { 8691183Svbart@nginx.com fb->file_pos += n; 8701183Svbart@nginx.com b->next = NULL; 8711183Svbart@nginx.com } 8721183Svbart@nginx.com 8731183Svbart@nginx.com b->mem.pos = b->mem.start; 8741183Svbart@nginx.com b->mem.free = b->mem.pos + n; 8751183Svbart@nginx.com 8761183Svbart@nginx.com nxt_http_request_send(task, r, b); 8771760Smax.romanov@nginx.com 8781760Smax.romanov@nginx.com if (next != NULL) { 8791760Smax.romanov@nginx.com b = next; 8801760Smax.romanov@nginx.com goto complete_buf; 8811760Smax.romanov@nginx.com } 8821760Smax.romanov@nginx.com 8831183Svbart@nginx.com return; 8841183Svbart@nginx.com 8851183Svbart@nginx.com clean: 8861183Svbart@nginx.com 8871760Smax.romanov@nginx.com do { 8881760Smax.romanov@nginx.com next = b->next; 8891760Smax.romanov@nginx.com 8901760Smax.romanov@nginx.com nxt_mp_free(r->mem_pool, b); 8911760Smax.romanov@nginx.com nxt_mp_release(r->mem_pool); 8921760Smax.romanov@nginx.com 8931760Smax.romanov@nginx.com b = next; 8941760Smax.romanov@nginx.com } while (b != NULL); 8951183Svbart@nginx.com 8961183Svbart@nginx.com if (fb != NULL) { 8971183Svbart@nginx.com nxt_file_close(task, fb->file); 8981183Svbart@nginx.com r->out = NULL; 8991183Svbart@nginx.com } 9001183Svbart@nginx.com } 9011183Svbart@nginx.com 9021183Svbart@nginx.com 9031183Svbart@nginx.com nxt_int_t 9041183Svbart@nginx.com nxt_http_static_mtypes_init(nxt_mp_t *mp, nxt_lvlhsh_t *hash) 9051183Svbart@nginx.com { 9061923Sz.hong@f5.com nxt_str_t *type, exten; 9071183Svbart@nginx.com nxt_int_t ret; 9081183Svbart@nginx.com nxt_uint_t i; 9091183Svbart@nginx.com 9101183Svbart@nginx.com static const struct { 9111183Svbart@nginx.com nxt_str_t type; 9121923Sz.hong@f5.com const char *exten; 9131183Svbart@nginx.com } default_types[] = { 9141183Svbart@nginx.com 9151183Svbart@nginx.com { nxt_string("text/html"), ".html" }, 9161183Svbart@nginx.com { nxt_string("text/html"), ".htm" }, 9171183Svbart@nginx.com { nxt_string("text/css"), ".css" }, 9181183Svbart@nginx.com 9191183Svbart@nginx.com { nxt_string("image/svg+xml"), ".svg" }, 9201183Svbart@nginx.com { nxt_string("image/webp"), ".webp" }, 9211183Svbart@nginx.com { nxt_string("image/png"), ".png" }, 9221617Svbart@nginx.com { nxt_string("image/apng"), ".apng" }, 9231183Svbart@nginx.com { nxt_string("image/jpeg"), ".jpeg" }, 9241183Svbart@nginx.com { nxt_string("image/jpeg"), ".jpg" }, 9251183Svbart@nginx.com { nxt_string("image/gif"), ".gif" }, 9261183Svbart@nginx.com { nxt_string("image/x-icon"), ".ico" }, 9271183Svbart@nginx.com 9281617Svbart@nginx.com { nxt_string("image/avif"), ".avif" }, 9291617Svbart@nginx.com { nxt_string("image/avif-sequence"), ".avifs" }, 9301617Svbart@nginx.com 9311183Svbart@nginx.com { nxt_string("font/woff"), ".woff" }, 9321183Svbart@nginx.com { nxt_string("font/woff2"), ".woff2" }, 9331183Svbart@nginx.com { nxt_string("font/otf"), ".otf" }, 9341183Svbart@nginx.com { nxt_string("font/ttf"), ".ttf" }, 9351183Svbart@nginx.com 9361183Svbart@nginx.com { nxt_string("text/plain"), ".txt" }, 9371183Svbart@nginx.com { nxt_string("text/markdown"), ".md" }, 9381183Svbart@nginx.com { nxt_string("text/x-rst"), ".rst" }, 9391183Svbart@nginx.com 9401183Svbart@nginx.com { nxt_string("application/javascript"), ".js" }, 9411183Svbart@nginx.com { nxt_string("application/json"), ".json" }, 9421183Svbart@nginx.com { nxt_string("application/xml"), ".xml" }, 9431183Svbart@nginx.com { nxt_string("application/rss+xml"), ".rss" }, 9441183Svbart@nginx.com { nxt_string("application/atom+xml"), ".atom" }, 9451183Svbart@nginx.com { nxt_string("application/pdf"), ".pdf" }, 9461183Svbart@nginx.com 9471183Svbart@nginx.com { nxt_string("application/zip"), ".zip" }, 9481183Svbart@nginx.com 9491183Svbart@nginx.com { nxt_string("audio/mpeg"), ".mp3" }, 9501183Svbart@nginx.com { nxt_string("audio/ogg"), ".ogg" }, 9511183Svbart@nginx.com { nxt_string("audio/midi"), ".midi" }, 9521183Svbart@nginx.com { nxt_string("audio/midi"), ".mid" }, 9531183Svbart@nginx.com { nxt_string("audio/flac"), ".flac" }, 9541183Svbart@nginx.com { nxt_string("audio/aac"), ".aac" }, 9551183Svbart@nginx.com { nxt_string("audio/wav"), ".wav" }, 9561183Svbart@nginx.com 9571183Svbart@nginx.com { nxt_string("video/mpeg"), ".mpeg" }, 9581183Svbart@nginx.com { nxt_string("video/mpeg"), ".mpg" }, 9591183Svbart@nginx.com { nxt_string("video/mp4"), ".mp4" }, 9601183Svbart@nginx.com { nxt_string("video/webm"), ".webm" }, 9611183Svbart@nginx.com { nxt_string("video/x-msvideo"), ".avi" }, 9621183Svbart@nginx.com 9631183Svbart@nginx.com { nxt_string("application/octet-stream"), ".exe" }, 9641183Svbart@nginx.com { nxt_string("application/octet-stream"), ".bin" }, 9651183Svbart@nginx.com { nxt_string("application/octet-stream"), ".dll" }, 9661183Svbart@nginx.com { nxt_string("application/octet-stream"), ".iso" }, 9671183Svbart@nginx.com { nxt_string("application/octet-stream"), ".img" }, 9681183Svbart@nginx.com { nxt_string("application/octet-stream"), ".msi" }, 9691183Svbart@nginx.com 9701183Svbart@nginx.com { nxt_string("application/octet-stream"), ".deb" }, 9711183Svbart@nginx.com { nxt_string("application/octet-stream"), ".rpm" }, 9721882So.canty@f5.com 9731882So.canty@f5.com { nxt_string("application/x-httpd-php"), ".php" }, 9741183Svbart@nginx.com }; 9751183Svbart@nginx.com 9761183Svbart@nginx.com for (i = 0; i < nxt_nitems(default_types); i++) { 9771183Svbart@nginx.com type = (nxt_str_t *) &default_types[i].type; 9781183Svbart@nginx.com 9791923Sz.hong@f5.com exten.start = (u_char *) default_types[i].exten; 9801923Sz.hong@f5.com exten.length = nxt_strlen(exten.start); 9811183Svbart@nginx.com 9821923Sz.hong@f5.com ret = nxt_http_static_mtypes_hash_add(mp, hash, &exten, type); 9831183Svbart@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 9841183Svbart@nginx.com return NXT_ERROR; 9851183Svbart@nginx.com } 9861183Svbart@nginx.com } 9871183Svbart@nginx.com 9881183Svbart@nginx.com return NXT_OK; 9891183Svbart@nginx.com } 9901183Svbart@nginx.com 9911183Svbart@nginx.com 9921183Svbart@nginx.com static const nxt_lvlhsh_proto_t nxt_http_static_mtypes_hash_proto 9931183Svbart@nginx.com nxt_aligned(64) = 9941183Svbart@nginx.com { 9951183Svbart@nginx.com NXT_LVLHSH_DEFAULT, 9961183Svbart@nginx.com nxt_http_static_mtypes_hash_test, 9971183Svbart@nginx.com nxt_http_static_mtypes_hash_alloc, 9981183Svbart@nginx.com nxt_http_static_mtypes_hash_free, 9991183Svbart@nginx.com }; 10001183Svbart@nginx.com 10011183Svbart@nginx.com 10021183Svbart@nginx.com typedef struct { 10031923Sz.hong@f5.com nxt_str_t exten; 10041183Svbart@nginx.com nxt_str_t *type; 10051183Svbart@nginx.com } nxt_http_static_mtype_t; 10061183Svbart@nginx.com 10071183Svbart@nginx.com 10081183Svbart@nginx.com nxt_int_t 10091183Svbart@nginx.com nxt_http_static_mtypes_hash_add(nxt_mp_t *mp, nxt_lvlhsh_t *hash, 10101923Sz.hong@f5.com nxt_str_t *exten, nxt_str_t *type) 10111183Svbart@nginx.com { 10121183Svbart@nginx.com nxt_lvlhsh_query_t lhq; 10131183Svbart@nginx.com nxt_http_static_mtype_t *mtype; 10141183Svbart@nginx.com 10151183Svbart@nginx.com mtype = nxt_mp_get(mp, sizeof(nxt_http_static_mtype_t)); 10161183Svbart@nginx.com if (nxt_slow_path(mtype == NULL)) { 10171183Svbart@nginx.com return NXT_ERROR; 10181183Svbart@nginx.com } 10191183Svbart@nginx.com 10201923Sz.hong@f5.com mtype->exten = *exten; 10211183Svbart@nginx.com mtype->type = type; 10221183Svbart@nginx.com 10231923Sz.hong@f5.com lhq.key = *exten; 10241183Svbart@nginx.com lhq.key_hash = nxt_djb_hash_lowcase(lhq.key.start, lhq.key.length); 10251183Svbart@nginx.com lhq.replace = 1; 10261183Svbart@nginx.com lhq.value = mtype; 10271183Svbart@nginx.com lhq.proto = &nxt_http_static_mtypes_hash_proto; 10281183Svbart@nginx.com lhq.pool = mp; 10291183Svbart@nginx.com 10301183Svbart@nginx.com return nxt_lvlhsh_insert(hash, &lhq); 10311183Svbart@nginx.com } 10321183Svbart@nginx.com 10331183Svbart@nginx.com 10341183Svbart@nginx.com nxt_str_t * 10351923Sz.hong@f5.com nxt_http_static_mtype_get(nxt_lvlhsh_t *hash, nxt_str_t *exten) 10361183Svbart@nginx.com { 10371183Svbart@nginx.com nxt_lvlhsh_query_t lhq; 10381183Svbart@nginx.com nxt_http_static_mtype_t *mtype; 10391183Svbart@nginx.com 10401883So.canty@f5.com static nxt_str_t empty = nxt_string(""); 10411883So.canty@f5.com 10421923Sz.hong@f5.com lhq.key = *exten; 10431183Svbart@nginx.com lhq.key_hash = nxt_djb_hash_lowcase(lhq.key.start, lhq.key.length); 10441183Svbart@nginx.com lhq.proto = &nxt_http_static_mtypes_hash_proto; 10451183Svbart@nginx.com 10461183Svbart@nginx.com if (nxt_lvlhsh_find(hash, &lhq) == NXT_OK) { 10471183Svbart@nginx.com mtype = lhq.value; 10481183Svbart@nginx.com return mtype->type; 10491183Svbart@nginx.com } 10501183Svbart@nginx.com 10511883So.canty@f5.com return ∅ 10521183Svbart@nginx.com } 10531183Svbart@nginx.com 10541183Svbart@nginx.com 10551183Svbart@nginx.com static nxt_int_t 10561183Svbart@nginx.com nxt_http_static_mtypes_hash_test(nxt_lvlhsh_query_t *lhq, void *data) 10571183Svbart@nginx.com { 10581183Svbart@nginx.com nxt_http_static_mtype_t *mtype; 10591183Svbart@nginx.com 10601183Svbart@nginx.com mtype = data; 10611183Svbart@nginx.com 10621923Sz.hong@f5.com return nxt_strcasestr_eq(&lhq->key, &mtype->exten) ? NXT_OK : NXT_DECLINED; 10631183Svbart@nginx.com } 10641183Svbart@nginx.com 10651183Svbart@nginx.com 10661183Svbart@nginx.com static void * 10671183Svbart@nginx.com nxt_http_static_mtypes_hash_alloc(void *data, size_t size) 10681183Svbart@nginx.com { 10691183Svbart@nginx.com return nxt_mp_align(data, size, size); 10701183Svbart@nginx.com } 10711183Svbart@nginx.com 10721183Svbart@nginx.com 10731183Svbart@nginx.com static void 10741183Svbart@nginx.com nxt_http_static_mtypes_hash_free(void *data, void *p) 10751183Svbart@nginx.com { 10761183Svbart@nginx.com nxt_mp_free(data, p); 10771183Svbart@nginx.com } 1078