This commit is contained in:
yhirose 2021-07-14 22:49:49 -04:00
parent 3d83cbb872
commit 06bfa7e08b
2 changed files with 79 additions and 18 deletions

View file

@ -5611,7 +5611,7 @@ inline bool ClientImpl::redirect(Request &req, Response &res, Error &error) {
if (location.empty()) { return false; }
const static std::regex re(
R"(^(?:(https?):)?(?://([^:/?#]*)(?::(\d+))?)?([^?#]*(?:\?[^#]*)?)(?:#.*)?)");
R"((?:(https?):)?(?://(?:\[([\d:]+)\]|([^:/?#]+))(?::(\d+))?)?([^?#]*(?:\?[^#]*)?)(?:#.*)?)");
std::smatch m;
if (!std::regex_match(location, m, re)) { return false; }
@ -5620,8 +5620,9 @@ inline bool ClientImpl::redirect(Request &req, Response &res, Error &error) {
auto next_scheme = m[1].str();
auto next_host = m[2].str();
auto port_str = m[3].str();
auto next_path = m[4].str();
if (next_host.empty()) { next_host = m[3].str(); }
auto port_str = m[4].str();
auto next_path = m[5].str();
auto next_port = port_;
if (!port_str.empty()) {
@ -7266,7 +7267,8 @@ inline Client::Client(const char *scheme_host_port)
inline Client::Client(const char *scheme_host_port,
const std::string &client_cert_path,
const std::string &client_key_path) {
const static std::regex re(R"(^(?:([a-z]+)://)?([^:/?#]+)(?::(\d+))?)");
const static std::regex re(
R"((?:([a-z]+):\/\/)?(?:\[([\d:]+)\]|([^:/?#]+))(?::(\d+))?)");
std::cmatch m;
if (std::regex_match(scheme_host_port, m, re)) {
@ -7285,8 +7287,9 @@ inline Client::Client(const char *scheme_host_port,
auto is_ssl = scheme == "https";
auto host = m[2].str();
if (host.empty()) { host = m[3].str(); }
auto port_str = m[3].str();
auto port_str = m[4].str();
auto port = !port_str.empty() ? std::stoi(port_str) : (is_ssl ? 443 : 80);
if (is_ssl) {

View file

@ -839,6 +839,18 @@ TEST(HttpsToHttpRedirectTest3, Redirect) {
EXPECT_EQ(200, res->status);
}
TEST(UrlWithSpace, Redirect) {
SSLClient cli("edge.forgecdn.net");
cli.set_follow_location(true);
auto res = cli.Get("/files/2595/310/Neat 1.4-17.jar");
ASSERT_TRUE(res);
EXPECT_EQ(200, res->status);
EXPECT_EQ(18527, res->get_header_value<uint64_t>("Content-Length"));
}
#endif
TEST(RedirectToDifferentPort, Redirect) {
Server svr8080;
Server svr8081;
@ -878,16 +890,6 @@ TEST(RedirectToDifferentPort, Redirect) {
ASSERT_FALSE(svr8081.is_running());
}
TEST(UrlWithSpace, Redirect) {
SSLClient cli("edge.forgecdn.net");
cli.set_follow_location(true);
auto res = cli.Get("/files/2595/310/Neat 1.4-17.jar");
ASSERT_TRUE(res);
EXPECT_EQ(200, res->status);
EXPECT_EQ(18527, res->get_header_value<uint64_t>("Content-Length"));
}
TEST(RedirectFromPageWithContent, Redirect) {
Server svr;
@ -943,7 +945,61 @@ TEST(RedirectFromPageWithContent, Redirect) {
ASSERT_FALSE(svr.is_running());
}
#endif
TEST(RedirectFromPageWithContentIP6, Redirect) {
Server svr;
svr.Get("/1", [&](const Request & /*req*/, Response &res) {
res.set_content("___", "text/plain");
// res.set_redirect("/2");
res.set_redirect("http://[::1]:1234/2");
});
svr.Get("/2", [&](const Request & /*req*/, Response &res) {
res.set_content("Hello World!", "text/plain");
});
auto th = std::thread([&]() { svr.listen("::1", 1234); });
while (!svr.is_running()) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
// Give GET time to get a few messages.
std::this_thread::sleep_for(std::chrono::seconds(1));
{
Client cli("http://[::1]:1234");
cli.set_follow_location(true);
std::string body;
auto res = cli.Get("/1", [&](const char *data, size_t data_length) {
body.append(data, data_length);
return true;
});
ASSERT_TRUE(res);
EXPECT_EQ(200, res->status);
EXPECT_EQ("Hello World!", body);
}
{
Client cli("http://[::1]:1234");
std::string body;
auto res = cli.Get("/1", [&](const char *data, size_t data_length) {
body.append(data, data_length);
return true;
});
ASSERT_TRUE(res);
EXPECT_EQ(302, res->status);
EXPECT_EQ("___", body);
}
svr.stop();
th.join();
ASSERT_FALSE(svr.is_running());
}
TEST(PathUrlEncodeTest, PathUrlEncode) {
Server svr;
@ -2717,10 +2773,12 @@ TEST_F(ServerTest, PutLargeFileWithGzip) {
TEST_F(ServerTest, PutLargeFileWithGzip2) {
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
Client cli("https://localhost:1234");
std::string s = std::string("https://") + HOST + ":" + std::to_string(PORT);
Client cli(s.c_str());
cli.enable_server_certificate_verification(false);
#else
Client cli("http://localhost:1234");
std::string s = std::string("http://") + HOST + ":" + std::to_string(PORT);
Client cli(s.c_str());
#endif
cli.set_compress(true);