mirror of
https://github.com/yhirose/cpp-httplib
synced 2024-11-21 06:26:02 -07:00
Added hosted_at
. (Resolve #1113)
This commit is contained in:
parent
27d128bbb4
commit
65a8f4cf44
2 changed files with 87 additions and 10 deletions
67
httplib.h
67
httplib.h
|
@ -1657,6 +1657,10 @@ Client::set_write_timeout(const std::chrono::duration<Rep, Period> &duration) {
|
|||
* .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::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,
|
||||
BindOrConnect bind_or_connect) {
|
||||
// Get address info
|
||||
const char *node = nullptr;
|
||||
struct addrinfo hints;
|
||||
struct addrinfo *result;
|
||||
|
||||
memset(&hints, 0, sizeof(struct addrinfo));
|
||||
hints.ai_family = address_family;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_flags = socket_flags;
|
||||
hints.ai_protocol = 0;
|
||||
|
||||
// Ask getaddrinfo to convert IP in c-string to address
|
||||
if (ip[0] != '\0') {
|
||||
node = ip;
|
||||
// Ask getaddrinfo to convert IP in c-string to address
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_flags = AI_NUMERICHOST;
|
||||
} else {
|
||||
node = host;
|
||||
hints.ai_family = address_family;
|
||||
hints.ai_flags = socket_flags;
|
||||
}
|
||||
|
||||
auto service = std::to_string(port);
|
||||
|
||||
if (ip[0] != '\0' ? getaddrinfo(ip, service.c_str(), &hints, &result)
|
||||
: getaddrinfo(host, service.c_str(), &hints, &result)) {
|
||||
if (getaddrinfo(node, service.c_str(), &hints, &result)) {
|
||||
#if defined __linux__ && !defined __ANDROID__
|
||||
res_init();
|
||||
#endif
|
||||
|
@ -2728,7 +2735,7 @@ inline socket_t create_client_socket(
|
|||
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,
|
||||
int &port) {
|
||||
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) {
|
||||
port =
|
||||
ntohs(reinterpret_cast<const struct sockaddr_in6 *>(&addr)->sin6_port);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::array<char, NI_MAXHOST> ipstr{};
|
||||
if (!getnameinfo(reinterpret_cast<const struct sockaddr *>(&addr), addr_len,
|
||||
ipstr.data(), static_cast<socklen_t>(ipstr.size()), nullptr,
|
||||
0, NI_NUMERICHOST)) {
|
||||
ip = ipstr.data();
|
||||
if (getnameinfo(reinterpret_cast<const struct sockaddr *>(&addr), addr_len,
|
||||
ipstr.data(), static_cast<socklen_t>(ipstr.size()), nullptr,
|
||||
0, NI_NUMERICHOST)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ip = ipstr.data();
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void get_remote_ip_and_port(socket_t sock, std::string &ip, int &port) {
|
||||
|
@ -4304,6 +4316,41 @@ private:
|
|||
|
||||
} // 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) {
|
||||
std::string path_with_query = path;
|
||||
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);
|
||||
}
|
||||
|
||||
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) {
|
||||
auto host = "www.httpwatch.com";
|
||||
|
||||
|
|
Loading…
Reference in a new issue