libfilezilla
https.cpp

Demonstrates how to use the fz::https::client

#include <libfilezilla/http/client.hpp>
using namespace std::literals;
typedef fz::http::client::request_response_holder<fz::http::client::request, fz::http::client::response> request_response;
class client : public fz::event_handler, public fz::http::client::client
{
public:
client(std::vector<fz::uri> uris, fz::event_loop & loop, fz::aio_buffer_pool & buffer_pool, fz::logger_interface & logger)
, fz::http::client::client(*this, buffer_pool, logger, "libfilezilla_https_demo")
, logger_(logger)
, trust_store_(pool_)
{
for (auto const& uri : uris) {
auto srr = std::make_shared<request_response>();
srr->request_.uri_ = uri;
srr->request_.headers_["Connection"] = "keep-alive";
if (add_request(srr)) {
requests_.push_back(srr);
}
}
if (requests_.empty()) {
event_loop_.stop();
}
}
~client()
{
remove_handler();
fz::http::client::client::stop(false);
}
virtual fz::socket_interface* create_socket(fz::native_string const& host, unsigned short, bool tls) override
{
destroy_socket();
socket_ = std::make_unique<fz::socket>(pool_, nullptr);
if (tls) {
tls_ = std::make_unique<fz::tls_layer>(event_loop_, nullptr, *socket_, &trust_store_, logger_);
tls_->client_handshake({}, {}, host);
return tls_.get();
}
else {
return socket_.get();
}
}
virtual void destroy_socket() override
{
tls_.reset();
socket_.reset();
}
virtual void operator()(fz::event_base const& ev) override
{
fz::dispatch<fz::http::client::done_event>(ev, this, &client::on_request_done);
}
void on_request_done(uint64_t, bool success)
{
auto & srr = requests_.front();
if (success) {
logger_.log(fz::logmsg::error, "Got response for %s with code %d", srr->req().uri_.to_string(), srr->res().code_);
}
else {
logger_.log(fz::logmsg::error, "Could not read response for %s", srr->req().uri_.to_string());
}
requests_.pop_front();
if (requests_.empty()) {
event_loop_.stop();
}
}
std::unique_ptr<fz::socket> socket_;
std::unique_ptr<fz::tls_layer> tls_;
std::deque<fz::http::client::shared_request_response> requests_;
};
int main(int argc , char * argv[])
{
if (argc < 2) {
logger.log(fz::logmsg::error, "Pass at least one URI"sv);
return 1;
}
std::vector<fz::uri> uris;
for (int i = 1; i < argc; ++i) {
auto uri = fz::uri(argv[i]);
if (!uri) {
logger.log(fz::logmsg::error, "Invalid URI: '%s'", argv[i]);
return 1;
}
uris.emplace_back(std::move(uri));
}
// Start an event loop
fz::event_loop loop(fz::event_loop::threadless);
//logger.set_all(fz::logmsg::type(-1));
// Create a handler
fz::aio_buffer_pool buffer_pool(logger, 8);
client c(uris, loop, buffer_pool, logger);
loop.run();
// All done.
return 0;
}
Buffer management and wait machinery for asynchronous I/O.
A buffer pool for use with async readers/writers.
Definition: aio.hpp:132
Common base class for all events.
Definition: event.hpp:23
Simple handler for asynchronous event processing.
Definition: event_handler.hpp:55
A threaded event loop that supports sending events and timers.
Definition: event_loop.hpp:34
Abstract interface for logging strings.
Definition: logger.hpp:51
void log(logmsg::type t, String &&fmt, Args &&...args)
Definition: logger.hpp:69
Interface for sockets.
Definition: socket.hpp:375
A simple logger that writes to stdout.
Definition: logger.hpp:183
A dumb thread-pool for asynchronous tasks.
Definition: thread_pool.hpp:64
Opaque class to load the system trust store asynchronously.
Definition: tls_system_trust_store.hpp:30
The uri class is used to decompose URIs into their individual components.
Definition: uri.hpp:22
Declares the event_handler class.
Interface for logging.
@ error
Error messages aimed at the user.
Definition: logger.hpp:21
std::wstring native_string
A string in the system's native character type and encoding. Note: This typedef changes depending on...
Definition: string.hpp:34
Socket classes for networking.
A Transport Layer Security (TLS) layer.
System trust store for TLS certificates.