Skip to content

Commit 80fb036

Browse files
authored
Only match path params that span full path segment (#1919)
* Only match path params that span full path segment * Fix C++11 build
1 parent 2480c03 commit 80fb036

File tree

2 files changed

+19
-5
lines changed

2 files changed

+19
-5
lines changed

httplib.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -840,7 +840,6 @@ class PathParamsMatcher final : public MatcherBase {
840840
bool match(Request &request) const override;
841841

842842
private:
843-
static constexpr char marker = ':';
844843
// Treat segment separators as the end of path parameter capture
845844
// Does not need to handle query parameters as they are parsed before path
846845
// matching
@@ -5887,6 +5886,8 @@ inline socket_t BufferStream::socket() const { return 0; }
58875886
inline const std::string &BufferStream::get_buffer() const { return buffer; }
58885887

58895888
inline PathParamsMatcher::PathParamsMatcher(const std::string &pattern) {
5889+
static constexpr char marker[] = "/:";
5890+
58905891
// One past the last ending position of a path param substring
58915892
std::size_t last_param_end = 0;
58925893

@@ -5899,13 +5900,14 @@ inline PathParamsMatcher::PathParamsMatcher(const std::string &pattern) {
58995900
#endif
59005901

59015902
while (true) {
5902-
const auto marker_pos = pattern.find(marker, last_param_end);
5903+
const auto marker_pos = pattern.find(
5904+
marker, last_param_end == 0 ? last_param_end : last_param_end - 1);
59035905
if (marker_pos == std::string::npos) { break; }
59045906

59055907
static_fragments_.push_back(
5906-
pattern.substr(last_param_end, marker_pos - last_param_end));
5908+
pattern.substr(last_param_end, marker_pos - last_param_end + 1));
59075909

5908-
const auto param_name_start = marker_pos + 1;
5910+
const auto param_name_start = marker_pos + 2;
59095911

59105912
auto sep_pos = pattern.find(separator, param_name_start);
59115913
if (sep_pos == std::string::npos) { sep_pos = pattern.length(); }
@@ -5967,7 +5969,7 @@ inline bool PathParamsMatcher::match(Request &request) const {
59675969
request.path_params.emplace(
59685970
param_name, request.path.substr(starting_pos, sep_pos - starting_pos));
59695971

5970-
// Mark everythin up to '/' as matched
5972+
// Mark everything up to '/' as matched
59715973
starting_pos = sep_pos + 1;
59725974
}
59735975
// Returns false if the path is longer than the pattern

test/test.cc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7599,6 +7599,18 @@ TEST(PathParamsTest, SequenceOfParams) {
75997599
EXPECT_EQ(request.path_params, expected_params);
76007600
}
76017601

7602+
TEST(PathParamsTest, SemicolonInTheMiddleIsNotAParam) {
7603+
const auto pattern = "/prefix:suffix";
7604+
detail::PathParamsMatcher matcher(pattern);
7605+
7606+
Request request;
7607+
request.path = "/prefix:suffix";
7608+
ASSERT_TRUE(matcher.match(request));
7609+
7610+
const std::unordered_map<std::string, std::string> expected_params = {};
7611+
EXPECT_EQ(request.path_params, expected_params);
7612+
}
7613+
76027614
TEST(UniversalClientImplTest, Ipv6LiteralAddress) {
76037615
// If ipv6 regex working, regex match codepath is taken.
76047616
// else port will default to 80 in Client impl

0 commit comments

Comments
 (0)