Skip to content

Commit 60d2a37

Browse files
committed
Improved FileStat
Added last_modified() to struct FileStat. Removed condition #ifdef CPPHTTPLIB_OPENSSL_SUPPORT around ETag generation. Adjusted tests.
1 parent dc30799 commit 60d2a37

File tree

2 files changed

+30
-17
lines changed

2 files changed

+30
-17
lines changed

httplib.h

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2407,7 +2407,9 @@ struct FileStat {
24072407
FileStat(const std::string &path);
24082408
bool is_file() const;
24092409
bool is_dir() const;
2410+
std::uint64_t last_modified() const;
24102411

2412+
private:
24112413
#if defined(_WIN32)
24122414
struct _stat st_;
24132415
#else
@@ -2883,6 +2885,17 @@ inline bool FileStat::is_file() const {
28832885
inline bool FileStat::is_dir() const {
28842886
return ret_ >= 0 && S_ISDIR(st_.st_mode);
28852887
}
2888+
inline std::uint64_t FileStat::last_modified() const {
2889+
if (is_dir() || is_file()) {
2890+
#if defined(_WIN32)
2891+
return st_.st_mtime;
2892+
#else
2893+
return st_.st_mtim.tv_sec;
2894+
#endif
2895+
} else {
2896+
throw std::runtime_error("Invalid directory or file.");
2897+
}
2898+
}
28862899

28872900
inline std::string encode_path(const std::string &s) {
28882901
std::string result;
@@ -7891,8 +7904,7 @@ inline bool Server::handle_file_request(const Request &req, Response &res) {
78917904
return false;
78927905
}
78937906

7894-
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
7895-
if (is_etag_enabled && stat.ret_ >= 0)
7907+
if (is_etag_enabled)
78967908
/*
78977909
* The HTTP request header If-Match and If-None-Match can be used
78987910
* with other methods where they have the meaning to only execute if
@@ -7905,10 +7917,9 @@ inline bool Server::handle_file_request(const Request &req, Response &res) {
79057917
*/
79067918
if (req.method == "GET" || req.method == "HEAD") {
79077919
// Value for HTTP response header ETag.
7908-
const std::string file_data(mm->data(), mm->size());
79097920
const std::string etag =
7910-
R"(")" + detail::from_i_to_hex(stat.st_.st_mtim.tv_sec) +
7911-
"-" + detail::from_i_to_hex(mm->size()) + R"(")";
7921+
R"(")" + detail::from_i_to_hex(stat.last_modified()) + "-" +
7922+
detail::from_i_to_hex(mm->size()) + R"(")";
79127923

79137924
/*
79147925
* Weak validation is not used in both cases.
@@ -7973,7 +7984,6 @@ inline bool Server::handle_file_request(const Request &req, Response &res) {
79737984
}
79747985
}
79757986
}
7976-
#endif
79777987

79787988
res.set_content_provider(
79797989
mm->size(),

test/test.cc

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10306,17 +10306,24 @@ TEST(UniversalClientImplTest, Ipv6LiteralAddress) {
1030610306
EXPECT_EQ(cli.port(), port);
1030710307
}
1030810308

10309-
TEST(FileSystemTest, FileAndDirExistenceCheck) {
10309+
TEST(FileSystemTest, FileStatTest) {
1031010310
auto file_path = "./www/dir/index.html";
1031110311
auto dir_path = "./www/dir";
1031210312

1031310313
detail::FileStat stat_file(file_path);
1031410314
EXPECT_TRUE(stat_file.is_file());
1031510315
EXPECT_FALSE(stat_file.is_dir());
10316+
EXPECT_GT(stat_file.last_modified(), 0);
1031610317

1031710318
detail::FileStat stat_dir(dir_path);
1031810319
EXPECT_FALSE(stat_dir.is_file());
1031910320
EXPECT_TRUE(stat_dir.is_dir());
10321+
EXPECT_GT(stat_dir.last_modified(), 0);
10322+
10323+
detail::FileStat stat_error("ranipsd");
10324+
EXPECT_FALSE(stat_error.is_file());
10325+
EXPECT_FALSE(stat_error.is_dir());
10326+
EXPECT_THROW(stat_error.last_modified(), std::runtime_error);
1032010327
}
1032110328

1032210329
TEST(DirtyDataRequestTest, HeadFieldValueContains_CR_LF_NUL) {
@@ -10837,16 +10844,15 @@ TEST(is_etag_enabled, getter_and_setter) {
1083710844
EXPECT_TRUE(svr.get_is_etag_enabled());
1083810845
}
1083910846

10840-
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
1084110847
TEST(StaticFileSever, If_Match) {
1084210848
detail::FileStat stat("./www/file");
10843-
ASSERT_GE(stat.ret_, 0);
10849+
ASSERT_TRUE(stat.is_file());
1084410850
auto mm = std::make_shared<detail::mmap>("./www/file");
1084510851
ASSERT_TRUE(mm->is_open());
1084610852

1084710853
const std::string etag = R"(")" +
10848-
detail::from_i_to_hex(stat.st_.st_mtim.tv_sec) +
10849-
"-" + detail::from_i_to_hex(mm->size()) + R"(")";
10854+
detail::from_i_to_hex(stat.last_modified()) + "-" +
10855+
detail::from_i_to_hex(mm->size()) + R"(")";
1085010856

1085110857
/*
1085210858
* 0: is_etag_enabled = false
@@ -10899,18 +10905,16 @@ TEST(StaticFileSever, If_Match) {
1089910905
}
1090010906
}
1090110907
}
10902-
#endif
1090310908

10904-
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
1090510909
TEST(StaticFileSever, If_None_Match) {
1090610910
detail::FileStat stat("./www/file");
10907-
ASSERT_GE(stat.ret_, 0);
10911+
ASSERT_TRUE(stat.is_file());
1090810912
auto mm = std::make_shared<detail::mmap>("./www/file");
1090910913
ASSERT_TRUE(mm->is_open());
1091010914

1091110915
const std::string etag = R"(")" +
10912-
detail::from_i_to_hex(stat.st_.st_mtim.tv_sec) +
10913-
"-" + detail::from_i_to_hex(mm->size()) + R"(")";
10916+
detail::from_i_to_hex(stat.last_modified()) + "-" +
10917+
detail::from_i_to_hex(mm->size()) + R"(")";
1091410918

1091510919
/*
1091610920
* 0: is_etag_enabled = false
@@ -10957,4 +10961,3 @@ TEST(StaticFileSever, If_None_Match) {
1095710961
}
1095810962
}
1095910963
}
10960-
#endif

0 commit comments

Comments
 (0)