Add a proxy fallback, and read proxy from env
This commit is contained in:
parent
4d456c56a8
commit
5d163800c3
@ -1,4 +1,3 @@
|
||||
#include "rublon/bits.hpp"
|
||||
#include <security/pam_appl.h>
|
||||
#include <security/pam_client.h>
|
||||
#include <security/pam_ext.h>
|
||||
@ -6,6 +5,7 @@
|
||||
#include <security/pam_modules.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include <rublon/bits.hpp>
|
||||
#include <rublon/check_application.hpp>
|
||||
#include <rublon/error.hpp>
|
||||
#include <rublon/error_handler.hpp>
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "tl/expected.hpp"
|
||||
#include <rublon/error.hpp>
|
||||
#include <rublon/memory.hpp>
|
||||
#include <rublon/static_string.hpp>
|
||||
@ -60,7 +61,7 @@ class ConfigurationReader {
|
||||
memory::MonotonicStack_1k_Resource memoryResource;
|
||||
std::ifstream file(filepath.data());
|
||||
if(not file.good())
|
||||
return ;
|
||||
return;
|
||||
|
||||
std::pmr::string line{&memoryResource};
|
||||
line.reserve(300);
|
||||
@ -74,7 +75,7 @@ class ConfigurationReader {
|
||||
continue;
|
||||
|
||||
auto posEqual = line.find('=');
|
||||
std::pmr::string key {line.substr(0, posEqual),&memoryResource};
|
||||
std::pmr::string key{line.substr(0, posEqual), &memoryResource};
|
||||
std::pmr::string value{line.substr(posEqual + 1), &memoryResource};
|
||||
|
||||
keyValues[std::move(key)] = std::move(value);
|
||||
@ -147,6 +148,64 @@ class ConfigurationReader {
|
||||
return std::nullopt;
|
||||
};
|
||||
|
||||
auto parseProxyURL = [&](const char * envValue) -> bool {
|
||||
// Very simple parser: scheme://[user[:pass]@]host[:port]
|
||||
std::string_view url = envValue;
|
||||
|
||||
std::string_view scheme{};
|
||||
std::string_view auth{};
|
||||
std::string_view hostport{};
|
||||
|
||||
auto scheme_pos = url.find("://");
|
||||
if(scheme_pos != std::string_view::npos) {
|
||||
scheme = url.substr(0, scheme_pos);
|
||||
url = url.substr(scheme_pos + 3);
|
||||
} else {
|
||||
scheme = "http"; // default
|
||||
}
|
||||
|
||||
auto at_pos = url.find('@');
|
||||
if(at_pos != std::string_view::npos) {
|
||||
auth = url.substr(0, at_pos);
|
||||
hostport = url.substr(at_pos + 1);
|
||||
} else {
|
||||
hostport = url;
|
||||
}
|
||||
|
||||
std::string_view host = hostport;
|
||||
std::string_view port_str{};
|
||||
auto colon_pos = hostport.rfind(':');
|
||||
if(colon_pos != std::string_view::npos && colon_pos < hostport.size() - 1) {
|
||||
host = hostport.substr(0, colon_pos);
|
||||
port_str = hostport.substr(colon_pos + 1);
|
||||
}
|
||||
|
||||
config.proxyEnabled = true;
|
||||
config.proxyType = scheme;
|
||||
config.proxyServer = host;
|
||||
|
||||
if(!port_str.empty()) {
|
||||
config.proxyPort = conv::to_uint32opt(port_str);
|
||||
if(not config.proxyPort) {
|
||||
log(LogLevel::Error, "Invalid proxy port in environment variable");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(!auth.empty()) {
|
||||
auto colon = auth.find(':');
|
||||
if(colon != std::string_view::npos) {
|
||||
config.proxyUsername = auth.substr(0, colon);
|
||||
config.proxyPass = auth.substr(colon + 1);
|
||||
} else {
|
||||
config.proxyUsername = auth;
|
||||
}
|
||||
config.proxyAuthRequired = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
/// NOTE:
|
||||
// getStringOpt can return a valid empty string, for example configuration entry like
|
||||
// option=
|
||||
@ -183,6 +242,22 @@ class ConfigurationReader {
|
||||
config.proxyEnabled = getBool("proxyEnabled").value_or(false);
|
||||
config.proxyType = getStringOpt("proxyType");
|
||||
config.proxyServer = getStringOpt("proxyServer");
|
||||
|
||||
|
||||
// Apply fallback if no config is set
|
||||
if (config.proxyEnabled && (!config.proxyType || config.proxyType->empty()) && (!config.proxyServer || config.proxyServer->empty())) {
|
||||
log(LogLevel::Info, "Proxy is enabled but no configuration for it is provided, trying to read from env");
|
||||
if (const char* https_proxy = std::getenv("https_proxy"); https_proxy && *https_proxy) {
|
||||
if (parseProxyURL(https_proxy)) {
|
||||
log(LogLevel::Info, "Loaded proxy config from HTTPS_PROXY");
|
||||
}
|
||||
} else if (const char* http_proxy = std::getenv("http_proxy"); http_proxy && *http_proxy) {
|
||||
if (parseProxyURL(http_proxy)) {
|
||||
log(LogLevel::Info, "Loaded proxy config from HTTP_PROXY");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(config.proxyEnabled) {
|
||||
if(not config.proxyType or config.proxyType->empty()) {
|
||||
log(LogLevel::Error, "Proxy is enabled but proxy type is not present or empty");
|
||||
|
||||
@ -99,7 +99,7 @@ class CURL {
|
||||
proxyUrl = *conf().proxyType;
|
||||
proxyUrl += "://";
|
||||
proxyUrl += *conf().proxyServer;
|
||||
if(conf().proxyPort > 0) {
|
||||
if(conf().proxyPort.value_or(0) > 0) {
|
||||
proxyUrl += ":";
|
||||
proxyUrl += std::to_string(*conf().proxyPort);
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <charconv>
|
||||
#include <optional>
|
||||
#include <rublon/memory.hpp>
|
||||
#include <rublon/static_string.hpp>
|
||||
@ -150,22 +151,22 @@ namespace conv {
|
||||
return strcmp(buf.data(), "true") == 0;
|
||||
}
|
||||
|
||||
inline tl::expected< std::uint32_t, Error > to_uint32(std::string_view userinput) noexcept {
|
||||
try {
|
||||
return std::stoi(userinput.data());
|
||||
} catch(const std::invalid_argument & e) {
|
||||
return tl::make_unexpected(Error::NotANumber);
|
||||
} catch(const std::out_of_range & e) {
|
||||
return tl::make_unexpected(Error::OutOfRange);
|
||||
}
|
||||
}
|
||||
|
||||
inline std::optional< std::uint32_t> to_uint32opt(std::string_view userinput) noexcept {
|
||||
try {
|
||||
return std::stoi(userinput.data());
|
||||
} catch(...) {
|
||||
int out;
|
||||
const std::from_chars_result result = std::from_chars(userinput.data(), userinput.data() + userinput.size(), out);
|
||||
if(result.ec == std::errc::invalid_argument || result.ec == std::errc::result_out_of_range) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
inline tl::expected< std::uint32_t, Error > to_uint32(std::string_view userinput) noexcept {
|
||||
int out;
|
||||
const std::from_chars_result result = std::from_chars(userinput.data(), userinput.data() + userinput.size(), out);
|
||||
if(result.ec == std::errc::invalid_argument || result.ec == std::errc::result_out_of_range) {
|
||||
return tl::make_unexpected(Error::NotANumber);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
} // namespace conv
|
||||
|
||||
|
||||
@ -93,7 +93,7 @@ class WebSocket {
|
||||
}
|
||||
|
||||
proxyUrl += *cfg.proxyServer;
|
||||
if(cfg.proxyPort > 0) {
|
||||
if(cfg.proxyPort.value_or(0) > 0) {
|
||||
proxyUrl += ":";
|
||||
proxyUrl += std::to_string(*cfg.proxyPort);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user