Skip to content

Commit 06bfa7e

Browse files
committed
Fix #979
1 parent 3d83cbb commit 06bfa7e

File tree

2 files changed

+79
-18
lines changed

2 files changed

+79
-18
lines changed

httplib.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5611,7 +5611,7 @@ inline bool ClientImpl::redirect(Request &req, Response &res, Error &error) {
56115611
if (location.empty()) { return false; }
56125612

56135613
const static std::regex re(
5614-
R"(^(?:(https?):)?(?://([^:/?#]*)(?::(\d+))?)?([^?#]*(?:\?[^#]*)?)(?:#.*)?)");
5614+
R"((?:(https?):)?(?://(?:\[([\d:]+)\]|([^:/?#]+))(?::(\d+))?)?([^?#]*(?:\?[^#]*)?)(?:#.*)?)");
56155615

56165616
std::smatch m;
56175617
if (!std::regex_match(location, m, re)) { return false; }
@@ -5620,8 +5620,9 @@ inline bool ClientImpl::redirect(Request &req, Response &res, Error &error) {
56205620

56215621
auto next_scheme = m[1].str();
56225622
auto next_host = m[2].str();
5623-
auto port_str = m[3].str();
5624-
auto next_path = m[4].str();
5623+
if (next_host.empty()) { next_host = m[3].str(); }
5624+
auto port_str = m[4].str();
5625+
auto next_path = m[5].str();
56255626

56265627
auto next_port = port_;
56275628
if (!port_str.empty()) {
@@ -7266,7 +7267,8 @@ inline Client::Client(const char *scheme_host_port)
72667267
inline Client::Client(const char *scheme_host_port,
72677268
const std::string &client_cert_path,
72687269
const std::string &client_key_path) {
7269-
const static std::regex re(R"(^(?:([a-z]+)://)?([^:/?#]+)(?::(\d+))?)");
7270+
const static std::regex re(
7271+
R"((?:([a-z]+):\/\/)?(?:\[([\d:]+)\]|([^:/?#]+))(?::(\d+))?)");
72707272

72717273
std::cmatch m;
72727274
if (std::regex_match(scheme_host_port, m, re)) {
@@ -7285,8 +7287,9 @@ inline Client::Client(const char *scheme_host_port,
72857287
auto is_ssl = scheme == "https";
72867288

72877289
auto host = m[2].str();
7290+
if (host.empty()) { host = m[3].str(); }
72887291

7289-
auto port_str = m[3].str();
7292+
auto port_str = m[4].str();
72907293
auto port = !port_str.empty() ? std::stoi(port_str) : (is_ssl ? 443 : 80);
72917294

72927295
if (is_ssl) {

test/test.cc

Lines changed: 71 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -839,6 +839,18 @@ TEST(HttpsToHttpRedirectTest3, Redirect) {
839839
EXPECT_EQ(200, res->status);
840840
}
841841

842+
TEST(UrlWithSpace, Redirect) {
843+
SSLClient cli("edge.forgecdn.net");
844+
cli.set_follow_location(true);
845+
846+
auto res = cli.Get("/files/2595/310/Neat 1.4-17.jar");
847+
ASSERT_TRUE(res);
848+
EXPECT_EQ(200, res->status);
849+
EXPECT_EQ(18527, res->get_header_value<uint64_t>("Content-Length"));
850+
}
851+
852+
#endif
853+
842854
TEST(RedirectToDifferentPort, Redirect) {
843855
Server svr8080;
844856
Server svr8081;
@@ -878,16 +890,6 @@ TEST(RedirectToDifferentPort, Redirect) {
878890
ASSERT_FALSE(svr8081.is_running());
879891
}
880892

881-
TEST(UrlWithSpace, Redirect) {
882-
SSLClient cli("edge.forgecdn.net");
883-
cli.set_follow_location(true);
884-
885-
auto res = cli.Get("/files/2595/310/Neat 1.4-17.jar");
886-
ASSERT_TRUE(res);
887-
EXPECT_EQ(200, res->status);
888-
EXPECT_EQ(18527, res->get_header_value<uint64_t>("Content-Length"));
889-
}
890-
891893
TEST(RedirectFromPageWithContent, Redirect) {
892894
Server svr;
893895

@@ -943,7 +945,61 @@ TEST(RedirectFromPageWithContent, Redirect) {
943945
ASSERT_FALSE(svr.is_running());
944946
}
945947

946-
#endif
948+
TEST(RedirectFromPageWithContentIP6, Redirect) {
949+
Server svr;
950+
951+
svr.Get("/1", [&](const Request & /*req*/, Response &res) {
952+
res.set_content("___", "text/plain");
953+
// res.set_redirect("/2");
954+
res.set_redirect("http://[::1]:1234/2");
955+
});
956+
957+
svr.Get("/2", [&](const Request & /*req*/, Response &res) {
958+
res.set_content("Hello World!", "text/plain");
959+
});
960+
961+
auto th = std::thread([&]() { svr.listen("::1", 1234); });
962+
963+
while (!svr.is_running()) {
964+
std::this_thread::sleep_for(std::chrono::milliseconds(1));
965+
}
966+
967+
// Give GET time to get a few messages.
968+
std::this_thread::sleep_for(std::chrono::seconds(1));
969+
970+
{
971+
Client cli("http://[::1]:1234");
972+
cli.set_follow_location(true);
973+
974+
std::string body;
975+
auto res = cli.Get("/1", [&](const char *data, size_t data_length) {
976+
body.append(data, data_length);
977+
return true;
978+
});
979+
980+
ASSERT_TRUE(res);
981+
EXPECT_EQ(200, res->status);
982+
EXPECT_EQ("Hello World!", body);
983+
}
984+
985+
{
986+
Client cli("http://[::1]:1234");
987+
988+
std::string body;
989+
auto res = cli.Get("/1", [&](const char *data, size_t data_length) {
990+
body.append(data, data_length);
991+
return true;
992+
});
993+
994+
ASSERT_TRUE(res);
995+
EXPECT_EQ(302, res->status);
996+
EXPECT_EQ("___", body);
997+
}
998+
999+
svr.stop();
1000+
th.join();
1001+
ASSERT_FALSE(svr.is_running());
1002+
}
9471003

9481004
TEST(PathUrlEncodeTest, PathUrlEncode) {
9491005
Server svr;
@@ -2717,10 +2773,12 @@ TEST_F(ServerTest, PutLargeFileWithGzip) {
27172773

27182774
TEST_F(ServerTest, PutLargeFileWithGzip2) {
27192775
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
2720-
Client cli("https://localhost:1234");
2776+
std::string s = std::string("https://") + HOST + ":" + std::to_string(PORT);
2777+
Client cli(s.c_str());
27212778
cli.enable_server_certificate_verification(false);
27222779
#else
2723-
Client cli("http://localhost:1234");
2780+
std::string s = std::string("http://") + HOST + ":" + std::to_string(PORT);
2781+
Client cli(s.c_str());
27242782
#endif
27252783
cli.set_compress(true);
27262784

0 commit comments

Comments
 (0)