Created
July 25, 2021 19:45
-
-
Save niansa/1cd2b593471a377bf7b3a54c10039606 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class HttpClient { | |
std::shared_ptr<coro::io_scheduler> scheduler; | |
coro::net::ip_address addr; | |
std::string host; | |
uint16_t port = 80; | |
std::chrono::milliseconds timeout = std::chrono::milliseconds(5000); | |
public: | |
HttpClient(std::weak_ptr<coro::io_scheduler> sched) : scheduler(sched) {} | |
void set_addr(const std::string& addrStr) { | |
addr = coro::net::ip_address::from_string(addrStr); | |
} | |
void set_addr(const coro::net::ip_address& addr) { | |
this->addr = addr; | |
} | |
coro::generator<bool> set_host(const std::string& host) { | |
this->host = host; | |
// Resolve host | |
coro::net::dns_resolver resolver(scheduler, timeout); | |
auto ips = (co_await resolver.host_by_name(coro::net::hostname(host)))->ip_addresses(); | |
if (ips.empty()) { | |
co_return false; | |
} else { | |
addr = ips[0]; | |
co_return true; | |
} | |
} | |
void set_port(uint16_t port) { | |
this->port = port; | |
} | |
void set_timeout(std::chrono::milliseconds timeout) { | |
this->timeout = timeout; | |
} | |
void set_timeout(time_t timeout) { | |
this->timeout = std::chrono::milliseconds(timeout); | |
} | |
coro::generator<std::span<const char>> send(std::string_view path, std::function<coro::task<bool> (std::span<const char>)> cb) { | |
co_await scheduler->schedule(); | |
// Connect | |
coro::net::tcp_client client{scheduler, { | |
.address = {addr}, | |
.port = port | |
} | |
}; | |
std::cout << addr.to_string() << std::endl; | |
co_await client.connect(timeout); | |
if (!client.socket().is_valid()) { | |
co_return; | |
} | |
// Build request | |
std::string reqStr; | |
{ | |
std::ostringstream req; | |
req << "GET " << path << " HTTP/1.1\n" | |
"Host: " << (host.empty()?addr.to_string():host) << "\n\n"; | |
reqStr = req.str(); | |
} | |
// Send Request | |
std::span<const char> remaining = reqStr; | |
while (true) { | |
auto [send_status, r] = client.send(remaining); | |
if (send_status != coro::net::send_status::ok) { | |
co_return; | |
} | |
if (r.empty()) { | |
break; | |
} | |
remaining = r; | |
auto pstatus = co_await client.poll(coro::poll_op::write, timeout); | |
if (pstatus != coro::poll_status::event) { | |
co_return; | |
} | |
} | |
// Receive response | |
std::vector<char> response(256); | |
while (true) { | |
co_await client.poll(coro::poll_op::read, timeout); | |
auto [recv_status, recv_bytes] = client.recv(response); | |
if (recv_status != coro::net::recv_status::ok) { | |
co_return; // Connection closed | |
} else { | |
co_yield recv_bytes; | |
} | |
} | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment