#include "../http/mime.hpp" #include "../logger.hpp" #include #include #include "staticcontent.hpp" #include #include namespace Middleware { bool TryReadAllBytes(std::string const & filePath, std::vector & buffer) { std::ifstream ifs(filePath, std::ios_base::binary | std::ios_base::ate); if (!ifs.is_open()) { return false; } std::ifstream::pos_type length = ifs.tellg(); auto const oldBufferSize = buffer.size(); buffer.resize(oldBufferSize + length); ifs.seekg(0, std::ios_base::beg); ifs.read(&buffer[oldBufferSize], length); return true; } bool ContainsDoubleDots(std::string const & s) { bool previousWasDot = false; for(unsigned i = 0; i < s.size(); ++i) { if (s[i] == '.') { if(previousWasDot) { return true; } previousWasDot = true; } else { previousWasDot = false; } } return false; } void StaticContent::HandleRequest(State & state, ScheduleHelper & scheduleHelper) { if (!(state.request.type == HttpRequest::Type::GET || state.request.type == HttpRequest::Type::HEAD)) { return; } std::string path; if (state.request.url.HasPath()) { path = root + state.request.url.GetPath(); } else { // TODO make configurable? path = root + "/index.html"; } if (ContainsDoubleDots(state.request.url.GetPath())) { // We cannot deal with this, we are not going to bother checking if // this double dot escapes our root directory return; } if (access(path.c_str(), F_OK) != 0) { // File does not exist return; } state.response.code = HttpResponse::Code::OK; state.response.contentType = Http::GetMimeType(path); // Regular file descriptors are not supported by epoll, so we have to "just read it" if (state.request.type == HttpRequest::Type::GET && !TryReadAllBytes(path, state.response.content)) { state.response.code = HttpResponse::Code::INTERNAL_SERVER_ERROR; state.response.contentType = Http::GetMimeType(""); } // HEAD request state.finished = true; return; } StaticContent::StaticContent(Logger & _logger, std::string const & staticFileRoot) : BaseMiddleware(_logger), root(staticFileRoot) { std::stringstream ss; ss << "Using static file root " << root; _logger.Info(ss.str()); } }