network-experiment/bmrshared-web/include/bmrshared/request_response.hpp

104 lines
3.2 KiB
C++

// GNU Lesser General Public License v3.0
// Copyright (c) 2025 Bart Beumer <bart@4beumer.nl>
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License v3.0 as published by
// the Free Software Foundation.
//
#pragma once
#include "server.hpp"
#include <boost/beast.hpp>
#include <functional>
#include <memory>
namespace bmrshared::web
{
class request_response final
{
public:
using response_sender = std::function<void(boost::beast::tcp_stream& stream)>;
using request_type = bmrshared::web::server::request_type;
using callback_on_finalize = std::function<void(response_sender send_response)>;
private:
class response_writer_interface
{
public:
virtual ~response_writer_interface();
virtual void write_response(boost::beast::tcp_stream&) = 0;
};
template<typename response_type>
class response_writer final : public response_writer_interface
{
public:
template<typename... TArgs>
response_writer(TArgs&&... args)
: m_response(std::forward<TArgs>(args)...)
{}
~response_writer() override = default;
void write_response(boost::beast::tcp_stream& stream) override
{
boost::beast::http::write(stream, m_response);
}
response_type& response()
{
return m_response;
}
private:
response_type m_response;
};
class internal_request_response final
{
public:
// Disabling copying and moving.
internal_request_response() = delete;
internal_request_response(const internal_request_response&) = delete;
internal_request_response(internal_request_response&&) = delete;
internal_request_response& operator=(const internal_request_response&) = delete;
internal_request_response& operator=(internal_request_response&&) = delete;
internal_request_response(request_type request, callback_on_finalize cb_finalize);
~internal_request_response();
const request_type& get_request() const;
void set_response_sender(std::unique_ptr<response_writer_interface> response_writer);
private:
request_type m_request;
callback_on_finalize m_cb_finalize;
std::unique_ptr<response_writer_interface> m_response_writer;
};
public:
request_response() = delete;
request_response(const request_response&) = default;
request_response(request_response&&) = default;
request_response& operator=(const request_response&) = default;
request_response& operator=(request_response&&) = default;
request_response(request_type request, callback_on_finalize cb_finalize);
~request_response();
template<typename response_type, typename... arg_types>
response_type& create_response(arg_types&&... args)
{
auto created = std::make_unique<response_writer<response_type>>(std::forward<arg_types>(args)...);
auto& resp = created->response();
m_internal->set_response_sender(std::move(created));
return resp;
}
const request_type& get_request() const;
private:
std::shared_ptr<internal_request_response> m_internal;
};
}