mirror of
https://github.com/yhirose/cpp-httplib.git
synced 2025-05-11 21:53:57 +00:00
Added hosted_at
. (Resolve #1113)
This commit is contained in:
parent
27d128bbb4
commit
65a8f4cf44
67
httplib.h
67
httplib.h
@ -1657,6 +1657,10 @@ Client::set_write_timeout(const std::chrono::duration<Rep, Period> &duration) {
|
|||||||
* .h + .cc.
|
* .h + .cc.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
std::string hosted_at(const char *hostname);
|
||||||
|
|
||||||
|
void hosted_at(const char *hostname, std::vector<std::string> &addrs);
|
||||||
|
|
||||||
std::string append_query_params(const char *path, const Params ¶ms);
|
std::string append_query_params(const char *path, const Params ¶ms);
|
||||||
|
|
||||||
std::pair<std::string, std::string> make_range_header(Ranges ranges);
|
std::pair<std::string, std::string> make_range_header(Ranges ranges);
|
||||||
@ -2499,25 +2503,28 @@ socket_t create_socket(const char *host, const char *ip, int port,
|
|||||||
SocketOptions socket_options,
|
SocketOptions socket_options,
|
||||||
BindOrConnect bind_or_connect) {
|
BindOrConnect bind_or_connect) {
|
||||||
// Get address info
|
// Get address info
|
||||||
|
const char *node = nullptr;
|
||||||
struct addrinfo hints;
|
struct addrinfo hints;
|
||||||
struct addrinfo *result;
|
struct addrinfo *result;
|
||||||
|
|
||||||
memset(&hints, 0, sizeof(struct addrinfo));
|
memset(&hints, 0, sizeof(struct addrinfo));
|
||||||
hints.ai_family = address_family;
|
|
||||||
hints.ai_socktype = SOCK_STREAM;
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
hints.ai_flags = socket_flags;
|
|
||||||
hints.ai_protocol = 0;
|
hints.ai_protocol = 0;
|
||||||
|
|
||||||
// Ask getaddrinfo to convert IP in c-string to address
|
|
||||||
if (ip[0] != '\0') {
|
if (ip[0] != '\0') {
|
||||||
|
node = ip;
|
||||||
|
// Ask getaddrinfo to convert IP in c-string to address
|
||||||
hints.ai_family = AF_UNSPEC;
|
hints.ai_family = AF_UNSPEC;
|
||||||
hints.ai_flags = AI_NUMERICHOST;
|
hints.ai_flags = AI_NUMERICHOST;
|
||||||
|
} else {
|
||||||
|
node = host;
|
||||||
|
hints.ai_family = address_family;
|
||||||
|
hints.ai_flags = socket_flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto service = std::to_string(port);
|
auto service = std::to_string(port);
|
||||||
|
|
||||||
if (ip[0] != '\0' ? getaddrinfo(ip, service.c_str(), &hints, &result)
|
if (getaddrinfo(node, service.c_str(), &hints, &result)) {
|
||||||
: getaddrinfo(host, service.c_str(), &hints, &result)) {
|
|
||||||
#if defined __linux__ && !defined __ANDROID__
|
#if defined __linux__ && !defined __ANDROID__
|
||||||
res_init();
|
res_init();
|
||||||
#endif
|
#endif
|
||||||
@ -2728,7 +2735,7 @@ inline socket_t create_client_socket(
|
|||||||
return sock;
|
return sock;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void get_remote_ip_and_port(const struct sockaddr_storage &addr,
|
inline bool get_remote_ip_and_port(const struct sockaddr_storage &addr,
|
||||||
socklen_t addr_len, std::string &ip,
|
socklen_t addr_len, std::string &ip,
|
||||||
int &port) {
|
int &port) {
|
||||||
if (addr.ss_family == AF_INET) {
|
if (addr.ss_family == AF_INET) {
|
||||||
@ -2736,14 +2743,19 @@ inline void get_remote_ip_and_port(const struct sockaddr_storage &addr,
|
|||||||
} else if (addr.ss_family == AF_INET6) {
|
} else if (addr.ss_family == AF_INET6) {
|
||||||
port =
|
port =
|
||||||
ntohs(reinterpret_cast<const struct sockaddr_in6 *>(&addr)->sin6_port);
|
ntohs(reinterpret_cast<const struct sockaddr_in6 *>(&addr)->sin6_port);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::array<char, NI_MAXHOST> ipstr{};
|
std::array<char, NI_MAXHOST> ipstr{};
|
||||||
if (!getnameinfo(reinterpret_cast<const struct sockaddr *>(&addr), addr_len,
|
if (getnameinfo(reinterpret_cast<const struct sockaddr *>(&addr), addr_len,
|
||||||
ipstr.data(), static_cast<socklen_t>(ipstr.size()), nullptr,
|
ipstr.data(), static_cast<socklen_t>(ipstr.size()), nullptr,
|
||||||
0, NI_NUMERICHOST)) {
|
0, NI_NUMERICHOST)) {
|
||||||
ip = ipstr.data();
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ip = ipstr.data();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void get_remote_ip_and_port(socket_t sock, std::string &ip, int &port) {
|
inline void get_remote_ip_and_port(socket_t sock, std::string &ip, int &port) {
|
||||||
@ -4304,6 +4316,41 @@ private:
|
|||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
|
inline std::string hosted_at(const char *hostname) {
|
||||||
|
std::vector<std::string> addrs;
|
||||||
|
hosted_at(hostname, addrs);
|
||||||
|
if (addrs.empty()) { return std::string(); }
|
||||||
|
return addrs[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void hosted_at(const char *hostname, std::vector<std::string> &addrs) {
|
||||||
|
struct addrinfo hints;
|
||||||
|
struct addrinfo *result;
|
||||||
|
|
||||||
|
memset(&hints, 0, sizeof(struct addrinfo));
|
||||||
|
hints.ai_family = AF_UNSPEC;
|
||||||
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
hints.ai_protocol = 0;
|
||||||
|
|
||||||
|
if (getaddrinfo(hostname, nullptr, &hints, &result)) {
|
||||||
|
#if defined __linux__ && !defined __ANDROID__
|
||||||
|
res_init();
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto rp = result; rp; rp = rp->ai_next) {
|
||||||
|
const auto &addr =
|
||||||
|
*reinterpret_cast<struct sockaddr_storage *>(rp->ai_addr);
|
||||||
|
std::string ip;
|
||||||
|
int dummy = -1;
|
||||||
|
if (detail::get_remote_ip_and_port(addr, sizeof(struct sockaddr_storage),
|
||||||
|
ip, dummy)) {
|
||||||
|
addrs.push_back(ip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline std::string append_query_params(const char *path, const Params ¶ms) {
|
inline std::string append_query_params(const char *path, const Params ¶ms) {
|
||||||
std::string path_with_query = path;
|
std::string path_with_query = path;
|
||||||
const static std::regex re("[^?]+\\?.*");
|
const static std::regex re("[^?]+\\?.*");
|
||||||
|
30
test/test.cc
30
test/test.cc
@ -401,6 +401,36 @@ TEST(ChunkedEncodingTest, FromHTTPWatch_Online) {
|
|||||||
EXPECT_EQ(out, res->body);
|
EXPECT_EQ(out, res->body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(HostnameToIPConversionTest, HTTPWatch_Online) {
|
||||||
|
auto host = "www.httpwatch.com";
|
||||||
|
|
||||||
|
{
|
||||||
|
auto ip = hosted_at(host);
|
||||||
|
EXPECT_EQ("191.236.16.12", ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::vector<std::string> addrs;
|
||||||
|
hosted_at(host, addrs);
|
||||||
|
EXPECT_EQ(1u, addrs.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(HostnameToIPConversionTest, YouTube_Online) {
|
||||||
|
auto host = "www.youtube.com";
|
||||||
|
|
||||||
|
{
|
||||||
|
auto ip = hosted_at(host);
|
||||||
|
EXPECT_EQ("2607:f8b0:4006:809::200e", ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::vector<std::string> addrs;
|
||||||
|
hosted_at(host, addrs);
|
||||||
|
EXPECT_EQ(20u, addrs.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TEST(ChunkedEncodingTest, WithContentReceiver_Online) {
|
TEST(ChunkedEncodingTest, WithContentReceiver_Online) {
|
||||||
auto host = "www.httpwatch.com";
|
auto host = "www.httpwatch.com";
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user