summaryrefslogtreecommitdiff
path: root/src/static_files.cc
diff options
context:
space:
mode:
authorJoel Klinghed <the_jk@spawned.biz>2021-11-17 22:34:57 +0100
committerJoel Klinghed <the_jk@spawned.biz>2021-11-17 22:34:57 +0100
commit6232d13f5321b87ddf12a1aa36b4545da45f173d (patch)
tree23f3316470a14136debd9d02f9e920ca2b06f4cc /src/static_files.cc
Travel3: Simple image and video display site
Reads the images and videos from filesystem and builds a site in memroy.
Diffstat (limited to 'src/static_files.cc')
-rw-r--r--src/static_files.cc113
1 files changed, 113 insertions, 0 deletions
diff --git a/src/static_files.cc b/src/static_files.cc
new file mode 100644
index 0000000..7125ee0
--- /dev/null
+++ b/src/static_files.cc
@@ -0,0 +1,113 @@
+#include "common.hh"
+
+#include "files_finder.hh"
+#include "hasher.hh"
+#include "mime_types.hh"
+#include "send_file.hh"
+#include "static_files.hh"
+#include "weak_ptr.hh"
+
+#include <optional>
+
+namespace {
+
+class StaticFilesImpl : public StaticFiles, public FilesFinder::Delegate {
+public:
+ StaticFilesImpl(
+ std::shared_ptr<Logger> logger,
+ std::shared_ptr<TaskRunner> runner,
+ std::shared_ptr<SendFile> send_file,
+ std::filesystem::path path,
+ size_t threads)
+ : root_(std::move(path)), send_file_(std::move(send_file)),
+ weak_ptr_owner_(this) {
+ finder_ = FilesFinder::create(logger, runner, root_, this, threads);
+ hasher_ = Hasher::create(logger, runner, threads);
+ }
+
+ std::unique_ptr<Transport::Response> request(
+ Transport* transport, std::string_view path) override {
+ auto it = files_.find(std::string(path));
+ if (it == files_.end())
+ return nullptr;
+ auto resp = send_file_->create_ok_file(transport, it->second.path_,
+ it->first, it->second.etag_,
+ it->second.size_);
+ if (!it->second.mime_type_.empty())
+ resp->add_header("Content-Type", it->second.mime_type_);
+ return resp;
+ }
+
+ void file(std::filesystem::path path) override {
+ std::string name("/");
+ name.append(path.filename());
+ auto parent = path.parent_path();
+ while (true) {
+ if (parent == root_ || !parent.has_parent_path())
+ break;
+ name.insert(0, parent.filename());
+ name.insert(0, "/");
+ parent = parent.parent_path();
+ }
+ files_[name].path_ = path;
+ if (path.has_extension())
+ files_[name].mime_type_ = mime_types::from_extension(
+ std::string(path.extension()).substr(1));
+ hasher_->hash(path, std::bind(&StaticFilesImpl::weak_hashed,
+ weak_ptr_owner_.get(), name,
+ std::placeholders::_1,
+ std::placeholders::_2));
+ }
+
+ void done() override {
+ finder_.reset();
+ }
+
+private:
+ struct File {
+ std::filesystem::path path_;
+ std::string mime_type_;
+ std::string etag_;
+ std::optional<uint64_t> size_;
+ };
+
+ static void weak_hashed(std::shared_ptr<WeakPtr<StaticFilesImpl>> weak_ptr,
+ std::string const& name,
+ std::string hash,
+ uint64_t size) {
+ auto* ptr = weak_ptr->get();
+ if (ptr)
+ ptr->hashed(name, std::move(hash), size);
+ }
+
+ void hashed(std::string const& name, std::string hash, uint64_t size) {
+ if (hash.empty())
+ return;
+
+ hash.insert(0, "\"");
+ hash.push_back('"');
+ files_[name].etag_ = std::move(hash);
+ files_[name].size_ = size;
+ }
+
+ std::filesystem::path root_;
+ std::shared_ptr<SendFile> send_file_;
+ std::unordered_map<std::string, File> files_;
+ std::unique_ptr<FilesFinder> finder_;
+ std::unique_ptr<Hasher> hasher_;
+
+ WeakPtrOwner<StaticFilesImpl> weak_ptr_owner_;
+};
+
+} // namespace
+
+std::unique_ptr<StaticFiles> StaticFiles::create(
+ std::shared_ptr<Logger> logger,
+ std::shared_ptr<TaskRunner> runner,
+ std::shared_ptr<SendFile> send_file,
+ std::filesystem::path path,
+ size_t threads) {
+ return std::make_unique<StaticFilesImpl>(
+ std::move(logger), std::move(runner), std::move(send_file),
+ std::move(path), threads);
+}