Merge pull request #1537 from nghttp2/nghttpx-allow-colon-in-pattern

nghttpx: Add workaround to include ':' in backend pattern
This commit is contained in:
Tatsuhiro Tsujikawa 2020-11-27 23:35:27 +09:00 committed by GitHub
commit fb5b5aef0a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 61 additions and 5 deletions

View File

@ -1841,6 +1841,53 @@ StringRef normalize_path(BlockAllocator &balloc, const StringRef &path,
query);
}
StringRef normalize_path_colon(BlockAllocator &balloc, const StringRef &path,
const StringRef &query) {
// First, decode %XX for unreserved characters and ':', then do
// http2::path_join
// We won't find %XX if length is less than 3.
if (path.size() < 3 ||
std::find(std::begin(path), std::end(path), '%') == std::end(path)) {
return path_join(balloc, StringRef{}, StringRef{}, path, query);
}
// includes last terminal NULL.
auto result = make_byte_ref(balloc, path.size() + 1);
auto p = result.base;
auto it = std::begin(path);
for (; it + 2 < std::end(path);) {
if (*it == '%') {
if (util::is_hex_digit(*(it + 1)) && util::is_hex_digit(*(it + 2))) {
auto c =
(util::hex_to_uint(*(it + 1)) << 4) + util::hex_to_uint(*(it + 2));
if (util::in_rfc3986_unreserved_chars(c) || c == ':') {
*p++ = c;
it += 3;
continue;
}
*p++ = '%';
*p++ = util::upcase(*(it + 1));
*p++ = util::upcase(*(it + 2));
it += 3;
continue;
}
}
*p++ = *it++;
}
p = std::copy(it, std::end(path), p);
*p = '\0';
return path_join(balloc, StringRef{}, StringRef{}, StringRef{result.base, p},
query);
}
std::string normalize_path(const StringRef &path, const StringRef &query) {
BlockAllocator balloc(1024, 1024);

View File

@ -410,6 +410,12 @@ StringRef to_method_string(int method_token);
StringRef normalize_path(BlockAllocator &balloc, const StringRef &path,
const StringRef &query);
// normalize_path_colon is like normalize_path, but it additionally
// does percent-decoding %3A in order to workaround the issue that ':'
// cannot be included in backend pattern.
StringRef normalize_path_colon(BlockAllocator &balloc, const StringRef &path,
const StringRef &query);
std::string normalize_path(const StringRef &path, const StringRef &query);
StringRef rewrite_clean_path(BlockAllocator &balloc, const StringRef &src);

View File

@ -1877,8 +1877,11 @@ Connections:
affinity is enabled.
Since ";" and ":" are used as delimiter, <PATTERN> must
not contain these characters. Since ";" has special
meaning in shell, the option value must be quoted.
not contain these characters. In order to include ":"
in <PATTERN>, one has to specify "%3A" (which is
percent-encoded from of ":") instead. Since ";" has
special meaning in shell, the option value must be
quoted.
Default: )"
<< DEFAULT_DOWNSTREAM_HOST << "," << DEFAULT_DOWNSTREAM_PORT << R"(

View File

@ -1109,9 +1109,9 @@ int parse_mapping(Config *config, DownstreamAddrConfig &addr,
*p = '\0';
pattern = StringRef{iov.base, p};
} else {
auto path = http2::normalize_path(downstreamconf.balloc,
StringRef{slash, std::end(raw_pattern)},
StringRef{});
auto path = http2::normalize_path_colon(
downstreamconf.balloc, StringRef{slash, std::end(raw_pattern)},
StringRef{});
auto iov = make_byte_ref(downstreamconf.balloc,
std::distance(std::begin(raw_pattern), slash) +
path.size() + 1);