From 6232d13f5321b87ddf12a1aa36b4545da45f173d Mon Sep 17 00:00:00 2001 From: Joel Klinghed Date: Wed, 17 Nov 2021 22:34:57 +0100 Subject: Travel3: Simple image and video display site Reads the images and videos from filesystem and builds a site in memroy. --- src/static_files.cc | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 src/static_files.cc (limited to 'src/static_files.cc') 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 + +namespace { + +class StaticFilesImpl : public StaticFiles, public FilesFinder::Delegate { +public: + StaticFilesImpl( + std::shared_ptr logger, + std::shared_ptr runner, + std::shared_ptr 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 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 size_; + }; + + static void weak_hashed(std::shared_ptr> 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 send_file_; + std::unordered_map files_; + std::unique_ptr finder_; + std::unique_ptr hasher_; + + WeakPtrOwner weak_ptr_owner_; +}; + +} // namespace + +std::unique_ptr StaticFiles::create( + std::shared_ptr logger, + std::shared_ptr runner, + std::shared_ptr send_file, + std::filesystem::path path, + size_t threads) { + return std::make_unique( + std::move(logger), std::move(runner), std::move(send_file), + std::move(path), threads); +} -- cgit v1.2.3-70-g09d2