From 3f2922b3faab7d77507ad23c63a33cceeaa7c054 Mon Sep 17 00:00:00 2001 From: yhirose Date: Mon, 9 Sep 2024 19:25:52 -0400 Subject: [PATCH] Fix #1929 --- httplib.h | 33 +++++++++++++++++++++------------ test/test.cc | 10 ++++++---- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/httplib.h b/httplib.h index 56af371..40bcb8b 100644 --- a/httplib.h +++ b/httplib.h @@ -2253,9 +2253,15 @@ make_basic_authentication_header(const std::string &username, namespace detail { -bool is_file(const std::string &path); +struct FileStat { + FileStat(const std::string &path); + bool is_file() const; + bool is_dir() const; -bool is_dir(const std::string &path); +private: + struct stat st_; + int ret_ = -1; +}; std::string encode_query_param(const std::string &value); @@ -2626,14 +2632,14 @@ inline bool is_valid_path(const std::string &path) { return true; } -inline bool is_file(const std::string &path) { - struct stat st; - return stat(path.c_str(), &st) >= 0 && S_ISREG(st.st_mode); +inline FileStat::FileStat(const std::string &path) { + ret_ = stat(path.c_str(), &st_); } - -inline bool is_dir(const std::string &path) { - struct stat st; - return stat(path.c_str(), &st) >= 0 && S_ISDIR(st.st_mode); +inline bool FileStat::is_file() const { + return ret_ >= 0 && S_ISREG(st_.st_mode); +} +inline bool FileStat::is_dir() const { + return ret_ >= 0 && S_ISDIR(st_.st_mode); } inline std::string encode_query_param(const std::string &value) { @@ -6085,7 +6091,8 @@ inline bool Server::set_base_dir(const std::string &dir, inline bool Server::set_mount_point(const std::string &mount_point, const std::string &dir, Headers headers) { - if (detail::is_dir(dir)) { + detail::FileStat stat(dir); + if (stat.is_dir()) { std::string mnt = !mount_point.empty() ? mount_point : "/"; if (!mnt.empty() && mnt[0] == '/') { base_dirs_.push_back({mnt, dir, std::move(headers)}); @@ -6569,12 +6576,14 @@ inline bool Server::handle_file_request(const Request &req, Response &res, auto path = entry.base_dir + sub_path; if (path.back() == '/') { path += "index.html"; } - if (detail::is_dir(path)) { + detail::FileStat stat(path); + + if (stat.is_dir()) { res.set_redirect(sub_path + "/", StatusCode::MovedPermanently_301); return true; } - if (detail::is_file(path)) { + if (stat.is_file()) { for (const auto &kv : entry.headers) { res.set_header(kv.first, kv.second); } diff --git a/test/test.cc b/test/test.cc index 05a9744..b9bc977 100644 --- a/test/test.cc +++ b/test/test.cc @@ -7676,11 +7676,13 @@ TEST(FileSystemTest, FileAndDirExistenceCheck) { auto file_path = "./www/dir/index.html"; auto dir_path = "./www/dir"; - EXPECT_TRUE(detail::is_file(file_path)); - EXPECT_FALSE(detail::is_dir(file_path)); + detail::FileStat stat_file(file_path); + EXPECT_TRUE(stat_file.is_file()); + EXPECT_FALSE(stat_file.is_dir()); - EXPECT_FALSE(detail::is_file(dir_path)); - EXPECT_TRUE(detail::is_dir(dir_path)); + detail::FileStat stat_dir(dir_path); + EXPECT_FALSE(stat_dir.is_file()); + EXPECT_TRUE(stat_dir.is_dir()); } TEST(DirtyDataRequestTest, HeadFieldValueContains_CR_LF_NUL) {