29std::string
http_get(
const std::string& host,
const std::string& path,
30 std::chrono::milliseconds timeout)
32 struct addrinfo hints{};
33 hints.ai_family = AF_UNSPEC;
34 hints.ai_socktype = SOCK_STREAM;
35 struct addrinfo* res =
nullptr;
36 if (getaddrinfo(host.c_str(),
"80", &hints, &res) != 0 || !res)
return {};
38 int fd = ::socket(res->ai_family, res->ai_socktype, res->ai_protocol);
39 if (fd < 0) { freeaddrinfo(res);
return {}; }
43 tv.tv_sec = timeout.count() / 1000;
44 tv.tv_usec = (timeout.count() % 1000) * 1000;
45 ::setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv,
sizeof(tv));
46 ::setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv,
sizeof(tv));
48 if (::connect(fd, res->ai_addr, res->ai_addrlen) < 0) {
49 ::close(fd); freeaddrinfo(res);
return {};
53 std::string req =
"GET " + path +
" HTTP/1.0\r\n";
54 req +=
"Host: " + host +
"\r\n";
55 req +=
"User-Agent: BastionGuard-SC/1.0\r\n";
56 req +=
"Connection: close\r\n\r\n";
57 if (::send(fd, req.data(), req.size(), 0) < 0) { ::close(fd);
return {}; }
62 ssize_t n = ::recv(fd, buf,
sizeof(buf), 0);
64 response.append(buf,
static_cast<size_t>(n));
65 if (response.size() > 64 * 1024)
break;
70 const auto sep = response.find(
"\r\n\r\n");
71 if (sep == std::string::npos)
return {};
72 return response.substr(sep + 4);