目前在做的项目需要一个C++版本的https server,只能求助于boost库。幸运的是确实存在。并且提供了协程版本,本着学习的精神拿来改造一下,就获得了如下成果。
AsyncHttpServerV2.hpp
//
// Created by chuanqin on 7/5/21.
//
#ifndef CBRS_UT_TOOL_ASYNCHTTPSERVERV2_HPP_
#define CBRS_UT_TOOL_ASYNCHTTPSERVERV2_HPP_
#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <memory>
#include <string>
#include <thread>
#include <vector>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/spawn.hpp>
#include <boost/asio/ssl/stream.hpp>
#include <boost/beast/core.hpp>
#include <boost/beast/http.hpp>
#include <boost/beast/version.hpp>
#include <boost/config.hpp>
#include "common/Logger.hpp"
namespace beast = boost::beast;
namespace http = beast::http;
namespace net = boost::asio;
namespace ssl = boost::asio::ssl;
using tcp = boost::asio::ip::tcp;
namespace cbrs
{
namespace ut
{
namespace tool
{
class AsyncHttpServerV2 : public std::enable_shared_from_this<AsyncHttpServerV2>
{
public:
AsyncHttpServerV2(unsigned short port);
~AsyncHttpServerV2() {
}
void start();
void stop();
private:
void load_server_certificate();
void do_listen(
boost::asio::yield_context yield);
void do_session(
tcp::socket &socket,
boost::asio::yield_context yield);
void fail(boost::system::error_code ec, char const *what);
template <class Body, class Allocator, class Send>
void handle_request(
http::request<Body, http::basic_fields<Allocator>> &&req,
Send &&send);
std::string path_cat(boost::beast::string_view base, boost::beast::string_view path);
boost::beast::string_view mime_type(boost::beast::string_view path);
net::ip::address address;
unsigned short port;
std::shared_ptr<std::string> doc_root;
unsigned short threads;
net::io_context ioc;
ssl::context ctx;
std::string tls12CipherSuite;
logging::Logger logger_;
std::string certChain;
std::string privateKey;
std::vector<std::thread> threadList;
};
template <class Stream>
struct send_lambda
{
Stream &stream_;
bool &close_;
boost::system::error_code &ec_;
boost::asio::yield_context yield_;
explicit send_lambda(
Stream &stream,
bool &close,
boost::system::error_code &ec,
boost::asio::yield_context yield)
: stream_(stream), close_(close), ec_(ec), yield_(yield)
{
}
template <bool isRequest, class Body, class Fields>
void operator()(http::message<isRequest, Body, Fields> &&msg) const
{
// Determine if we should close the connection after
close_ = msg.need_eof();
// We need the serializer here because the serializer requires
// a non-const file_body, and the message oriented version of
// http::write only works with const messages.
http::serializer<isRequest, Body, Fields> sr{
msg};
http::async_write(stream_, sr, yield_[ec_]);
}
};
} // namespace tool
} // namespace ut
} // namespace cbrs
#endif // CBRS_UT_TOOL_ASYNCHTTPSERVERV2_HPP_
AsyncHttpServerV2.cpp
#include "AsyncHttpServerV2.hpp"
#include "CertificateInfo.hpp"
#include "common/Logger.hpp"
#include <boost/assert.hpp>
namespace boost
{
void assertion_failed_msg(
char const *expr, char const *msg, char const *function, char const *file, long line)
{
}
} // namespace boost
namespace cbrs
{
namespace ut
{
namespace tool
{
AsyncHttpServerV2::AsyncHttpServerV2(unsigned short port)