Skip to content

Commit 295e4d5

Browse files
committed
1 parent 448de6a commit 295e4d5

File tree

6 files changed

+86
-24
lines changed

6 files changed

+86
-24
lines changed

httplib.h

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,9 @@ using socket_t = int;
129129
#define INVALID_SOCKET (-1)
130130
#endif //_WIN32
131131

132-
#include <cassert>
132+
#include <array>
133133
#include <atomic>
134+
#include <cassert>
134135
#include <condition_variable>
135136
#include <errno.h>
136137
#include <fcntl.h>
@@ -145,7 +146,6 @@ using socket_t = int;
145146
#include <string>
146147
#include <sys/stat.h>
147148
#include <thread>
148-
#include <array>
149149

150150
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
151151
#include <openssl/err.h>
@@ -507,7 +507,7 @@ class Server {
507507
Server &Delete(const char *pattern, Handler handler);
508508
Server &Options(const char *pattern, Handler handler);
509509

510-
bool set_base_dir(const char *path);
510+
bool set_base_dir(const char *dir, const char *mount_point = nullptr);
511511
void set_file_request_handler(Handler handler);
512512

513513
void set_error_handler(Handler handler);
@@ -570,7 +570,7 @@ class Server {
570570

571571
std::atomic<bool> is_running_;
572572
std::atomic<socket_t> svr_sock_;
573-
std::string base_dir_;
573+
std::vector<std::pair<std::string, std::string>> base_dirs_;
574574
Handler file_request_handler_;
575575
Handlers get_handlers_;
576576
Handlers post_handlers_;
@@ -2408,10 +2408,13 @@ inline Server &Server::Options(const char *pattern, Handler handler) {
24082408
return *this;
24092409
}
24102410

2411-
inline bool Server::set_base_dir(const char *path) {
2412-
if (detail::is_dir(path)) {
2413-
base_dir_ = path;
2414-
return true;
2411+
inline bool Server::set_base_dir(const char *dir, const char *mount_point) {
2412+
if (detail::is_dir(dir)) {
2413+
std::string mnt = mount_point ? mount_point : "/";
2414+
if (!mnt.empty() && mnt[0] == '/') {
2415+
base_dirs_.emplace_back(mnt, dir);
2416+
return true;
2417+
}
24152418
}
24162419
return false;
24172420
}
@@ -2684,21 +2687,28 @@ Server::read_content_with_content_receiver(Stream &strm, bool last_connection,
26842687
}
26852688

26862689
inline bool Server::handle_file_request(Request &req, Response &res) {
2687-
if (!base_dir_.empty() && detail::is_valid_path(req.path)) {
2688-
std::string path = base_dir_ + req.path;
2689-
2690-
if (!path.empty() && path.back() == '/') { path += "index.html"; }
2691-
2692-
if (detail::is_file(path)) {
2693-
detail::read_file(path, res.body);
2694-
auto type = detail::find_content_type(path);
2695-
if (type) { res.set_header("Content-Type", type); }
2696-
res.status = 200;
2697-
if (file_request_handler_) { file_request_handler_(req, res); }
2698-
return true;
2690+
for (const auto& kv: base_dirs_) {
2691+
const auto& mount_point = kv.first;
2692+
const auto& base_dir = kv.second;
2693+
2694+
// Prefix match
2695+
if (!req.path.find(mount_point)) {
2696+
std::string sub_path = "/" + req.path.substr(mount_point.size());
2697+
if (detail::is_valid_path(sub_path)) {
2698+
auto path = base_dir + sub_path;
2699+
if (path.back() == '/') { path += "index.html"; }
2700+
2701+
if (detail::is_file(path)) {
2702+
detail::read_file(path, res.body);
2703+
auto type = detail::find_content_type(path);
2704+
if (type) { res.set_header("Content-Type", type); }
2705+
res.status = 200;
2706+
if (file_request_handler_) { file_request_handler_(req, res); }
2707+
return true;
2708+
}
2709+
}
26992710
}
27002711
}
2701-
27022712
return false;
27032713
}
27042714

test/test.cc

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,7 @@ class ServerTest : public ::testing::Test {
567567

568568
virtual void SetUp() {
569569
svr_.set_base_dir("./www");
570+
svr_.set_base_dir("./www2", "/mount");
570571

571572
svr_.Get("/hi",
572573
[&](const Request & /*req*/, Response &res) {
@@ -1003,9 +1004,42 @@ TEST_F(ServerTest, GetMethodOutOfBaseDir2) {
10031004
EXPECT_EQ(404, res->status);
10041005
}
10051006

1006-
TEST_F(ServerTest, InvalidBaseDir) {
1007-
EXPECT_EQ(false, svr_.set_base_dir("invalid_dir"));
1008-
EXPECT_EQ(true, svr_.set_base_dir("."));
1007+
TEST_F(ServerTest, GetMethodDirMountTest) {
1008+
auto res = cli_.Get("/mount/dir/test.html");
1009+
ASSERT_TRUE(res != nullptr);
1010+
EXPECT_EQ(200, res->status);
1011+
EXPECT_EQ("text/html", res->get_header_value("Content-Type"));
1012+
EXPECT_EQ("test.html", res->body);
1013+
}
1014+
1015+
TEST_F(ServerTest, GetMethodDirMountTestWithDoubleDots) {
1016+
auto res = cli_.Get("/mount/dir/../dir/test.html");
1017+
ASSERT_TRUE(res != nullptr);
1018+
EXPECT_EQ(200, res->status);
1019+
EXPECT_EQ("text/html", res->get_header_value("Content-Type"));
1020+
EXPECT_EQ("test.html", res->body);
1021+
}
1022+
1023+
TEST_F(ServerTest, GetMethodInvalidMountPath) {
1024+
auto res = cli_.Get("/mount/dir/../test.html");
1025+
ASSERT_TRUE(res != nullptr);
1026+
EXPECT_EQ(404, res->status);
1027+
}
1028+
1029+
TEST_F(ServerTest, GetMethodOutOfBaseDirMount) {
1030+
auto res = cli_.Get("/mount/../www2/dir/test.html");
1031+
ASSERT_TRUE(res != nullptr);
1032+
EXPECT_EQ(404, res->status);
1033+
}
1034+
1035+
TEST_F(ServerTest, GetMethodOutOfBaseDirMount2) {
1036+
auto res = cli_.Get("/mount/dir/../../www2/dir/test.html");
1037+
ASSERT_TRUE(res != nullptr);
1038+
EXPECT_EQ(404, res->status);
1039+
}
1040+
1041+
TEST_F(ServerTest, InvalidBaseDirMount) {
1042+
EXPECT_EQ(false, svr_.set_base_dir("./www3", "invalid_mount_point"));
10091043
}
10101044

10111045
TEST_F(ServerTest, EmptyRequest) {

test/www2/dir/index.html

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<html>
2+
<head>
3+
</head>
4+
<body>
5+
<a href="/dir/test.html">Test</a>
6+
<a href="/hi">hi</a>
7+
</body>
8+
</html>

test/www2/dir/test.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
test.html

test/www3/dir/index.html

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<html>
2+
<head>
3+
</head>
4+
<body>
5+
<a href="/dir/test.html">Test</a>
6+
<a href="/hi">hi</a>
7+
</body>
8+
</html>

test/www3/dir/test.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
test.html

0 commit comments

Comments
 (0)