diff --git a/docs/README.md b/docs/README.md index e88d114c..f9bab9ae 100644 --- a/docs/README.md +++ b/docs/README.md @@ -686,8 +686,9 @@ Write a chunk of data in chunked encoding format. ```c struct mg_http_serve_opts { - const char *root_dir; // Web root directory, must be non-NULL - const char *ssi_pattern; // SSI filename pattern, e.g. #.shtml + const char *root_dir; // Web root directory, must be non-NULL + const char *ssi_pattern; // SSI filename pattern, e.g. #.shtml + const char *extra_headers; // Extra HTTP headers to add in responses }; void mg_http_serve_dir(struct mg_connection *, struct mg_http_message *hm, const struct mg_http_serve_opts *opts); diff --git a/examples/http-server/main.c b/examples/http-server/main.c index 00811ea6..a311e063 100644 --- a/examples/http-server/main.c +++ b/examples/http-server/main.c @@ -11,7 +11,7 @@ static const char *s_ssi_pattern = "#.shtml"; static void cb(struct mg_connection *c, int ev, void *ev_data, void *fn_data) { if (ev == MG_EV_HTTP_MSG) { - struct mg_http_serve_opts opts = {s_root_dir, s_ssi_pattern}; + struct mg_http_serve_opts opts = {s_root_dir, s_ssi_pattern, NULL}; mg_http_serve_dir(c, ev_data, &opts); } (void) fn_data; diff --git a/mongoose.c b/mongoose.c index 195fed9b..0f48089a 100644 --- a/mongoose.c +++ b/mongoose.c @@ -970,7 +970,7 @@ static void printdirentry(struct mg_connection *c, const char *name, } static void listdir(struct mg_connection *c, struct mg_http_message *hm, - char *dir) { + struct mg_http_serve_opts *opts, char *dir) { char path[MG_PATH_MAX], *p = &dir[strlen(dir) - 1], tmp[10]; struct dirent *dp; DIR *dirp; @@ -1001,10 +1001,12 @@ static void listdir(struct mg_connection *c, struct mg_http_message *hm, while (p > dir && *p != '/') *p-- = '\0'; if ((dirp = (opendir(dir))) != NULL) { size_t off, n; - mg_printf(c, "%s\r\n", + mg_printf(c, "HTTP/1.1 200 OK\r\n" "Content-Type: text/html; charset=utf-8\r\n" - "Content-Length: \r\n"); + "%s" + "Content-Length: \r\n\r\n", + opts->extra_headers == NULL ? "" : opts->extra_headers); off = c->send.len; // Start of body mg_printf(c, "Index of %.*s%s%s" @@ -1099,7 +1101,7 @@ void mg_http_serve_dir(struct mg_connection *c, struct mg_http_message *hm, #endif if (is_index && fp == NULL) { #if MG_ENABLE_DIRECTORY_LISTING - listdir(c, hm, t2); + listdir(c, hm, opts, t2); #else mg_http_reply(c, 403, "", "%s", "Directory listing not supported"); #endif @@ -1111,7 +1113,8 @@ void mg_http_serve_dir(struct mg_connection *c, struct mg_http_message *hm, mg_http_serve_ssi(c, t1, t2); #endif } else { - mg_http_serve_file(c, hm, t2, guess_content_type(t2), NULL); + mg_http_serve_file(c, hm, t2, guess_content_type(t2), + opts->extra_headers); } if (fp != NULL) fclose(fp); } diff --git a/mongoose.h b/mongoose.h index 12f7b2b3..ac3618d6 100644 --- a/mongoose.h +++ b/mongoose.h @@ -688,8 +688,9 @@ struct mg_http_message { // Parameter for mg_http_serve_dir() struct mg_http_serve_opts { - const char *root_dir; // Web root directory, must be non-NULL - const char *ssi_pattern; // SSI filename pattern, e.g. #.shtml + const char *root_dir; // Web root directory, must be non-NULL + const char *ssi_pattern; // SSI filename pattern, e.g. #.shtml + const char *extra_headers; // Extra HTTP headers to add in responses }; int mg_http_parse(const char *s, size_t len, struct mg_http_message *); diff --git a/src/http.c b/src/http.c index 78b834b9..8660a899 100644 --- a/src/http.c +++ b/src/http.c @@ -551,7 +551,7 @@ static void printdirentry(struct mg_connection *c, const char *name, } static void listdir(struct mg_connection *c, struct mg_http_message *hm, - char *dir) { + struct mg_http_serve_opts *opts, char *dir) { char path[MG_PATH_MAX], *p = &dir[strlen(dir) - 1], tmp[10]; struct dirent *dp; DIR *dirp; @@ -582,10 +582,12 @@ static void listdir(struct mg_connection *c, struct mg_http_message *hm, while (p > dir && *p != '/') *p-- = '\0'; if ((dirp = (opendir(dir))) != NULL) { size_t off, n; - mg_printf(c, "%s\r\n", + mg_printf(c, "HTTP/1.1 200 OK\r\n" "Content-Type: text/html; charset=utf-8\r\n" - "Content-Length: \r\n"); + "%s" + "Content-Length: \r\n\r\n", + opts->extra_headers == NULL ? "" : opts->extra_headers); off = c->send.len; // Start of body mg_printf(c, "Index of %.*s%s%s" @@ -680,7 +682,7 @@ void mg_http_serve_dir(struct mg_connection *c, struct mg_http_message *hm, #endif if (is_index && fp == NULL) { #if MG_ENABLE_DIRECTORY_LISTING - listdir(c, hm, t2); + listdir(c, hm, opts, t2); #else mg_http_reply(c, 403, "", "%s", "Directory listing not supported"); #endif @@ -692,7 +694,8 @@ void mg_http_serve_dir(struct mg_connection *c, struct mg_http_message *hm, mg_http_serve_ssi(c, t1, t2); #endif } else { - mg_http_serve_file(c, hm, t2, guess_content_type(t2), NULL); + mg_http_serve_file(c, hm, t2, guess_content_type(t2), + opts->extra_headers); } if (fp != NULL) fclose(fp); } diff --git a/src/http.h b/src/http.h index 13a4ae06..6e0ccb03 100644 --- a/src/http.h +++ b/src/http.h @@ -23,8 +23,9 @@ struct mg_http_message { // Parameter for mg_http_serve_dir() struct mg_http_serve_opts { - const char *root_dir; // Web root directory, must be non-NULL - const char *ssi_pattern; // SSI filename pattern, e.g. #.shtml + const char *root_dir; // Web root directory, must be non-NULL + const char *ssi_pattern; // SSI filename pattern, e.g. #.shtml + const char *extra_headers; // Extra HTTP headers to add in responses }; int mg_http_parse(const char *s, size_t len, struct mg_http_message *); diff --git a/test/unit_test.c b/test/unit_test.c index ab9da266..c703679b 100644 --- a/test/unit_test.c +++ b/test/unit_test.c @@ -337,7 +337,7 @@ static void eh1(struct mg_connection *c, int ev, void *ev_data, void *fn_data) { } else if (mg_http_match_uri(hm, "/bar")) { mg_http_reply(c, 404, "", "not found"); } else if (mg_http_match_uri(hm, "/badroot")) { - struct mg_http_serve_opts opts = {"/BAAADDD!", NULL}; + struct mg_http_serve_opts opts = {"/BAAADDD!", NULL, NULL}; mg_http_serve_dir(c, hm, &opts); } else if (mg_http_match_uri(hm, "/creds")) { char user[100], pass[100]; @@ -346,10 +346,10 @@ static void eh1(struct mg_connection *c, int ev, void *ev_data, void *fn_data) { } else if (mg_http_match_uri(hm, "/upload")) { mg_http_upload(c, hm, "."); } else if (mg_http_match_uri(hm, "/test/")) { - struct mg_http_serve_opts opts = {".", NULL}; + struct mg_http_serve_opts opts = {".", NULL, "A: B\r\nC: D\r\n"}; mg_http_serve_dir(c, hm, &opts); } else { - struct mg_http_serve_opts opts = {"./test/data", "#.shtml"}; + struct mg_http_serve_opts opts = {"./test/data", "#.shtml", "C: D\r\n"}; mg_http_serve_dir(c, hm, &opts); } } else if (ev == MG_EV_WS_MSG) {