Merge pull request #788 from nghttp2/nghttpx-h2-proxy-pattern-match

nghttpx: Enable backend pattern matching with http2-proxy
This commit is contained in:
Tatsuhiro Tsujikawa 2017-03-06 21:22:34 +09:00 committed by GitHub
commit fa074145a4
4 changed files with 15 additions and 30 deletions

View File

@ -1632,8 +1632,7 @@ Connections:
with "unix:" (e.g., unix:/var/run/backend.sock). with "unix:" (e.g., unix:/var/run/backend.sock).
Optionally, if <PATTERN>s are given, the backend address Optionally, if <PATTERN>s are given, the backend address
is only used if request matches the pattern. If is only used if request matches the pattern. The
--http2-proxy is used, <PATTERN>s are ignored. The
pattern matching is closely designed to ServeMux in pattern matching is closely designed to ServeMux in
net/http package of Go programming language. <PATTERN> net/http package of Go programming language. <PATTERN>
consists of path, host + path or just host. The path consists of path, host + path or just host. The path
@ -1648,7 +1647,10 @@ Connections:
request host. If host alone is given, "/" is appended request host. If host alone is given, "/" is appended
to it, so that it matches all request paths under the to it, so that it matches all request paths under the
host (e.g., specifying "nghttp2.org" equals to host (e.g., specifying "nghttp2.org" equals to
"nghttp2.org/"). "nghttp2.org/"). CONNECT method is treated specially.
It does not have path, and we don't allow empty path.
To workaround this, we assume that CONNECT method has
"/" as path.
Patterns with host take precedence over patterns with Patterns with host take precedence over patterns with
just path. Then, longer patterns take precedence over just path. Then, longer patterns take precedence over

View File

@ -980,18 +980,19 @@ ClientHandler::get_downstream_connection(int &err, Downstream *downstream) {
return make_unique<HealthMonitorDownstreamConnection>(); return make_unique<HealthMonitorDownstreamConnection>();
} }
auto &balloc = downstream->get_block_allocator();
// Fast path. If we have one group, it must be catch-all group. // Fast path. If we have one group, it must be catch-all group.
// proxy mode falls in this case. // proxy mode falls in this case.
if (groups.size() == 1) { if (groups.size() == 1) {
group_idx = 0; group_idx = 0;
} else if (req.method == HTTP_CONNECT) { } else if (req.method == HTTP_CONNECT) {
// We don't know how to treat CONNECT request in host-path // CONNECT method does not have path. But we requires path in
// mapping. It most likely appears in proxy scenario. Since we // host-path mapping. As workaround, we assume that path is "/".
// have dealt with proxy case already, just use catch-all group. group_idx = match_downstream_addr_group(routerconf, req.authority,
group_idx = catch_all; StringRef::from_lit("/"), groups,
catch_all, balloc);
} else { } else {
auto &balloc = downstream->get_block_allocator();
if (!req.authority.empty()) { if (!req.authority.empty()) {
group_idx = match_downstream_addr_group( group_idx = match_downstream_addr_group(
routerconf, req.authority, req.path, groups, catch_all, balloc); routerconf, req.authority, req.path, groups, catch_all, balloc);

View File

@ -3610,19 +3610,6 @@ int configure_downstream_group(Config *config, bool http2_proxy,
g.addrs.push_back(std::move(addr)); g.addrs.push_back(std::move(addr));
router.add_route(g.pattern, addr_groups.size()); router.add_route(g.pattern, addr_groups.size());
addr_groups.push_back(std::move(g)); addr_groups.push_back(std::move(g));
} else if (http2_proxy) {
// We don't support host mapping in these cases. Move all
// non-catch-all patterns to catch-all pattern.
DownstreamAddrGroupConfig catch_all(StringRef::from_lit("/"));
for (auto &g : addr_groups) {
std::move(std::begin(g.addrs), std::end(g.addrs),
std::back_inserter(catch_all.addrs));
}
std::vector<DownstreamAddrGroupConfig>().swap(addr_groups);
// maybe not necessary?
routerconf = RouterConfig{};
router.add_route(catch_all.pattern, addr_groups.size());
addr_groups.push_back(std::move(catch_all));
} }
// backward compatibility: override all SNI fields with the option // backward compatibility: override all SNI fields with the option

View File

@ -207,7 +207,7 @@ int htp_hdr_valcb(http_parser *htp, const char *data, size_t len) {
namespace { namespace {
void rewrite_request_host_path_from_uri(BlockAllocator &balloc, Request &req, void rewrite_request_host_path_from_uri(BlockAllocator &balloc, Request &req,
const StringRef &uri, const StringRef &uri,
http_parser_url &u, bool http2_proxy) { http_parser_url &u) {
assert(u.field_set & (1 << UF_HOST)); assert(u.field_set & (1 << UF_HOST));
// As per https://tools.ietf.org/html/rfc7230#section-5.4, we // As per https://tools.ietf.org/html/rfc7230#section-5.4, we
@ -276,12 +276,8 @@ void rewrite_request_host_path_from_uri(BlockAllocator &balloc, Request &req,
} }
} }
if (http2_proxy) {
req.path = path;
} else {
req.path = http2::rewrite_clean_path(balloc, path); req.path = http2::rewrite_clean_path(balloc, path);
} }
}
} // namespace } // namespace
namespace { namespace {
@ -395,8 +391,7 @@ int htp_hdrs_completecb(http_parser *htp) {
req.scheme = StringRef::from_lit("http"); req.scheme = StringRef::from_lit("http");
} }
} else { } else {
rewrite_request_host_path_from_uri( rewrite_request_host_path_from_uri(balloc, req, req.path, u);
balloc, req, req.path, u, config->http2_proxy && !faddr->alt_mode);
} }
} }