mirror of
https://github.com/yhirose/cpp-httplib.git
synced 2026-10-26 12:24:46 +00:00
Remove dot segments from absolute redirect locations (#2648)
resolve_relative_location removed "." and ".." segments only from a relative-path Location. A Location that starts with "/" or an absolute URI was requested as is, so a redirect to /dir/../target went out as /dir/../target and a server that does not normalize the path answered 404. RFC 3986 section 5.2.2 applies remove_dot_segments to the target path of every reference that has a path, and Go and urllib3 do the same. The loop now lives in detail::remove_dot_segments, and ClientImpl::redirect applies it to an absolute path as well. Relative locations resolve as before.
This commit is contained in:
1 parent
8710fbd25d
commit
252dbaa505
2 files changed
+75
-20
No files matched your search
@@ -20593,6 +20593,51 @@ TEST(RedirectTest, ResolveRelativeLocation) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(RedirectTest, RemoveDotSegments) {
|
||||
// RFC 3986 section 5.2.4
|
||||
EXPECT_EQ("/a/g", detail::remove_dot_segments("/a/b/c/./../../g"));
|
||||
EXPECT_EQ("/mid/6", detail::remove_dot_segments("/mid/content=5/../6"));
|
||||
EXPECT_EQ("/g", detail::remove_dot_segments("/./g"));
|
||||
EXPECT_EQ("/g", detail::remove_dot_segments("/../g"));
|
||||
EXPECT_EQ("/", detail::remove_dot_segments("/.."));
|
||||
EXPECT_EQ("/a/", detail::remove_dot_segments("/a/b/.."));
|
||||
EXPECT_EQ("/a/b", detail::remove_dot_segments("/a/b"));
|
||||
}
|
||||
|
||||
TEST(RedirectTest, AbsoluteLocationIsNormalized) {
|
||||
Server svr;
|
||||
|
||||
svr.Get("/absolute-path", [](const Request & /*req*/, Response &res) {
|
||||
res.set_redirect("/dir/../target?x=1");
|
||||
});
|
||||
svr.Get("/absolute-uri", [](const Request & /*req*/, Response &res) {
|
||||
res.set_redirect("http://localhost:" + std::to_string(PORT) +
|
||||
"/dir/./../target");
|
||||
});
|
||||
svr.Get("/target", [](const Request &req, Response &res) {
|
||||
res.set_content(req.path, "text/plain");
|
||||
});
|
||||
|
||||
auto th = std::thread([&]() { svr.listen("localhost", PORT); });
|
||||
auto se = detail::scope_exit([&] {
|
||||
svr.stop();
|
||||
th.join();
|
||||
ASSERT_FALSE(svr.is_running());
|
||||
});
|
||||
|
||||
svr.wait_until_ready();
|
||||
|
||||
Client cli("localhost", PORT);
|
||||
cli.set_follow_location(true);
|
||||
|
||||
for (auto path : {"/absolute-path", "/absolute-uri"}) {
|
||||
auto res = cli.Get(path);
|
||||
ASSERT_TRUE(res) << path << ": " << to_string(res.error());
|
||||
EXPECT_EQ(StatusCode::OK_200, res->status) << path;
|
||||
EXPECT_EQ("/target", res->body) << path;
|
||||
}
|
||||
}
|
||||
|
||||
TEST(RedirectTest, RelativeLocationWithoutLeadingSlash) {
|
||||
Server svr;
|
||||
|
||||
|
||||
Reference in new issue
Block a user