You are right, Asio and Asio based libraries are usually heavily templated as they need to work with generic executors, buffers and stream types. There are new facilities in Asio for alleviating this issue like any_executor and any_completion_handler which you can utilize to implement async operations in a source file.
I'll look into it, thanks. (Though thankfully the wrapper strategy does work, and has the advantage of accommodating other HTTP libraries.)
You don't need to pass a socket to acceptor, it has multiple overloads: https://www.boost.org/doc/libs/1_84_0/doc/html/boost_asio/reference/basic_so...
One of them creates a socket and passes it to the completion token, so, you can use it like: acceptor.async_accept([](auto ec, auto socket){ // ... });
Oh of course, that makes sense now: there are two "types" of sockets: - One that accepts connections (under some TCP port number) - One that *already* accepted a connection, and can send & receive messages. This API that creates the socket in the callback makes much more sense under this mental model. Thank you, Loup.