add file index to static file handler

This commit is contained in:
Sky Johnson 2025-06-14 18:58:31 -05:00
parent 0ac37c6ab3
commit cab962fde0

View File

@ -6,11 +6,14 @@
#include <string>
#include <string_view>
#include <unordered_map>
#include <unordered_set>
#include <fstream>
#include <filesystem>
#include <chrono>
#include <shared_mutex>
#include <zlib.h>
#include <cstring>
#include <mutex>
using std::string_view;
using std::string;
@ -21,8 +24,31 @@ private:
string url_prefix_;
string root_path_;
std::unordered_map<string, std::pair<string, std::chrono::time_point<std::chrono::file_clock>>> cache_;
std::unordered_set<string> file_index_;
mutable std::shared_mutex index_mutex_;
size_t max_cache_size_ = 50 * 1024 * 1024; // 50MB cache limit
void build_file_index() {
std::unique_lock lock(index_mutex_);
file_index_.clear();
if (!fs::exists(root_path_) || !fs::is_directory(root_path_)) {
return;
}
for (const auto& entry : fs::recursive_directory_iterator(root_path_)) {
if (entry.is_regular_file()) {
auto rel_path = fs::relative(entry.path(), root_path_);
file_index_.insert(rel_path.string());
}
}
}
bool file_exists_fast(const string& relative_path) const {
std::shared_lock lock(index_mutex_);
return file_index_.count(relative_path) > 0;
}
string compress_gzip(const string& data) const {
z_stream zs;
memset(&zs, 0, sizeof(zs));
@ -79,6 +105,11 @@ public:
if (!url_prefix_.empty() && url_prefix_.back() != '/') {
url_prefix_ += '/';
}
build_file_index();
}
void refresh_index() {
build_file_index();
}
bool handle(const Request& req, Response& res) {
@ -101,19 +132,22 @@ public:
return false;
}
string file_path = root_path_;
string relative_path;
if (file_path_part.empty() || file_path_part == "/") {
file_path += "index.html";
relative_path = "index.html";
} else {
// Remove leading slash if present
if (file_path_part[0] == '/') file_path_part = file_path_part.substr(1);
file_path += string(file_path_part);
relative_path = string(file_path_part);
}
if (!fs::exists(file_path) || !fs::is_regular_file(file_path)) {
// Fast file existence check
if (!file_exists_fast(relative_path)) {
return false;
}
string file_path = root_path_ + relative_path;
// Get file info
auto last_write = fs::last_write_time(file_path);
auto file_size = fs::file_size(file_path);
@ -163,4 +197,4 @@ public:
return true;
}
};
};