diff options
author | Ed Tanous <ed.tanous@intel.com> | 2017-08-15 19:37:42 +0300 |
---|---|---|
committer | Ed Tanous <ed.tanous@intel.com> | 2017-10-11 23:34:56 +0300 |
commit | 911ac31759cb7b77a856af8806b4e064d50d7422 (patch) | |
tree | c4b714fabb2b956936ab6dffc18d9ff418756cf4 /include/webassets.hpp | |
parent | 8f0c0481d2280919b38a31656ba21a4347d12620 (diff) | |
download | bmcweb-911ac31759cb7b77a856af8806b4e064d50d7422.tar.xz |
Large updates to webserver
Do not merge yet
Change-Id: I38c56844c1b0e3e8e5493c2705e62e6db7ee2102
Diffstat (limited to 'include/webassets.hpp')
-rw-r--r-- | include/webassets.hpp | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/include/webassets.hpp b/include/webassets.hpp new file mode 100644 index 0000000000..988af767ba --- /dev/null +++ b/include/webassets.hpp @@ -0,0 +1,118 @@ +#pragma once + +#include <experimental/filesystem> +#include <fstream> +#include <string> +#include <crow/app.h> +#include <crow/http_request.h> +#include <crow/http_response.h> +#include <crow/routing.h> +#include <boost/algorithm/string/replace.hpp> +#include <boost/container/flat_set.hpp> + +namespace crow { +namespace webassets { + +namespace filesystem = std::experimental::filesystem; +static const char* gzip_string = "gzip"; +static const char* none_string = "none"; +static const char* if_none_match_string = "If-None-Match"; +static const char* content_encoding_string = "Content-Encoding"; +static const char* content_type_string = "Content-Type"; +static const char* etag_string = "ETag"; + +static boost::container::flat_set<std::string> routes; + +template <typename... Middlewares> +void request_routes(Crow<Middlewares...>& app) { + const static boost::container::flat_map<const char*, const char*> content_types{ + {{".css", "text/css;charset=UTF-8"}, + {".html", "text/html;charset=UTF-8"}, + {".js", "text/html;charset=UTF-8"}, + {".png", "image/png;charset=UTF-8"}, + {".woff", "application/x-font-woff"}, + {".woff2", "application/x-font-woff2"}, + {".ttf", "application/x-font-ttf"}, + {".svg", "image/svg+xml"}, + {".eot", "application/vnd.ms-fontobject"}, + // dev tools don't care about map type, setting to json causes + // browser to show as text + // https://stackoverflow.com/questions/19911929/what-mime-type-should-i-use-for-javascript-source-map-files + {".map", "application/json"}}}; + auto rootpath = filesystem::path("/usr/share/www/"); + auto dir_iter = filesystem::recursive_directory_iterator(rootpath); + for (auto& dir : dir_iter) { + auto absolute_path = dir.path(); + auto relative_path = filesystem::path( + absolute_path.string().substr(rootpath.string().size() - 1)); + // make sure we don't recurse into certain directories + // note: maybe check for is_directory() here as well... + if (filesystem::is_directory(dir)) { + // don't recurse into hidden directories or symlinks + if (boost::starts_with(dir.path().filename().string(), ".") || + filesystem::is_symlink(dir)) { + dir_iter.disable_recursion_pending(); + } + } else if (filesystem::is_regular_file(dir)) { + auto webpath = relative_path; + bool is_gzip = false; + if (relative_path.extension() == ".gz") { + webpath = webpath.replace_extension(""); + is_gzip = true; + } + + if (webpath.filename() == "index.html") { + webpath = webpath.parent_path(); + } + + routes.insert(webpath.string()); + + std::string absolute_path_str = absolute_path.string(); + const char* content_type = nullptr; + auto content_type_it = + content_types.find(relative_path.extension().c_str()); + if (content_type_it != content_types.end()) { + content_type = content_type_it->second; + } + app.route_dynamic(std::string(webpath.string()))( + [is_gzip, absolute_path_str, content_type](const crow::request& req, + crow::response& res) { + if (is_gzip) { + res.add_header(content_encoding_string, gzip_string); + } else { + res.add_header(content_encoding_string, none_string); + } + // std::string sha1("a576dc96a5c605b28afb032f3103630d61ac1068"); + // res.add_header(etag_string, sha1); + + // if (req.get_header_value(if_none_match_string) == sha1) { + // res.code = 304; + //} else { + // res.code = 200; + // TODO, if you have a browser from the dark ages that doesn't + // support + // gzip, unzip it before sending based on Accept-Encoding header + // res.add_header(content_encoding_string, gzip_string); + if (content_type != nullptr) { + res.add_header(content_type_string, content_type); + } + // res.set_header("Cache-Control", "public, max-age=86400"); + std::ifstream inf(absolute_path_str); + if (!inf) { + CROW_LOG_DEBUG << "failed to read file"; + res.code = 400; + res.end(); + return; + } + + std::string body{std::istreambuf_iterator<char>(inf), + std::istreambuf_iterator<char>()}; + + res.body = body; + res.end(); + }); + } + } +} +} // namespace webassets +} // namespace crow
\ No newline at end of file |