From 8801e5113803f5ca7eee57bce19792be6410fd2c Mon Sep 17 00:00:00 2001 From: yhirose Date: Fri, 31 Jan 2020 20:34:03 -0500 Subject: [PATCH 1/2] Fix #341 --- example/simplesvr.cc | 2 +- httplib.h | 18 +++++++++++++++- test/test.cc | 50 +++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 65 insertions(+), 5 deletions(-) diff --git a/example/simplesvr.cc b/example/simplesvr.cc index c6f50bb..46234c7 100644 --- a/example/simplesvr.cc +++ b/example/simplesvr.cc @@ -122,7 +122,7 @@ int main(int argc, const char **argv) { auto base_dir = "./"; if (argc > 2) { base_dir = argv[2]; } - if (!svr.set_base_dir(base_dir)) { + if (!svr.set_mount_point(base_dir, "/")) { cout << "The specified base directory doesn't exist..."; return 1; } diff --git a/httplib.h b/httplib.h index e0f3689..d5620da 100644 --- a/httplib.h +++ b/httplib.h @@ -465,7 +465,9 @@ public: Server &Delete(const char *pattern, Handler handler); Server &Options(const char *pattern, Handler handler); - bool set_base_dir(const char *dir, const char *mount_point = nullptr); + [[deprecated]] bool set_base_dir(const char *dir, const char *mount_point = nullptr); + bool set_mount_point(const char *dir, const char *mount_point); + bool remove_mount_point(const char *mount_point); void set_file_extension_and_mimetype_mapping(const char *ext, const char *mime); void set_file_request_handler(Handler handler); @@ -2889,6 +2891,10 @@ inline Server &Server::Options(const char *pattern, Handler handler) { } inline bool Server::set_base_dir(const char *dir, const char *mount_point) { + return set_mount_point(dir, mount_point); +} + +inline bool Server::set_mount_point(const char *dir, const char *mount_point) { if (detail::is_dir(dir)) { std::string mnt = mount_point ? mount_point : "/"; if (!mnt.empty() && mnt[0] == '/') { @@ -2899,6 +2905,16 @@ inline bool Server::set_base_dir(const char *dir, const char *mount_point) { return false; } +inline bool Server::remove_mount_point(const char *mount_point) { + for (auto it = base_dirs_.begin(); it != base_dirs_.end(); ++it) { + if (it->first == mount_point) { + base_dirs_.erase(it); + return true; + } + } + return false; +} + inline void Server::set_file_extension_and_mimetype_mapping(const char *ext, const char *mime) { file_extension_and_mimetype_map_[ext] = mime; diff --git a/test/test.cc b/test/test.cc index d66a93b..22daf70 100644 --- a/test/test.cc +++ b/test/test.cc @@ -662,8 +662,8 @@ protected: } virtual void SetUp() { - svr_.set_base_dir("./www"); - svr_.set_base_dir("./www2", "/mount"); + svr_.set_mount_point("./www", "/"); + svr_.set_mount_point("./www2", "/mount"); svr_.set_file_extension_and_mimetype_mapping("abcde", "text/abcde"); svr_.Get("/hi", @@ -1245,7 +1245,7 @@ TEST_F(ServerTest, UserDefinedMIMETypeMapping) { } TEST_F(ServerTest, InvalidBaseDirMount) { - EXPECT_EQ(false, svr_.set_base_dir("./www3", "invalid_mount_point")); + EXPECT_EQ(false, svr_.set_mount_point("./www3", "invalid_mount_point")); } TEST_F(ServerTest, EmptyRequest) { @@ -2069,6 +2069,50 @@ TEST(ServerStopTest, StopServerWithChunkedTransmission) { ASSERT_FALSE(svr.is_running()); } +TEST(MountTest, Unmount) { + Server svr; + + auto listen_thread = std::thread([&svr]() { svr.listen("localhost", PORT); }); + while (!svr.is_running()) { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + + // Give GET time to get a few messages. + std::this_thread::sleep_for(std::chrono::seconds(1)); + + Client cli("localhost", PORT); + + svr.set_mount_point("./www2", "/mount2"); + + auto res = cli.Get("/"); + ASSERT_TRUE(res != nullptr); + EXPECT_EQ(404, res->status); + + res = cli.Get("/mount2/dir/test.html"); + ASSERT_TRUE(res != nullptr); + EXPECT_EQ(200, res->status); + + svr.set_mount_point("./www", "/"); + + res = cli.Get("/dir/"); + ASSERT_TRUE(res != nullptr); + EXPECT_EQ(200, res->status); + + svr.remove_mount_point("/"); + res = cli.Get("/dir/"); + ASSERT_TRUE(res != nullptr); + EXPECT_EQ(404, res->status); + + svr.remove_mount_point("/mount2"); + res = cli.Get("/mount2/dir/test.html"); + ASSERT_TRUE(res != nullptr); + EXPECT_EQ(404, res->status); + + svr.stop(); + listen_thread.join(); + ASSERT_FALSE(svr.is_running()); +} + class ServerTestWithAI_PASSIVE : public ::testing::Test { protected: ServerTestWithAI_PASSIVE() From 7c5197c86c27d00879b37a7e115a55772c7d15f6 Mon Sep 17 00:00:00 2001 From: yhirose Date: Fri, 31 Jan 2020 20:40:33 -0500 Subject: [PATCH 2/2] Updated README --- README.md | 46 ++++++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index fbbc9c6..8d05333 100644 --- a/README.md +++ b/README.md @@ -50,17 +50,21 @@ svr.listen_after_bind(); ### Static File Server ```cpp -auto ret = svr.set_base_dir("./www"); // This is same as `svr.set_base_dir("./www", "/")`; +// Mount / to ./www directory +auto ret = svr.set_mount_point("./www", "/"); if (!ret) { // The specified base directory doesn't exist... } // Mount /public to ./www directory -ret = svr.set_base_dir("./www", "/public"); +ret = svr.set_mount_point("./www", "/public"); // Mount /public to ./www1 and ./www2 directories -ret = svr.set_base_dir("./www1", "/public"); // 1st order to search -ret = svr.set_base_dir("./www2", "/public"); // 2nd order to search +ret = svr.set_mount_point("./www1", "/public"); // 1st order to search +ret = svr.set_mount_point("./www2", "/public"); // 2nd order to search + +// Remove mount / +ret = svr.remove_mount_point("/"); ``` ```cpp @@ -72,22 +76,24 @@ svr.set_file_extension_and_mimetype_mapping("hh", "text/x-h"); The followings are built-in mappings: -| Extension | MIME Type | -| :--------- | :--------------------- | -| .txt | text/plain | -| .html .htm | text/html | -| .css | text/css | -| .jpeg .jpg | image/jpg | -| .png | image/png | -| .gif | image/gif | -| .svg | image/svg+xml | -| .ico | image/x-icon | -| .json | application/json | -| .pdf | application/pdf | -| .js | application/javascript | -| .wasm | application/wasm | -| .xml | application/xml | -| .xhtml | application/xhtml+xml | +| Extension | MIME Type | +| :-------- | :--------------------- | +| txt | text/plain | +| html, htm | text/html | +| css | text/css | +| jpeg, jpg | image/jpg | +| png | image/png | +| gif | image/gif | +| svg | image/svg+xml | +| ico | image/x-icon | +| json | application/json | +| pdf | application/pdf | +| js | application/javascript | +| wasm | application/wasm | +| xml | application/xml | +| xhtml | application/xhtml+xml | + +NOTE: These the static file server methods are not thread safe. ### Logging