diff --git a/httplib.h b/httplib.h index 751aa92b69..d3a1a61cc6 100644 --- a/httplib.h +++ b/httplib.h @@ -2854,8 +2854,7 @@ inline socket_t create_client_socket( } inline bool get_ip_and_port(const struct sockaddr_storage &addr, - socklen_t addr_len, std::string &ip, - int &port) { + socklen_t addr_len, std::string &ip, int &port) { if (addr.ss_family == AF_INET) { port = ntohs(reinterpret_cast(&addr)->sin_port); } else if (addr.ss_family == AF_INET6) { @@ -3353,7 +3352,11 @@ inline bool parse_header(const char *beg, const char *end, T fn) { } if (p < end) { - fn(std::string(beg, key_end), decode_url(std::string(p, end), false)); + std::string key(beg, key_end); + std::string rawValue(p, end); + std::string value = + key == "Location" ? std::move(rawValue) : decode_url(rawValue, false); + fn(std::move(key), std::move(value)); return true; } @@ -4536,8 +4539,8 @@ inline void hosted_at(const std::string &hostname, *reinterpret_cast(rp->ai_addr); std::string ip; int dummy = -1; - if (detail::get_ip_and_port(addr, sizeof(struct sockaddr_storage), - ip, dummy)) { + if (detail::get_ip_and_port(addr, sizeof(struct sockaddr_storage), ip, + dummy)) { addrs.push_back(ip); } } @@ -7443,7 +7446,7 @@ inline void SSLSocketStream::get_remote_ip_and_port(std::string &ip, } inline void SSLSocketStream::get_local_ip_and_port(std::string &ip, - int &port) const { + int &port) const { detail::get_local_ip_and_port(sock_, ip, port); } diff --git a/test/test.cc b/test/test.cc index 88937ce852..1f08f476bc 100644 --- a/test/test.cc +++ b/test/test.cc @@ -5597,3 +5597,41 @@ TEST(TaskQueueTest, IncreaseAtomicInteger) { EXPECT_NO_THROW(task_queue->shutdown()); EXPECT_EQ(number_of_task, count.load()); } + +TEST(ParseHeader, LocationValueDecoding) { + static const std::string URL( + "https://stitcher2.acast.com/livestitches/" + "4d4cc4fe72c9452bd0b0992a5c89e434.mp3?aid=63a4721c69c77e001126ad39&chid=" + "a8879bdf-de58-4537-8dab-a3bb13948786&ci=" + "oFpQlSRp3GFDZwrcZw5e3SEuFWtGfBXjcj6-mtxC8TJYKWNWTP3KWg%3D%3D&pf=rss&sv=" + "sphinx%401.134.1&uid=6ec01abdba610f88f88e42ff560ecdef&Expires=" + "1672109987714&Key-Pair-Id=K38CTQXUSD0VVB&Signature=TQXsBs7XluU~" + "YRtPTcYe1EtVuvnkf542tbp1p7KUnvn24rm-tQjO8dYgLSbXlJCBwsiPtbnJc-" + "YjLbGlaVLKDzzfABj2lCldE-KoeUSdnEQPWXdPK6FK5BR7kuN-CuY1MfQ-" + "0sDa4MTGAErHZZB1p3~jiiZbbP7fYd9ttBfXwlZgjv5BtHOL4KQs7QY7q-~" + "ZP5tXoGhtufPMruWRYOptrves991ax5lgKPwTvzhXSL6CEKpHWoAMi88shXnBBC~" + "f2iOropB-yzcj5K-uaK6LPcObfHh9Akgl~uIAqbLka2Nrq-HQ-" + "7QrMIUmFcA2nTEaAF66dGRj7AGtEkS2m2hB4A__"); + static const std::string Location("Location"); + static const std::string testLocation(Location + ":" + URL); + + // test Location URL is preserved + httplib::detail::parse_header( + testLocation.data(), testLocation.data() + testLocation.size(), + [&](std::string const &key, std::string const &value) { + EXPECT_EQ(key, Location); + EXPECT_EQ(value, URL); + EXPECT_NE(value, httplib::detail::decode_url(URL, false)); + }); + + // test non-Location URL is decoded + static const std::string Other("Other"); + static const std::string testOther(Other + ":" + URL); + httplib::detail::parse_header( + testOther.data(), testOther.data() + testOther.size(), + [&](std::string const &key, std::string const &value) { + EXPECT_EQ(key, Other); + EXPECT_EQ(value, httplib::detail::decode_url(URL, false)); + EXPECT_NE(value, URL); + }); +}