summaryrefslogtreecommitdiffhomepage
path: root/src/nxt_http_static.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/nxt_http_static.c219
1 files changed, 157 insertions, 62 deletions
diff --git a/src/nxt_http_static.c b/src/nxt_http_static.c
index c8b73fac..9b79a666 100644
--- a/src/nxt_http_static.c
+++ b/src/nxt_http_static.c
@@ -7,12 +7,22 @@
#include <nxt_http.h>
+typedef struct {
+ nxt_str_t share;
+ nxt_str_t chroot;
+ nxt_uint_t resolve;
+ nxt_http_route_rule_t *types;
+} nxt_http_static_conf_t;
+
+
#define NXT_HTTP_STATIC_BUF_COUNT 2
#define NXT_HTTP_STATIC_BUF_SIZE (128 * 1024)
+static nxt_http_action_t *nxt_http_static(nxt_task_t *task,
+ nxt_http_request_t *r, nxt_http_action_t *action);
static void nxt_http_static_extract_extension(nxt_str_t *path,
- nxt_str_t *extension);
+ nxt_str_t *exten);
static void nxt_http_static_body_handler(nxt_task_t *task, void *obj,
void *data);
static void nxt_http_static_buf_completion(nxt_task_t *task, void *obj,
@@ -27,30 +37,122 @@ static void nxt_http_static_mtypes_hash_free(void *data, void *p);
static const nxt_http_request_state_t nxt_http_static_send_state;
-nxt_http_action_t *
-nxt_http_static_handler(nxt_task_t *task, nxt_http_request_t *r,
+nxt_int_t
+nxt_http_static_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
+ nxt_http_action_t *action, nxt_http_action_conf_t *acf)
+{
+ nxt_mp_t *mp;
+ nxt_str_t *str, value;
+ nxt_http_static_conf_t *conf;
+
+ mp = tmcf->router_conf->mem_pool;
+
+ conf = nxt_mp_zget(mp, sizeof(nxt_http_static_conf_t));
+ if (nxt_slow_path(conf == NULL)) {
+ return NXT_ERROR;
+ }
+
+ action->handler = nxt_http_static;
+ action->u.conf = conf;
+
+ nxt_conf_get_string(acf->share, &value);
+
+ str = nxt_str_dup(mp, &conf->share, &value);
+ if (nxt_slow_path(str == NULL)) {
+ return NXT_ERROR;
+ }
+
+#if (NXT_HAVE_OPENAT2)
+ if (acf->chroot.length > 0) {
+ u_char *p;
+ nxt_str_t slash;
+
+ if (acf->chroot.start[acf->chroot.length - 1] != '/') {
+ nxt_str_set(&slash, "/");
+
+ } else {
+ nxt_str_set(&slash, "");
+ }
+
+ value.length = acf->chroot.length + slash.length;
+
+ value.start = nxt_mp_alloc(mp, value.length + 1);
+ if (nxt_slow_path(value.start == NULL)) {
+ return NXT_ERROR;
+ }
+
+ p = value.start;
+ p = nxt_cpymem(p, acf->chroot.start, acf->chroot.length);
+ p = nxt_cpymem(p, slash.start, slash.length);
+ *p = '\0';
+
+ conf->chroot = value;
+ conf->resolve |= RESOLVE_IN_ROOT;
+ }
+
+ if (acf->follow_symlinks != NULL
+ && !nxt_conf_get_boolean(acf->follow_symlinks))
+ {
+ conf->resolve |= RESOLVE_NO_SYMLINKS;
+ }
+
+ if (acf->traverse_mounts != NULL
+ && !nxt_conf_get_boolean(acf->traverse_mounts))
+ {
+ conf->resolve |= RESOLVE_NO_XDEV;
+ }
+#endif
+
+ if (acf->types != NULL) {
+ conf->types = nxt_http_route_types_rule_create(task, mp, acf->types);
+ if (nxt_slow_path(conf->types == NULL)) {
+ return NXT_ERROR;
+ }
+ }
+
+ if (acf->fallback != NULL) {
+ action->fallback = nxt_mp_alloc(mp, sizeof(nxt_http_action_t));
+ if (nxt_slow_path(action->fallback == NULL)) {
+ return NXT_ERROR;
+ }
+
+ return nxt_http_action_init(task, tmcf, acf->fallback,
+ action->fallback);
+ }
+
+ return NXT_OK;
+}
+
+
+static nxt_http_action_t *
+nxt_http_static(nxt_task_t *task, nxt_http_request_t *r,
nxt_http_action_t *action)
{
- size_t length, encode;
- u_char *p, *fname;
- struct tm tm;
- nxt_buf_t *fb;
- nxt_int_t ret;
- nxt_str_t index, extension, *mtype, *chroot;
- nxt_uint_t level;
- nxt_bool_t need_body;
- nxt_file_t *f, file;
- nxt_file_info_t fi;
- nxt_http_field_t *field;
- nxt_http_status_t status;
- nxt_router_conf_t *rtcf;
- nxt_work_handler_t body_handler;
+ size_t length, encode;
+ u_char *p, *fname;
+ struct tm tm;
+ nxt_buf_t *fb;
+ nxt_int_t ret;
+ nxt_str_t index, exten, *mtype, *chroot;
+ nxt_uint_t level;
+ nxt_bool_t need_body;
+ nxt_file_t *f, file;
+ nxt_file_info_t fi;
+ nxt_http_field_t *field;
+ nxt_http_status_t status;
+ nxt_router_conf_t *rtcf;
+ nxt_work_handler_t body_handler;
+ nxt_http_static_conf_t *conf;
+
+ conf = action->u.conf;
+
+ nxt_debug(task, "http static: \"%V\"", &conf->share);
if (nxt_slow_path(!nxt_str_eq(r->method, "GET", 3))) {
if (!nxt_str_eq(r->method, "HEAD", 4)) {
- if (action->u.share.fallback != NULL) {
- return action->u.share.fallback;
+ if (action->fallback != NULL) {
+ return action->fallback;
}
nxt_http_request_error(task, r, NXT_HTTP_METHOD_NOT_ALLOWED);
@@ -66,11 +168,11 @@ nxt_http_static_handler(nxt_task_t *task, nxt_http_request_t *r,
if (r->path->start[r->path->length - 1] == '/') {
/* TODO: dynamic index setting. */
nxt_str_set(&index, "index.html");
- nxt_str_set(&extension, ".html");
+ nxt_str_set(&exten, ".html");
} else {
nxt_str_set(&index, "");
- nxt_str_null(&extension);
+ nxt_str_null(&exten);
}
f = NULL;
@@ -79,20 +181,19 @@ nxt_http_static_handler(nxt_task_t *task, nxt_http_request_t *r,
mtype = NULL;
- if (action->u.share.types != NULL && extension.start == NULL) {
- nxt_http_static_extract_extension(r->path, &extension);
- mtype = nxt_http_static_mtypes_hash_find(&rtcf->mtypes_hash,
- &extension);
+ if (conf->types != NULL && exten.start == NULL) {
+ nxt_http_static_extract_extension(r->path, &exten);
+ mtype = nxt_http_static_mtype_get(&rtcf->mtypes_hash, &exten);
- ret = nxt_http_route_test_rule(r, action->u.share.types,
- mtype->start, mtype->length);
+ ret = nxt_http_route_test_rule(r, conf->types, mtype->start,
+ mtype->length);
if (nxt_slow_path(ret == NXT_ERROR)) {
goto fail;
}
if (ret == 0) {
- if (action->u.share.fallback != NULL) {
- return action->u.share.fallback;
+ if (action->fallback != NULL) {
+ return action->fallback;
}
nxt_http_request_error(task, r, NXT_HTTP_FORBIDDEN);
@@ -100,7 +201,7 @@ nxt_http_static_handler(nxt_task_t *task, nxt_http_request_t *r,
}
}
- length = action->name.length + r->path->length + index.length;
+ length = conf->share.length + r->path->length + index.length;
fname = nxt_mp_nget(r->mem_pool, length + 1);
if (nxt_slow_path(fname == NULL)) {
@@ -108,7 +209,7 @@ nxt_http_static_handler(nxt_task_t *task, nxt_http_request_t *r,
}
p = fname;
- p = nxt_cpymem(p, action->name.start, action->name.length);
+ p = nxt_cpymem(p, conf->share.start, conf->share.length);
p = nxt_cpymem(p, r->path->start, r->path->length);
p = nxt_cpymem(p, index.start, index.length);
*p = '\0';
@@ -117,11 +218,10 @@ nxt_http_static_handler(nxt_task_t *task, nxt_http_request_t *r,
file.name = fname;
- chroot = &action->u.share.chroot;
+ chroot = &conf->chroot;
#if (NXT_HAVE_OPENAT2)
-
- if (action->u.share.resolve != 0) {
+ if (conf->resolve != 0) {
if (chroot->length > 0) {
file.name = chroot->start;
@@ -156,8 +256,7 @@ nxt_http_static_handler(nxt_task_t *task, nxt_http_request_t *r,
file.name = fname;
ret = nxt_file_openat2(task, &file, NXT_FILE_RDONLY,
- NXT_FILE_OPEN, 0, af.fd,
- action->u.share.resolve);
+ NXT_FILE_OPEN, 0, af.fd, conf->resolve);
if (af.fd != AT_FDCWD) {
nxt_file_close(task, &af);
@@ -169,9 +268,7 @@ nxt_http_static_handler(nxt_task_t *task, nxt_http_request_t *r,
}
#else
-
ret = nxt_file_open(task, &file, NXT_FILE_RDONLY, NXT_FILE_OPEN, 0);
-
#endif
if (nxt_slow_path(ret != NXT_OK)) {
@@ -211,8 +308,8 @@ nxt_http_static_handler(nxt_task_t *task, nxt_http_request_t *r,
break;
}
- if (level == NXT_LOG_ERR && action->u.share.fallback != NULL) {
- return action->u.share.fallback;
+ if (level == NXT_LOG_ERR && action->fallback != NULL) {
+ return action->fallback;
}
if (status != NXT_HTTP_NOT_FOUND) {
@@ -283,13 +380,12 @@ nxt_http_static_handler(nxt_task_t *task, nxt_http_request_t *r,
nxt_file_size(&fi))
- p;
- if (extension.start == NULL) {
- nxt_http_static_extract_extension(r->path, &extension);
+ if (exten.start == NULL) {
+ nxt_http_static_extract_extension(r->path, &exten);
}
if (mtype == NULL) {
- mtype = nxt_http_static_mtypes_hash_find(&rtcf->mtypes_hash,
- &extension);
+ mtype = nxt_http_static_mtype_get(&rtcf->mtypes_hash, &exten);
}
if (mtype->length != 0) {
@@ -328,8 +424,8 @@ nxt_http_static_handler(nxt_task_t *task, nxt_http_request_t *r,
nxt_file_close(task, f);
if (nxt_slow_path(!nxt_is_dir(&fi))) {
- if (action->u.share.fallback != NULL) {
- return action->u.share.fallback;
+ if (action->fallback != NULL) {
+ return action->fallback;
}
nxt_log(task, NXT_LOG_ERR, "\"%FN\" is not a regular file",
@@ -401,7 +497,7 @@ fail:
static void
-nxt_http_static_extract_extension(nxt_str_t *path, nxt_str_t *extension)
+nxt_http_static_extract_extension(nxt_str_t *path, nxt_str_t *exten)
{
u_char ch, *p, *end;
@@ -419,8 +515,8 @@ nxt_http_static_extract_extension(nxt_str_t *path, nxt_str_t *extension)
p++;
/* Fall through. */
case '.':
- extension->length = end - p;
- extension->start = p;
+ exten->length = end - p;
+ exten->start = p;
return;
}
}
@@ -571,13 +667,13 @@ clean:
nxt_int_t
nxt_http_static_mtypes_init(nxt_mp_t *mp, nxt_lvlhsh_t *hash)
{
- nxt_str_t *type, extension;
+ nxt_str_t *type, exten;
nxt_int_t ret;
nxt_uint_t i;
static const struct {
nxt_str_t type;
- const char *extension;
+ const char *exten;
} default_types[] = {
{ nxt_string("text/html"), ".html" },
@@ -644,10 +740,10 @@ nxt_http_static_mtypes_init(nxt_mp_t *mp, nxt_lvlhsh_t *hash)
for (i = 0; i < nxt_nitems(default_types); i++) {
type = (nxt_str_t *) &default_types[i].type;
- extension.start = (u_char *) default_types[i].extension;
- extension.length = nxt_strlen(extension.start);
+ exten.start = (u_char *) default_types[i].exten;
+ exten.length = nxt_strlen(exten.start);
- ret = nxt_http_static_mtypes_hash_add(mp, hash, &extension, type);
+ ret = nxt_http_static_mtypes_hash_add(mp, hash, &exten, type);
if (nxt_slow_path(ret != NXT_OK)) {
return NXT_ERROR;
}
@@ -668,14 +764,14 @@ static const nxt_lvlhsh_proto_t nxt_http_static_mtypes_hash_proto
typedef struct {
- nxt_str_t extension;
+ nxt_str_t exten;
nxt_str_t *type;
} nxt_http_static_mtype_t;
nxt_int_t
nxt_http_static_mtypes_hash_add(nxt_mp_t *mp, nxt_lvlhsh_t *hash,
- nxt_str_t *extension, nxt_str_t *type)
+ nxt_str_t *exten, nxt_str_t *type)
{
nxt_lvlhsh_query_t lhq;
nxt_http_static_mtype_t *mtype;
@@ -685,10 +781,10 @@ nxt_http_static_mtypes_hash_add(nxt_mp_t *mp, nxt_lvlhsh_t *hash,
return NXT_ERROR;
}
- mtype->extension = *extension;
+ mtype->exten = *exten;
mtype->type = type;
- lhq.key = *extension;
+ lhq.key = *exten;
lhq.key_hash = nxt_djb_hash_lowcase(lhq.key.start, lhq.key.length);
lhq.replace = 1;
lhq.value = mtype;
@@ -700,14 +796,14 @@ nxt_http_static_mtypes_hash_add(nxt_mp_t *mp, nxt_lvlhsh_t *hash,
nxt_str_t *
-nxt_http_static_mtypes_hash_find(nxt_lvlhsh_t *hash, nxt_str_t *extension)
+nxt_http_static_mtype_get(nxt_lvlhsh_t *hash, nxt_str_t *exten)
{
nxt_lvlhsh_query_t lhq;
nxt_http_static_mtype_t *mtype;
static nxt_str_t empty = nxt_string("");
- lhq.key = *extension;
+ lhq.key = *exten;
lhq.key_hash = nxt_djb_hash_lowcase(lhq.key.start, lhq.key.length);
lhq.proto = &nxt_http_static_mtypes_hash_proto;
@@ -727,8 +823,7 @@ nxt_http_static_mtypes_hash_test(nxt_lvlhsh_query_t *lhq, void *data)
mtype = data;
- return nxt_strcasestr_eq(&lhq->key, &mtype->extension) ? NXT_OK
- : NXT_DECLINED;
+ return nxt_strcasestr_eq(&lhq->key, &mtype->exten) ? NXT_OK : NXT_DECLINED;
}