nghttpx: Use VString for DownstreamAddr::host and hostport to remember size
This commit is contained in:
parent
dbbf3a4a10
commit
34d5382d66
|
@ -151,6 +151,12 @@ nghttp2_nv make_nv_ls_nocopy(const char(&name)[N], const std::string &value) {
|
||||||
NGHTTP2_NV_FLAG_NO_COPY_NAME | NGHTTP2_NV_FLAG_NO_COPY_VALUE};
|
NGHTTP2_NV_FLAG_NO_COPY_NAME | NGHTTP2_NV_FLAG_NO_COPY_VALUE};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <size_t N>
|
||||||
|
nghttp2_nv make_nv_ls_nocopy(const char(&name)[N], const StringAdaptor &value) {
|
||||||
|
return {(uint8_t *)name, (uint8_t *)value.c_str(), N - 1, value.size(),
|
||||||
|
NGHTTP2_NV_FLAG_NO_COPY_NAME | NGHTTP2_NV_FLAG_NO_COPY_VALUE};
|
||||||
|
}
|
||||||
|
|
||||||
// Appends headers in |headers| to |nv|. |headers| must be indexed
|
// Appends headers in |headers| to |nv|. |headers| must be indexed
|
||||||
// before this call (its element's token field is assigned). Certain
|
// before this call (its element's token field is assigned). Certain
|
||||||
// headers, including disallowed headers in HTTP/2 spec and headers
|
// headers, including disallowed headers in HTTP/2 spec and headers
|
||||||
|
|
15
src/shrpx.cc
15
src/shrpx.cc
|
@ -2474,7 +2474,7 @@ int main(int argc, char **argv) {
|
||||||
|
|
||||||
if (get_config()->downstream_addr_groups.empty()) {
|
if (get_config()->downstream_addr_groups.empty()) {
|
||||||
DownstreamAddr addr;
|
DownstreamAddr addr;
|
||||||
addr.host = strcopy(DEFAULT_DOWNSTREAM_HOST);
|
addr.host = VString(DEFAULT_DOWNSTREAM_HOST);
|
||||||
addr.port = DEFAULT_DOWNSTREAM_PORT;
|
addr.port = DEFAULT_DOWNSTREAM_PORT;
|
||||||
|
|
||||||
DownstreamAddrGroup g("/");
|
DownstreamAddrGroup g("/");
|
||||||
|
@ -2513,7 +2513,7 @@ int main(int argc, char **argv) {
|
||||||
LOG(INFO) << "Host-path pattern: group " << i << ": '" << g.pattern.get()
|
LOG(INFO) << "Host-path pattern: group " << i << ": '" << g.pattern.get()
|
||||||
<< "'";
|
<< "'";
|
||||||
for (auto &addr : g.addrs) {
|
for (auto &addr : g.addrs) {
|
||||||
LOG(INFO) << "group " << i << " -> " << addr.host.get()
|
LOG(INFO) << "group " << i << " -> " << addr.host.c_str()
|
||||||
<< (addr.host_unix ? "" : ":" + util::utos(addr.port));
|
<< (addr.host_unix ? "" : ":" + util::utos(addr.port));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2537,10 +2537,10 @@ int main(int argc, char **argv) {
|
||||||
// hostport. This is used as Host header field to backend and
|
// hostport. This is used as Host header field to backend and
|
||||||
// not going to be passed to any syscalls.
|
// not going to be passed to any syscalls.
|
||||||
addr.hostport =
|
addr.hostport =
|
||||||
strcopy(util::make_hostport("localhost", get_config()->port));
|
VString(util::make_hostport("localhost", get_config()->port));
|
||||||
|
|
||||||
auto path = addr.host.get();
|
auto path = addr.host.c_str();
|
||||||
auto pathlen = strlen(path);
|
auto pathlen = addr.host.size();
|
||||||
|
|
||||||
if (pathlen + 1 > sizeof(addr.addr.su.un.sun_path)) {
|
if (pathlen + 1 > sizeof(addr.addr.su.un.sun_path)) {
|
||||||
LOG(FATAL) << "UNIX domain socket path " << path << " is too long > "
|
LOG(FATAL) << "UNIX domain socket path " << path << " is too long > "
|
||||||
|
@ -2559,10 +2559,11 @@ int main(int argc, char **argv) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
addr.hostport = strcopy(util::make_hostport(addr.host.get(), addr.port));
|
addr.hostport =
|
||||||
|
VString(util::make_hostport(addr.host.c_str(), addr.port));
|
||||||
|
|
||||||
if (resolve_hostname(
|
if (resolve_hostname(
|
||||||
&addr.addr, addr.host.get(), addr.port,
|
&addr.addr, addr.host.c_str(), addr.port,
|
||||||
get_config()->backend_ipv4 ? AF_INET : (get_config()->backend_ipv6
|
get_config()->backend_ipv4 ? AF_INET : (get_config()->backend_ipv6
|
||||||
? AF_INET6
|
? AF_INET6
|
||||||
: AF_UNSPEC)) == -1) {
|
: AF_UNSPEC)) == -1) {
|
||||||
|
|
|
@ -79,9 +79,8 @@ TicketKeys::~TicketKeys() {
|
||||||
}
|
}
|
||||||
|
|
||||||
DownstreamAddr::DownstreamAddr(const DownstreamAddr &other)
|
DownstreamAddr::DownstreamAddr(const DownstreamAddr &other)
|
||||||
: addr(other.addr), host(strcopy(other.host)),
|
: addr(other.addr), host(other.host), hostport(other.hostport),
|
||||||
hostport(strcopy(other.hostport)), port(other.port),
|
port(other.port), host_unix(other.host_unix) {}
|
||||||
host_unix(other.host_unix) {}
|
|
||||||
|
|
||||||
DownstreamAddr &DownstreamAddr::operator=(const DownstreamAddr &other) {
|
DownstreamAddr &DownstreamAddr::operator=(const DownstreamAddr &other) {
|
||||||
if (this == &other) {
|
if (this == &other) {
|
||||||
|
@ -89,8 +88,8 @@ DownstreamAddr &DownstreamAddr::operator=(const DownstreamAddr &other) {
|
||||||
}
|
}
|
||||||
|
|
||||||
addr = other.addr;
|
addr = other.addr;
|
||||||
host = strcopy(other.host);
|
host = other.host;
|
||||||
hostport = strcopy(other.hostport);
|
hostport = other.hostport;
|
||||||
port = other.port;
|
port = other.port;
|
||||||
host_unix = other.host_unix;
|
host_unix = other.host_unix;
|
||||||
|
|
||||||
|
@ -1394,7 +1393,7 @@ int parse_config(const char *opt, const char *optarg,
|
||||||
DownstreamAddr addr;
|
DownstreamAddr addr;
|
||||||
if (util::istarts_with(optarg, SHRPX_UNIX_PATH_PREFIX)) {
|
if (util::istarts_with(optarg, SHRPX_UNIX_PATH_PREFIX)) {
|
||||||
auto path = optarg + str_size(SHRPX_UNIX_PATH_PREFIX);
|
auto path = optarg + str_size(SHRPX_UNIX_PATH_PREFIX);
|
||||||
addr.host = strcopy(path, pat_delim);
|
addr.host = VString(path, pat_delim);
|
||||||
addr.host_unix = true;
|
addr.host_unix = true;
|
||||||
} else {
|
} else {
|
||||||
if (split_host_port(host, sizeof(host), &port, optarg,
|
if (split_host_port(host, sizeof(host), &port, optarg,
|
||||||
|
@ -1402,7 +1401,7 @@ int parse_config(const char *opt, const char *optarg,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
addr.host = strcopy(host);
|
addr.host = VString(host);
|
||||||
addr.port = port;
|
addr.port = port;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -245,8 +245,8 @@ struct DownstreamAddr {
|
||||||
Address addr;
|
Address addr;
|
||||||
// backend address. If |host_unix| is true, this is UNIX domain
|
// backend address. If |host_unix| is true, this is UNIX domain
|
||||||
// socket path.
|
// socket path.
|
||||||
std::unique_ptr<char[]> host;
|
VString host;
|
||||||
std::unique_ptr<char[]> hostport;
|
VString hostport;
|
||||||
// backend port. 0 if |host_unix| is true.
|
// backend port. 0 if |host_unix| is true.
|
||||||
uint16_t port;
|
uint16_t port;
|
||||||
// true if |host| contains UNIX domain socket path.
|
// true if |host| contains UNIX domain socket path.
|
||||||
|
|
|
@ -264,19 +264,18 @@ int Http2DownstreamConnection::push_request_headers() {
|
||||||
// addr_idx here.
|
// addr_idx here.
|
||||||
auto addr_idx = http2session_->get_addr_idx();
|
auto addr_idx = http2session_->get_addr_idx();
|
||||||
auto group = http2session_->get_group();
|
auto group = http2session_->get_group();
|
||||||
auto downstream_hostport = get_config()
|
const auto &downstream_hostport =
|
||||||
->downstream_addr_groups[group]
|
get_config()->downstream_addr_groups[group].addrs[addr_idx].hostport;
|
||||||
.addrs[addr_idx]
|
|
||||||
.hostport.get();
|
|
||||||
|
|
||||||
// For HTTP/1.0 request, there is no authority in request. In that
|
// For HTTP/1.0 request, there is no authority in request. In that
|
||||||
// case, we use backend server's host nonetheless.
|
// case, we use backend server's host nonetheless.
|
||||||
const char *authority = downstream_hostport;
|
auto authority = StringAdaptor(downstream_hostport);
|
||||||
|
|
||||||
if (no_host_rewrite && !req.authority.empty()) {
|
if (no_host_rewrite && !req.authority.empty()) {
|
||||||
authority = req.authority.c_str();
|
authority = req.authority;
|
||||||
}
|
}
|
||||||
|
|
||||||
downstream_->set_request_downstream_host(authority);
|
downstream_->set_request_downstream_host(authority.str());
|
||||||
|
|
||||||
size_t num_cookies = 0;
|
size_t num_cookies = 0;
|
||||||
if (!get_config()->http2_no_cookie_crumbling) {
|
if (!get_config()->http2_no_cookie_crumbling) {
|
||||||
|
@ -312,12 +311,12 @@ int Http2DownstreamConnection::push_request_headers() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!req.no_authority) {
|
if (!req.no_authority) {
|
||||||
nva.push_back(http2::make_nv_lc_nocopy(":authority", authority));
|
nva.push_back(http2::make_nv_ls_nocopy(":authority", authority));
|
||||||
} else {
|
} else {
|
||||||
nva.push_back(http2::make_nv_lc_nocopy("host", authority));
|
nva.push_back(http2::make_nv_ls_nocopy("host", authority));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
nva.push_back(http2::make_nv_lc_nocopy(":authority", authority));
|
nva.push_back(http2::make_nv_ls_nocopy(":authority", authority));
|
||||||
}
|
}
|
||||||
|
|
||||||
http2::copy_headers_to_nva_nocopy(nva, req.fs.headers());
|
http2::copy_headers_to_nva_nocopy(nva, req.fs.headers());
|
||||||
|
|
|
@ -338,7 +338,7 @@ int Http2Session::initiate_connection() {
|
||||||
if (get_config()->backend_tls_sni_name) {
|
if (get_config()->backend_tls_sni_name) {
|
||||||
sni_name = get_config()->backend_tls_sni_name.get();
|
sni_name = get_config()->backend_tls_sni_name.get();
|
||||||
} else {
|
} else {
|
||||||
sni_name = downstream_addr.host.get();
|
sni_name = downstream_addr.host.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sni_name && !util::numeric_host(sni_name)) {
|
if (sni_name && !util::numeric_host(sni_name)) {
|
||||||
|
@ -518,13 +518,13 @@ int Http2Session::downstream_connect_proxy() {
|
||||||
get_config()->downstream_addr_groups[group_].addrs[addr_idx_];
|
get_config()->downstream_addr_groups[group_].addrs[addr_idx_];
|
||||||
|
|
||||||
std::string req = "CONNECT ";
|
std::string req = "CONNECT ";
|
||||||
req += downstream_addr.hostport.get();
|
req.append(downstream_addr.hostport.c_str(), downstream_addr.hostport.size());
|
||||||
if (downstream_addr.port == 80 || downstream_addr.port == 443) {
|
if (downstream_addr.port == 80 || downstream_addr.port == 443) {
|
||||||
req += ':';
|
req += ':';
|
||||||
req += util::utos(downstream_addr.port);
|
req += util::utos(downstream_addr.port);
|
||||||
}
|
}
|
||||||
req += " HTTP/1.1\r\nHost: ";
|
req += " HTTP/1.1\r\nHost: ";
|
||||||
req += downstream_addr.host.get();
|
req.append(downstream_addr.host.c_str(), downstream_addr.host.size());
|
||||||
req += "\r\n";
|
req += "\r\n";
|
||||||
if (get_config()->downstream_http_proxy_userinfo) {
|
if (get_config()->downstream_http_proxy_userinfo) {
|
||||||
req += "Proxy-Authorization: Basic ";
|
req += "Proxy-Authorization: Basic ";
|
||||||
|
|
|
@ -211,27 +211,24 @@ int HttpDownstreamConnection::attach_downstream(Downstream *downstream) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int HttpDownstreamConnection::push_request_headers() {
|
int HttpDownstreamConnection::push_request_headers() {
|
||||||
auto downstream_hostport = get_config()
|
const auto &downstream_hostport =
|
||||||
->downstream_addr_groups[group_]
|
get_config()->downstream_addr_groups[group_].addrs[addr_idx_].hostport;
|
||||||
.addrs[addr_idx_]
|
|
||||||
.hostport.get();
|
|
||||||
const auto &req = downstream_->request();
|
const auto &req = downstream_->request();
|
||||||
|
|
||||||
auto connect_method = req.method == HTTP_CONNECT;
|
auto connect_method = req.method == HTTP_CONNECT;
|
||||||
|
|
||||||
// For HTTP/1.0 request, there is no authority in request. In that
|
// For HTTP/1.0 request, there is no authority in request. In that
|
||||||
// case, we use backend server's host nonetheless.
|
// case, we use backend server's host nonetheless.
|
||||||
const char *authority = downstream_hostport;
|
auto authority = StringAdaptor(downstream_hostport);
|
||||||
auto no_host_rewrite = get_config()->no_host_rewrite ||
|
auto no_host_rewrite = get_config()->no_host_rewrite ||
|
||||||
get_config()->http2_proxy ||
|
get_config()->http2_proxy ||
|
||||||
get_config()->client_proxy || connect_method;
|
get_config()->client_proxy || connect_method;
|
||||||
|
|
||||||
if (no_host_rewrite && !req.authority.empty()) {
|
if (no_host_rewrite && !req.authority.empty()) {
|
||||||
authority = req.authority.c_str();
|
authority = StringAdaptor(req.authority);
|
||||||
}
|
}
|
||||||
auto authoritylen = strlen(authority);
|
|
||||||
|
|
||||||
downstream_->set_request_downstream_host(authority);
|
downstream_->set_request_downstream_host(authority.str());
|
||||||
|
|
||||||
auto buf = downstream_->get_request_buf();
|
auto buf = downstream_->get_request_buf();
|
||||||
|
|
||||||
|
@ -241,14 +238,14 @@ int HttpDownstreamConnection::push_request_headers() {
|
||||||
buf->append(" ");
|
buf->append(" ");
|
||||||
|
|
||||||
if (connect_method) {
|
if (connect_method) {
|
||||||
buf->append(authority, authoritylen);
|
buf->append(authority.c_str(), authority.size());
|
||||||
} else if (get_config()->http2_proxy || get_config()->client_proxy) {
|
} else if (get_config()->http2_proxy || get_config()->client_proxy) {
|
||||||
// Construct absolute-form request target because we are going to
|
// Construct absolute-form request target because we are going to
|
||||||
// send a request to a HTTP/1 proxy.
|
// send a request to a HTTP/1 proxy.
|
||||||
assert(!req.scheme.empty());
|
assert(!req.scheme.empty());
|
||||||
buf->append(req.scheme);
|
buf->append(req.scheme);
|
||||||
buf->append("://");
|
buf->append("://");
|
||||||
buf->append(authority, authoritylen);
|
buf->append(authority.c_str(), authority.size());
|
||||||
buf->append(req.path);
|
buf->append(req.path);
|
||||||
} else if (req.method == HTTP_OPTIONS && req.path.empty()) {
|
} else if (req.method == HTTP_OPTIONS && req.path.empty()) {
|
||||||
// Server-wide OPTIONS
|
// Server-wide OPTIONS
|
||||||
|
@ -257,7 +254,7 @@ int HttpDownstreamConnection::push_request_headers() {
|
||||||
buf->append(req.path);
|
buf->append(req.path);
|
||||||
}
|
}
|
||||||
buf->append(" HTTP/1.1\r\nHost: ");
|
buf->append(" HTTP/1.1\r\nHost: ");
|
||||||
buf->append(authority, authoritylen);
|
buf->append(authority.c_str(), authority.size());
|
||||||
buf->append("\r\n");
|
buf->append("\r\n");
|
||||||
|
|
||||||
http2::build_http1_headers_from_headers(buf, req.fs.headers());
|
http2::build_http1_headers_from_headers(buf, req.fs.headers());
|
||||||
|
|
|
@ -973,7 +973,7 @@ int check_cert(SSL *ssl, const DownstreamAddr *addr) {
|
||||||
}
|
}
|
||||||
auto hostname = get_config()->backend_tls_sni_name
|
auto hostname = get_config()->backend_tls_sni_name
|
||||||
? get_config()->backend_tls_sni_name.get()
|
? get_config()->backend_tls_sni_name.get()
|
||||||
: addr->host.get();
|
: addr->host.c_str();
|
||||||
if (verify_hostname(cert, hostname, strlen(hostname), &addr->addr) != 0) {
|
if (verify_hostname(cert, hostname, strlen(hostname), &addr->addr) != 0) {
|
||||||
LOG(ERROR) << "Certificate verification failed: hostname does not match";
|
LOG(ERROR) << "Certificate verification failed: hostname does not match";
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -199,6 +199,47 @@ inline std::unique_ptr<char[]> strcopy(const std::unique_ptr<char[]> &val) {
|
||||||
return strcopy(val.get());
|
return strcopy(val.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct VString {
|
||||||
|
VString() : len(0) {}
|
||||||
|
VString(const char *s, size_t slen) : base(strcopy(s)), len(slen) {}
|
||||||
|
VString(const char *s) : base(strcopy(s)), len(strlen(s)) {}
|
||||||
|
VString(const std::string &s) : base(strcopy(s)), len(s.size()) {}
|
||||||
|
template <typename InputIt>
|
||||||
|
VString(InputIt first, InputIt last)
|
||||||
|
: base(strcopy(first, last)), len(std::distance(first, last)) {}
|
||||||
|
VString(const VString &other) : base(strcopy(other.base)), len(other.len) {}
|
||||||
|
VString(VString &&) = default;
|
||||||
|
VString &operator=(const VString &other) {
|
||||||
|
if (this == &other) {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
base = strcopy(other.base);
|
||||||
|
len = other.len;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
VString &operator=(VString &&other) = default;
|
||||||
|
|
||||||
|
const char *c_str() const { return base.get(); }
|
||||||
|
size_t size() const { return len; }
|
||||||
|
|
||||||
|
std::unique_ptr<char[]> base;
|
||||||
|
size_t len;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct StringAdaptor {
|
||||||
|
template <typename T>
|
||||||
|
StringAdaptor(const T &s)
|
||||||
|
: base(s.c_str()), len(s.size()) {}
|
||||||
|
|
||||||
|
const char *c_str() const { return base; }
|
||||||
|
size_t size() const { return len; }
|
||||||
|
|
||||||
|
std::string str() const { return std::string(base, len); }
|
||||||
|
|
||||||
|
const char *base;
|
||||||
|
size_t len;
|
||||||
|
};
|
||||||
|
|
||||||
inline int run_app(std::function<int(int, char **)> app, int argc,
|
inline int run_app(std::function<int(int, char **)> app, int argc,
|
||||||
char **argv) {
|
char **argv) {
|
||||||
try {
|
try {
|
||||||
|
|
Loading…
Reference in New Issue