Skip to content

Instantly share code, notes, and snippets.

@niansa
Created July 25, 2021 22:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save niansa/b2d589e1ed67c44e753414298f30404c to your computer and use it in GitHub Desktop.
Save niansa/b2d589e1ed67c44e753414298f30404c to your computer and use it in GitHub Desktop.
#include "httpclient.hpp"
#include <cerrno>
coro::task<bool> HttpClient::send(std::string_view path, std::function<coro::task<bool> (std::span<const char>)> cb, const Headers& headers) {
co_await scheduler->schedule();
// Connect
coro::net::tcp_client client{scheduler, {
.address = {addr},
.port = port?port:uint16_t(ssl_context?443:80),
.ssl_ctx = ssl_context.get()
}
};
co_await client.connect(timeout);
if (!client.socket().is_valid()) {
co_return false;
}
if (ssl_context) {
// SSL handshake
if (co_await client.ssl_handshake() != coro::net::ssl_handshake_status::ok) {
co_return false;
}
}
// Build request
std::string reqStr;
{
std::ostringstream req;
req << "GET " << path << " HTTP/1.1\n"
"Host: " << (host.empty()?addr.to_string():host) << "\n";
for (const auto& [key, value] : headers) {
req << key << ": " << value << '\n';
}
req << '\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 false;
}
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 false;
}
}
// 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_await cb(recv_bytes))) {
if (static_cast<int64_t>(recv_status) != EAGAIN) {
co_return recv_status == coro::net::recv_status::closed;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment