summaryrefslogtreecommitdiffstats
path: root/src/seastar/include/seastar/http/file_handler.hh
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/seastar/include/seastar/http/file_handler.hh172
1 files changed, 172 insertions, 0 deletions
diff --git a/src/seastar/include/seastar/http/file_handler.hh b/src/seastar/include/seastar/http/file_handler.hh
new file mode 100644
index 000000000..4aff2cf9f
--- /dev/null
+++ b/src/seastar/include/seastar/http/file_handler.hh
@@ -0,0 +1,172 @@
+/*
+ * This file is open source software, licensed to you under the terms
+ * of the Apache License, Version 2.0 (the "License"). See the NOTICE file
+ * distributed with this work for additional information regarding copyright
+ * ownership. You may not use this file except in compliance with the License.
+ *
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+/*
+ * Copyright 2015 Cloudius Systems
+ */
+
+#pragma once
+
+#include <seastar/http/handlers.hh>
+#include <seastar/core/iostream.hh>
+
+namespace seastar {
+
+namespace httpd {
+
+/**
+ * This is a base class for file transformer.
+ *
+ * File transformer adds the ability to modify a file content before returning
+ * the results, it acts as a factory class for output_stream.
+ *
+ * The transformer decides according to the file extension if transforming is
+ * needed.
+ *
+ * If a transformation is needed it would create a new output stream from the given stream.
+ */
+class file_transformer {
+public:
+ /**
+ * Any file transformer should implement this method.
+ * @param req the request
+ * @param extension the file extension originating the content
+ * returns a new output stream to be used when writing the file to the reply
+ */
+ virtual output_stream<char> transform(std::unique_ptr<request> req,
+ const sstring& extension, output_stream<char>&& s) = 0;
+
+ virtual ~file_transformer() = default;
+};
+
+/**
+ * A base class for handlers that interact with files.
+ * directory and file handlers both share some common logic
+ * with regards to file handling.
+ * they both needs to read a file from the disk, optionally transform it,
+ * and return the result or page not found on error
+ */
+class file_interaction_handler : public handler_base {
+public:
+ file_interaction_handler(file_transformer* p = nullptr)
+ : transformer(p) {
+
+ }
+
+ ~file_interaction_handler();
+
+ /**
+ * Allows setting a transformer to be used with the files returned.
+ * @param t the file transformer to use
+ * @return this
+ */
+ file_interaction_handler* set_transformer(file_transformer* t) {
+ transformer = t;
+ return this;
+ }
+
+ /**
+ * if the url ends without a slash redirect
+ * @param req the request
+ * @param rep the reply
+ * @return true on redirect
+ */
+ bool redirect_if_needed(const request& req, reply& rep) const;
+
+ /**
+ * A helper method that returns the file extension.
+ * @param file the file to check
+ * @return the file extension
+ */
+ static sstring get_extension(const sstring& file);
+
+protected:
+
+ /**
+ * read a file from the disk and return it in the replay.
+ * @param file the full path to a file on the disk
+ * @param req the reuest
+ * @param rep the reply
+ */
+ future<std::unique_ptr<reply> > read(sstring file,
+ std::unique_ptr<request> req, std::unique_ptr<reply> rep);
+ file_transformer* transformer;
+
+ output_stream<char> get_stream(std::unique_ptr<request> req,
+ const sstring& extension, output_stream<char>&& s);
+};
+
+/**
+ * The directory handler get a disk path in the
+ * constructor.
+ * and expect a path parameter in the handle method.
+ * it would concatenate the two and return the file
+ * e.g. if the path is /usr/mgmt/public in the path
+ * parameter is index.html
+ * handle will return the content of /usr/mgmt/public/index.html
+ */
+class directory_handler : public file_interaction_handler {
+public:
+
+ /**
+ * The directory handler map a base path and a path parameter to a file
+ * @param doc_root the root directory to search the file from.
+ * @param transformer an optional file transformer
+ * For example if the root is '/usr/mgmt/public' and the path parameter
+ * will be '/css/style.css' the file wil be /usr/mgmt/public/css/style.css'
+ */
+ explicit directory_handler(const sstring& doc_root,
+ file_transformer* transformer = nullptr);
+
+ future<std::unique_ptr<reply>> handle(const sstring& path,
+ std::unique_ptr<request> req, std::unique_ptr<reply> rep) override;
+
+private:
+ sstring doc_root;
+};
+
+/**
+ * The file handler get a path to a file on the disk
+ * in the constructor.
+ * it will always return the content of the file.
+ */
+class file_handler : public file_interaction_handler {
+public:
+
+ /**
+ * The file handler map a file to a url
+ * @param file the full path to the file on the disk
+ * @param transformer an optional file transformer
+ * @param force_path check if redirect is needed upon `handle`
+ */
+ explicit file_handler(const sstring& file, file_transformer* transformer =
+ nullptr, bool force_path = true)
+ : file_interaction_handler(transformer), file(file), force_path(
+ force_path) {
+ }
+
+ future<std::unique_ptr<reply>> handle(const sstring& path,
+ std::unique_ptr<request> req, std::unique_ptr<reply> rep) override;
+
+private:
+ sstring file;
+ bool force_path;
+};
+
+}
+
+}