diff --git a/config/debug_tawashi.ini.in b/config/debug_tawashi.ini.in index e0c6c27..cc6e2c5 100644 --- a/config/debug_tawashi.ini.in +++ b/config/debug_tawashi.ini.in @@ -2,7 +2,8 @@ redis_server = 127.0.0.1 redis_port = 6379 redis_mode = inet -base_uri = 127.0.0.1:8080 +host_name = 127.0.0.1 +host_port = from_downstream website_root = @CMAKE_CURRENT_BINARY_DIR@/html logging_level = trace log_file = @CMAKE_CURRENT_BINARY_DIR@/tawashi.log diff --git a/config/tawashi.ini b/config/tawashi.ini index 1e4aedb..8507a7b 100644 --- a/config/tawashi.ini +++ b/config/tawashi.ini @@ -2,6 +2,7 @@ redis_server = 127.0.0.1 redis_port = 6379 redis_mode = inet -base_uri = 127.0.0.1:8080 +host_name = 127.0.0.1 +host_port = from_downstream website_root = html logging_level = trace diff --git a/src/tawashi/main.cpp b/src/tawashi/main.cpp index 64de018..9c5fc80 100644 --- a/src/tawashi/main.cpp +++ b/src/tawashi/main.cpp @@ -70,7 +70,9 @@ namespace { parSettings.add_default("redis_mode", "sock"); parSettings.add_default("redis_sock", "/tmp/redis.sock"); parSettings.add_default("redis_db", "0"); - parSettings.add_default("base_uri", "http://127.0.0.1"); + parSettings.add_default("host_name", "127.0.0.1"); + parSettings.add_default("host_port", ""); + parSettings.add_default("host_path", "/"); parSettings.add_default("website_root", ""); parSettings.add_default("langmap_dir", "/usr/share/source-highlight"); parSettings.add_default("min_pastie_size", "10"); @@ -146,7 +148,7 @@ int main (int parArgc, char* parArgv[], char* parEnvp[]) { SPDLOG_DEBUG(statuslog, "tawashi started"); statuslog->info("Loaded config: \"{}\"", config_file_path()); - auto cgi_env = SafeStackObject(parEnvp); + auto cgi_env = SafeStackObject(parEnvp, settings->at("host_path")); tawashi::ResponseFactory resp_factory(settings, cgi_env); SPDLOG_TRACE(statuslog, "Registering makers in the response factory"); resp_factory.register_maker("index.cgi", &make_response); @@ -155,7 +157,7 @@ int main (int parArgc, char* parArgv[], char* parEnvp[]) { resp_factory.register_maker("error.cgi", &make_response); resp_factory.register_jolly_maker(&make_response); - std::unique_ptr response = resp_factory.make_response(cgi_env->path_info().substr(1)); + std::unique_ptr response = resp_factory.make_response(cgi_env->path_info()); response->send(); SPDLOG_DEBUG(statuslog, "tawashi done, quitting"); diff --git a/src/tawashi_implem/cgi_env.cpp b/src/tawashi_implem/cgi_env.cpp index 243826e..d769f56 100644 --- a/src/tawashi_implem/cgi_env.cpp +++ b/src/tawashi_implem/cgi_env.cpp @@ -30,6 +30,7 @@ #include #include #include +#include BOOST_FUSION_ADAPT_STRUCT( tawashi::cgi::Env::VersionInfo, @@ -81,9 +82,16 @@ namespace cgi { } } //unnamed namespace - Env::Env(const char* const* parEnvList) : - m_cgi_env(cgi_environment_vars(parEnvList)) + Env::Env(const char* const* parEnvList, const boost::string_ref& parBasePath) : + m_cgi_env(cgi_environment_vars(parEnvList)), + m_skip_path_info(0) { + const std::string& path = m_cgi_env[CGIVars::PATH_INFO]; + assert(parBasePath.size() <= path.size()); + if (boost::starts_with(path, parBasePath)) + m_skip_path_info = parBasePath.size(); + else + m_skip_path_info = 0; } Env::~Env() noexcept = default; @@ -106,8 +114,10 @@ namespace cgi { return split_version(m_cgi_env[CGIVars::GATEWAY_INTERFACE]); } - const std::string& Env::path_info() const { - return m_cgi_env[CGIVars::PATH_INFO]; + boost::string_ref Env::path_info() const { + const std::string& path = m_cgi_env[CGIVars::PATH_INFO]; + assert(m_skip_path_info <= path.size()); + return boost::string_ref(path).substr(m_skip_path_info); } const std::string& Env::path_translated() const { diff --git a/src/tawashi_implem/cgi_env.hpp b/src/tawashi_implem/cgi_env.hpp index e18e636..7b25eb9 100644 --- a/src/tawashi_implem/cgi_env.hpp +++ b/src/tawashi_implem/cgi_env.hpp @@ -41,14 +41,14 @@ namespace tawashi { typedef boost::container::flat_map GetMapType; - explicit Env (const char* const* parEnvList); + Env (const char* const* parEnvList, const boost::string_ref& parBasePath); ~Env() noexcept; const std::string& auth_type() const; std::size_t content_length() const; const std::string& content_type() const; boost::optional gateway_interface() const a_pure; - const std::string& path_info() const; + boost::string_ref path_info() const; const std::string& path_translated() const; const std::string& query_string() const; const std::string& remote_addr() const; @@ -70,6 +70,7 @@ namespace tawashi { private: std::vector m_cgi_env; Escapist m_houdini; + std::size_t m_skip_path_info; }; } //namespace cgi } //namespace tawashi diff --git a/src/tawashi_implem/pastie_response.cpp b/src/tawashi_implem/pastie_response.cpp index f0ed244..540c399 100644 --- a/src/tawashi_implem/pastie_response.cpp +++ b/src/tawashi_implem/pastie_response.cpp @@ -68,7 +68,7 @@ namespace tawashi { using opt_string = redis::IncRedis::opt_string; using opt_string_list = redis::IncRedis::opt_string_list; - auto token = boost::string_ref(cgi_env().path_info()).substr(1); + auto token = boost::string_ref(cgi_env().path_info()); auto& redis = this->redis(); opt_string_list pastie_reply = redis.hmget(token, "pastie"); opt_string pastie = (pastie_reply and not pastie_reply->empty() ? (*pastie_reply)[0] : opt_string()); diff --git a/src/tawashi_implem/response.cpp b/src/tawashi_implem/response.cpp index cd959aa..f909a72 100644 --- a/src/tawashi_implem/response.cpp +++ b/src/tawashi_implem/response.cpp @@ -20,6 +20,7 @@ #include "settings_bag.hpp" #include "tawashiConfig.h" #include "duckhandy/stringize.h" +#include "duckhandy/lexical_cast.hpp" #include "pathname/pathname.hpp" #include "list_highlight_langs.hpp" #include "cgi_env.hpp" @@ -107,13 +108,31 @@ namespace tawashi { return parStr; }; - std::string make_base_uri (const boost::string_ref& parBaseURI, bool parHttps) { + std::string make_base_uri (const Kakoune::SafePtr& parSettings, const Kakoune::SafePtr& parCgiEnv) { + assert(parSettings); + assert(parCgiEnv); + std::ostringstream oss; - if (parHttps) + if (parCgiEnv->https()) oss << "https://"; else oss << "http://"; - oss << parBaseURI; + oss << parSettings->at("host_name"); + boost::string_ref host_port = parSettings->at("host_port"); + if (not host_port.empty()) { + if (host_port == "from_downstream") { + const uint16_t port = parCgiEnv->server_port(); + if ((80 != port and not parCgiEnv->https()) or 443 != port and parCgiEnv->https()) { + oss << ':' << port; + } + } + else if (not host_port.empty()) { + oss << ':' << host_port; + } + } + boost::string_ref host_path = parSettings->at("host_path"); + if (host_path != "/") + oss << host_path; return oss.str(); } } //unnamed namespace @@ -128,7 +147,7 @@ namespace tawashi { m_cgi_env(parCgiEnv), m_settings(parSettings), m_website_root(make_root_path(*parSettings)), - m_base_uri(make_base_uri(m_settings->at("base_uri"), m_cgi_env->https())), + m_base_uri(make_base_uri(m_settings, m_cgi_env)), m_stream_out(parStreamOut), m_header_sent(false) { diff --git a/test/unit/test_index_response.cpp b/test/unit/test_index_response.cpp index 59e2f9f..f6e9675 100644 --- a/test/unit/test_index_response.cpp +++ b/test/unit/test_index_response.cpp @@ -77,7 +77,7 @@ TEST_CASE ("Index response", "[index][response]") { const char* const env_raw[] = { "AUTH_TYPE=", "CONTENT_TYPE=", - "PATH_INFO=", + "PATH_INFO=/", "PATH_TRANSLATED=", "QUERY_STRING=index.cgi" "REMOTE_ADDR=", @@ -90,16 +90,19 @@ TEST_CASE ("Index response", "[index][response]") { "SERVER_SOFTWARE=", "CONTENT_LENGTH=", "SERVER_PORT=80", + "HTTPS=", nullptr }; - SafeStackObject fake_env(env_raw); + SafeStackObject fake_env(env_raw, "/"); std::string tawashi_settings( "[tawashi]\n" - " base_uri = http://127.0.0.1\n" + " host_name = 127.0.0.1\n" " website_root = /home/michele/dev/code/cpp/tawashi/html\n" " logging_level = debug\n" " langmap_dir = /usr/share/source-highlight\n" + " host_path = /\n" + " host_port =\n" ); SafeStackObject ini(std::move(tawashi_settings)); SafeStackObject settings(ini); diff --git a/test/unit/test_invalid_utf8_post.cpp b/test/unit/test_invalid_utf8_post.cpp index e9bfe1e..9abc48b 100644 --- a/test/unit/test_invalid_utf8_post.cpp +++ b/test/unit/test_invalid_utf8_post.cpp @@ -49,10 +49,11 @@ TEST_CASE ("Retrieve and sanitize invalid an invalid utf-8 text", "[utf8][securi const char* const fake_env[] = { content_length.c_str(), + "PATH_INFO=/", nullptr }; - tawashi::cgi::Env env(fake_env); + tawashi::cgi::Env env(fake_env, "/"); const PostMapType& post_data = read_post(iss, env); CHECK(g_utf8_validate(post_data.at("invalid_text").data(), post_data.at("invalid_text").size(), nullptr));