mirror of
https://github.com/cesanta/mongoose.git
synced 2025-07-26 07:06:15 +08:00
Enhance packed fs serving
This commit is contained in:
parent
3a46055e52
commit
b40b1232cc
29
mongoose.c
29
mongoose.c
@ -433,14 +433,14 @@ const char *mg_unlist(size_t no) {
|
|||||||
|
|
||||||
static char *packed_realpath(const char *path, char *resolved_path) {
|
static char *packed_realpath(const char *path, char *resolved_path) {
|
||||||
if (resolved_path == NULL) resolved_path = (char *) malloc(strlen(path) + 1);
|
if (resolved_path == NULL) resolved_path = (char *) malloc(strlen(path) + 1);
|
||||||
while (*path == '.' || *path == '/') path++;
|
// while (*path == '.' || *path == '/') path++;
|
||||||
strcpy(resolved_path, path);
|
strcpy(resolved_path, path);
|
||||||
return resolved_path;
|
return resolved_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int is_dir_prefix(const char *prefix, size_t n, const char *path) {
|
static int is_dir_prefix(const char *prefix, size_t n, const char *path) {
|
||||||
return n < strlen(path) && memcmp(prefix, path, n) == 0 &&
|
return n < strlen(path) && memcmp(prefix, path, n) == 0 && path[n] == '/';
|
||||||
(n == 0 || path[n] == MG_DIRSEP);
|
//(n == 0 || path[n] == MG_DIRSEP);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int packed_stat(const char *path, size_t *size, time_t *mtime) {
|
static int packed_stat(const char *path, size_t *size, time_t *mtime) {
|
||||||
@ -454,12 +454,24 @@ static int packed_stat(const char *path, size_t *size, time_t *mtime) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void packed_list(const char *path, void (*fn)(const char *, void *),
|
static void packed_list(const char *dir, void (*fn)(const char *, void *),
|
||||||
void *userdata) {
|
void *userdata) {
|
||||||
const char *p;
|
char buf[256], tmp[sizeof(buf)];
|
||||||
size_t i, n = strlen(path);
|
const char *path, *begin, *end;
|
||||||
for (i = 0; (p = mg_unlist(i)) != NULL; i++) {
|
size_t i, n = strlen(dir);
|
||||||
if (is_dir_prefix(path, n, p)) fn(&p[n], userdata);
|
tmp[0] = '\0'; // Previously listed entry
|
||||||
|
for (i = 0; (path = mg_unlist(i)) != NULL; i++) {
|
||||||
|
if (!is_dir_prefix(dir, n, path)) continue;
|
||||||
|
begin = &path[n + 1];
|
||||||
|
end = strchr(begin, '/');
|
||||||
|
if (end == NULL) end = begin + strlen(begin);
|
||||||
|
snprintf(buf, sizeof(buf), "%.*s", (int) (end - begin), begin);
|
||||||
|
buf[sizeof(buf) - 1] = '\0';
|
||||||
|
// If this entry has been already listed, skip
|
||||||
|
// NOTE: we're assuming that file list is sorted alphabetically
|
||||||
|
if (strcmp(buf, tmp) == 0) continue;
|
||||||
|
fn(buf, userdata); // Not yet listed, call user function
|
||||||
|
strcpy(tmp, buf); // And save this entry as listed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1355,6 +1367,7 @@ static void printdirentry(const char *name, void *userdata) {
|
|||||||
char path[MG_PATH_MAX], sz[64], mod[64];
|
char path[MG_PATH_MAX], sz[64], mod[64];
|
||||||
int flags, n = 0;
|
int flags, n = 0;
|
||||||
|
|
||||||
|
// LOG(LL_DEBUG, ("[%s] [%s]", d->dir, name));
|
||||||
if (snprintf(path, sizeof(path), "%s%c%s", d->dir, '/', name) < 0) {
|
if (snprintf(path, sizeof(path), "%s%c%s", d->dir, '/', name) < 0) {
|
||||||
LOG(LL_ERROR, ("%s truncated", name));
|
LOG(LL_ERROR, ("%s truncated", name));
|
||||||
} else if ((flags = fs->stat(path, &size, &mtime)) == 0) {
|
} else if ((flags = fs->stat(path, &size, &mtime)) == 0) {
|
||||||
|
@ -22,14 +22,14 @@ const char *mg_unlist(size_t no) {
|
|||||||
|
|
||||||
static char *packed_realpath(const char *path, char *resolved_path) {
|
static char *packed_realpath(const char *path, char *resolved_path) {
|
||||||
if (resolved_path == NULL) resolved_path = (char *) malloc(strlen(path) + 1);
|
if (resolved_path == NULL) resolved_path = (char *) malloc(strlen(path) + 1);
|
||||||
while (*path == '.' || *path == '/') path++;
|
// while (*path == '.' || *path == '/') path++;
|
||||||
strcpy(resolved_path, path);
|
strcpy(resolved_path, path);
|
||||||
return resolved_path;
|
return resolved_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int is_dir_prefix(const char *prefix, size_t n, const char *path) {
|
static int is_dir_prefix(const char *prefix, size_t n, const char *path) {
|
||||||
return n < strlen(path) && memcmp(prefix, path, n) == 0 &&
|
return n < strlen(path) && memcmp(prefix, path, n) == 0 && path[n] == '/';
|
||||||
(n == 0 || path[n] == MG_DIRSEP);
|
//(n == 0 || path[n] == MG_DIRSEP);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int packed_stat(const char *path, size_t *size, time_t *mtime) {
|
static int packed_stat(const char *path, size_t *size, time_t *mtime) {
|
||||||
@ -43,12 +43,24 @@ static int packed_stat(const char *path, size_t *size, time_t *mtime) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void packed_list(const char *path, void (*fn)(const char *, void *),
|
static void packed_list(const char *dir, void (*fn)(const char *, void *),
|
||||||
void *userdata) {
|
void *userdata) {
|
||||||
const char *p;
|
char buf[256], tmp[sizeof(buf)];
|
||||||
size_t i, n = strlen(path);
|
const char *path, *begin, *end;
|
||||||
for (i = 0; (p = mg_unlist(i)) != NULL; i++) {
|
size_t i, n = strlen(dir);
|
||||||
if (is_dir_prefix(path, n, p)) fn(&p[n], userdata);
|
tmp[0] = '\0'; // Previously listed entry
|
||||||
|
for (i = 0; (path = mg_unlist(i)) != NULL; i++) {
|
||||||
|
if (!is_dir_prefix(dir, n, path)) continue;
|
||||||
|
begin = &path[n + 1];
|
||||||
|
end = strchr(begin, '/');
|
||||||
|
if (end == NULL) end = begin + strlen(begin);
|
||||||
|
snprintf(buf, sizeof(buf), "%.*s", (int) (end - begin), begin);
|
||||||
|
buf[sizeof(buf) - 1] = '\0';
|
||||||
|
// If this entry has been already listed, skip
|
||||||
|
// NOTE: we're assuming that file list is sorted alphabetically
|
||||||
|
if (strcmp(buf, tmp) == 0) continue;
|
||||||
|
fn(buf, userdata); // Not yet listed, call user function
|
||||||
|
strcpy(tmp, buf); // And save this entry as listed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -596,6 +596,7 @@ static void printdirentry(const char *name, void *userdata) {
|
|||||||
char path[MG_PATH_MAX], sz[64], mod[64];
|
char path[MG_PATH_MAX], sz[64], mod[64];
|
||||||
int flags, n = 0;
|
int flags, n = 0;
|
||||||
|
|
||||||
|
// LOG(LL_DEBUG, ("[%s] [%s]", d->dir, name));
|
||||||
if (snprintf(path, sizeof(path), "%s%c%s", d->dir, '/', name) < 0) {
|
if (snprintf(path, sizeof(path), "%s%c%s", d->dir, '/', name) < 0) {
|
||||||
LOG(LL_ERROR, ("%s truncated", name));
|
LOG(LL_ERROR, ("%s truncated", name));
|
||||||
} else if ((flags = fs->stat(path, &size, &mtime)) == 0) {
|
} else if ((flags = fs->stat(path, &size, &mtime)) == 0) {
|
||||||
|
@ -76,7 +76,7 @@ int main(int argc, char *argv[]) {
|
|||||||
for (i = 1; i < argc; i++) {
|
for (i = 1; i < argc; i++) {
|
||||||
struct stat st;
|
struct stat st;
|
||||||
stat(argv[i], &st);
|
stat(argv[i], &st);
|
||||||
printf(" {\"%s\", v%d, sizeof(v%d), %lu},\n", argv[i], i, i, st.st_mtime);
|
printf(" {\"/%s\", v%d, sizeof(v%d), %lu},\n", argv[i], i, i, st.st_mtime);
|
||||||
}
|
}
|
||||||
printf("%s", " {NULL, NULL, 0, 0}\n");
|
printf("%s", " {NULL, NULL, 0, 0}\n");
|
||||||
printf("%s", "};\n\n");
|
printf("%s", "};\n\n");
|
||||||
|
@ -582,7 +582,6 @@ static void test_http_server(void) {
|
|||||||
// Directory listing
|
// Directory listing
|
||||||
fetch(&mgr, buf, url, "GET /test/ HTTP/1.0\n\n");
|
fetch(&mgr, buf, url, "GET /test/ HTTP/1.0\n\n");
|
||||||
ASSERT(fetch(&mgr, buf, url, "GET /test/ HTTP/1.0\n\n") == 200);
|
ASSERT(fetch(&mgr, buf, url, "GET /test/ HTTP/1.0\n\n") == 200);
|
||||||
printf("-------\n%s\n", buf);
|
|
||||||
ASSERT(mg_strstr(mg_str(buf), mg_str(">Index of /test/<")) != NULL);
|
ASSERT(mg_strstr(mg_str(buf), mg_str(">Index of /test/<")) != NULL);
|
||||||
ASSERT(mg_strstr(mg_str(buf), mg_str(">fuzz.c<")) != NULL);
|
ASSERT(mg_strstr(mg_str(buf), mg_str(">fuzz.c<")) != NULL);
|
||||||
|
|
||||||
@ -1358,7 +1357,7 @@ static void eh7(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
|||||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||||
struct mg_http_serve_opts sopts;
|
struct mg_http_serve_opts sopts;
|
||||||
memset(&sopts, 0, sizeof(sopts));
|
memset(&sopts, 0, sizeof(sopts));
|
||||||
sopts.root_dir = ".";
|
sopts.root_dir = "";
|
||||||
sopts.fs = &mg_fs_packed;
|
sopts.fs = &mg_fs_packed;
|
||||||
mg_http_serve_dir(c, hm, &sopts);
|
mg_http_serve_dir(c, hm, &sopts);
|
||||||
}
|
}
|
||||||
@ -1371,12 +1370,26 @@ static void test_packed(void) {
|
|||||||
char buf[FETCH_BUF_SIZE] = "", *data = mg_file_read("Makefile", NULL);
|
char buf[FETCH_BUF_SIZE] = "", *data = mg_file_read("Makefile", NULL);
|
||||||
mg_mgr_init(&mgr);
|
mg_mgr_init(&mgr);
|
||||||
mg_http_listen(&mgr, url, eh7, NULL);
|
mg_http_listen(&mgr, url, eh7, NULL);
|
||||||
|
|
||||||
|
// Load top level file directly
|
||||||
ASSERT(fetch(&mgr, buf, url, "GET /Makefile HTTP/1.0\n\n") == 200);
|
ASSERT(fetch(&mgr, buf, url, "GET /Makefile HTTP/1.0\n\n") == 200);
|
||||||
ASSERT(cmpbody(buf, data) == 0);
|
ASSERT(cmpbody(buf, data) == 0);
|
||||||
free(data);
|
free(data);
|
||||||
|
|
||||||
|
// Load file deeper in the FS tree directly
|
||||||
|
data = mg_file_read("src/ssi.h", NULL);
|
||||||
|
ASSERT(fetch(&mgr, buf, url, "GET /src/ssi.h HTTP/1.0\n\n") == 200);
|
||||||
|
ASSERT(cmpbody(buf, data) == 0);
|
||||||
|
free(data);
|
||||||
|
|
||||||
|
// List root dir
|
||||||
ASSERT(fetch(&mgr, buf, url, "GET / HTTP/1.0\n\n") == 200);
|
ASSERT(fetch(&mgr, buf, url, "GET / HTTP/1.0\n\n") == 200);
|
||||||
// printf("--------\n%s\n", buf);
|
// printf("--------\n%s\n", buf);
|
||||||
// exit(0);
|
|
||||||
|
// List nested dir
|
||||||
|
ASSERT(fetch(&mgr, buf, url, "GET /test HTTP/1.0\n\n") == 200);
|
||||||
|
// printf("--------\n%s\n", buf);
|
||||||
|
|
||||||
mg_mgr_free(&mgr);
|
mg_mgr_free(&mgr);
|
||||||
ASSERT(mgr.conns == NULL);
|
ASSERT(mgr.conns == NULL);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user