diff --git a/src/shrpx.cc b/src/shrpx.cc index ae90fc20..2bf15a5b 100644 --- a/src/shrpx.cc +++ b/src/shrpx.cc @@ -972,8 +972,6 @@ void fill_default_config() { mod_config()->pid = getpid(); mod_config()->backend_ipv4 = false; mod_config()->backend_ipv6 = false; - mod_config()->downstream_http_proxy_userinfo = nullptr; - mod_config()->downstream_http_proxy_host = nullptr; mod_config()->downstream_http_proxy_port = 0; mod_config()->read_rate = 0; mod_config()->read_burst = 0; @@ -2572,13 +2570,12 @@ int main(int argc, char **argv) { } } - if (get_config()->downstream_http_proxy_host) { + auto &proxy = mod_config()->downstream_http_proxy; + if (!proxy.host.empty()) { if (LOG_ENABLED(INFO)) { LOG(INFO) << "Resolving backend http proxy address"; } - if (resolve_hostname(&mod_config()->downstream_http_proxy_addr, - get_config()->downstream_http_proxy_host.get(), - get_config()->downstream_http_proxy_port, + if (resolve_hostname(&proxy.addr, proxy.host.c_str(), proxy.port, AF_UNSPEC) == -1) { exit(EXIT_FAILURE); } diff --git a/src/shrpx_config.cc b/src/shrpx_config.cc index a661fc03..332f30d8 100644 --- a/src/shrpx_config.cc +++ b/src/shrpx_config.cc @@ -1705,6 +1705,10 @@ int parse_config(const char *opt, const char *optarg, return 0; case SHRPX_OPTID_BACKEND_HTTP_PROXY_URI: { + auto &proxy = mod_config()->downstream_http_proxy; + // Reset here so that multiple option occurrence does not merge + // the results. + proxy = {}; // parse URI and get hostname, port and optionally userinfo. http_parser_url u{}; int rv = http_parser_parse_url(optarg, strlen(optarg), 0, &u); @@ -1715,19 +1719,17 @@ int parse_config(const char *opt, const char *optarg, // Surprisingly, u.field_set & UF_USERINFO is nonzero even if // userinfo component is empty string. if (!val.empty()) { - val = util::percent_decode(std::begin(val), std::end(val)); - mod_config()->downstream_http_proxy_userinfo = strcopy(val); + proxy.userinfo = util::percent_decode(std::begin(val), std::end(val)); } } if (u.field_set & UF_HOST) { - http2::copy_url_component(val, &u, UF_HOST, optarg); - mod_config()->downstream_http_proxy_host = strcopy(val); + http2::copy_url_component(proxy.host, &u, UF_HOST, optarg); } else { LOG(ERROR) << opt << ": no hostname specified"; return -1; } if (u.field_set & UF_PORT) { - mod_config()->downstream_http_proxy_port = u.port; + proxy.port = u.port; } else { LOG(ERROR) << opt << ": no port specified"; return -1; diff --git a/src/shrpx_config.h b/src/shrpx_config.h index 3ee52c98..e75661dd 100644 --- a/src/shrpx_config.h +++ b/src/shrpx_config.h @@ -283,6 +283,15 @@ struct TicketKeys { std::vector keys; }; +struct HttpProxy { + Address addr; + // host in http proxy URI + std::string host; + // userinfo in http proxy URI, not percent-encoded form + std::string userinfo; + uint16_t port; +}; + struct Config { // The list of (private key file, certificate file) pair std::vector> subcerts; @@ -298,11 +307,10 @@ struct Config { std::vector npn_list; // list of supported SSL/TLS protocol strings. std::vector tls_proto_list; - // binary form of http proxy host and port - Address downstream_http_proxy_addr; Address session_cache_memcached_addr; Address tls_ticket_key_memcached_addr; Router router; + HttpProxy downstream_http_proxy; // obfuscated value used in "by" parameter of Forwarded header // field. std::string forwarded_by_obfuscated; @@ -335,10 +343,6 @@ struct Config { std::unique_ptr conf_path; std::unique_ptr ciphers; std::unique_ptr cacert; - // userinfo in http proxy URI, not percent-encoded form - std::unique_ptr downstream_http_proxy_userinfo; - // host in http proxy URI - std::unique_ptr downstream_http_proxy_host; std::unique_ptr http2_upstream_dump_request_header_file; std::unique_ptr http2_upstream_dump_response_header_file; // Path to file containing CA certificate solely used for client diff --git a/src/shrpx_http2_session.cc b/src/shrpx_http2_session.cc index b67a1a0d..dff02931 100644 --- a/src/shrpx_http2_session.cc +++ b/src/shrpx_http2_session.cc @@ -271,27 +271,24 @@ int Http2Session::initiate_connection() { auto &downstream_addr = addrs[addr_idx_]; - if (get_config()->downstream_http_proxy_host && state_ == DISCONNECTED) { + const auto &proxy = get_config()->downstream_http_proxy; + if (!proxy.host.empty() && state_ == DISCONNECTED) { if (LOG_ENABLED(INFO)) { - SSLOG(INFO, this) << "Connecting to the proxy " - << get_config()->downstream_http_proxy_host.get() << ":" - << get_config()->downstream_http_proxy_port; + SSLOG(INFO, this) << "Connecting to the proxy " << proxy.host << ":" + << proxy.port; } - conn_.fd = util::create_nonblock_socket( - get_config()->downstream_http_proxy_addr.su.storage.ss_family); + conn_.fd = util::create_nonblock_socket(proxy.addr.su.storage.ss_family); if (conn_.fd == -1) { connect_blocker_->on_failure(); return -1; } - rv = connect(conn_.fd, &get_config()->downstream_http_proxy_addr.su.sa, - get_config()->downstream_http_proxy_addr.len); + rv = connect(conn_.fd, &proxy.addr.su.sa, proxy.addr.len); if (rv != 0 && errno != EINPROGRESS) { - SSLOG(ERROR, this) << "Failed to connect to the proxy " - << get_config()->downstream_http_proxy_host.get() - << ":" << get_config()->downstream_http_proxy_port; + SSLOG(ERROR, this) << "Failed to connect to the proxy " << proxy.host + << ":" << proxy.port; connect_blocker_->on_failure(); return -1; } @@ -523,12 +520,10 @@ int Http2Session::downstream_connect_proxy() { req += " HTTP/1.1\r\nHost: "; req.append(downstream_addr.host.c_str(), downstream_addr.host.size()); req += "\r\n"; - if (get_config()->downstream_http_proxy_userinfo) { + const auto &proxy = get_config()->downstream_http_proxy; + if (!proxy.userinfo.empty()) { req += "Proxy-Authorization: Basic "; - size_t len = strlen(get_config()->downstream_http_proxy_userinfo.get()); - req += base64::encode(get_config()->downstream_http_proxy_userinfo.get(), - get_config()->downstream_http_proxy_userinfo.get() + - len); + req += base64::encode(std::begin(proxy.userinfo), std::end(proxy.userinfo)); req += "\r\n"; } req += "\r\n";