I am looking for a modern C++ HTTP library because libcurl's shortcomings are difficult to work around by C++ wrappers. Solutions based on Boost.ASIO, which has become the de-facto C++ TCP library, are preferred.
The other day somebody recommended this on another thread:
http://cpp-netlib.github.com/
I think this is as high-level as you will find, but I'm not sure if it's mature enough yet (I would say it probably is since they've proposed it for Boost inclusion).
Better late than never, here's a new answer to an old question. There's this new open source library called Boost.Beast which offers both HTTP and WebSocket functionality using Boost.Asio. It emulates the familiar Asio interfaces as closely as possible, and its got plenty of documentation. It builds on clang, gcc, and Visual Studio using either bjam or CMake - your choice! Note, I am also the author of the library.
https://github.com/boostorg/beast/
Here's a complete example program that retrieves a web page:
#include <boost/beast/core.hpp> #include <boost/beast/http.hpp> #include <boost/beast/version.hpp> #include <boost/asio/connect.hpp> #include <boost/asio/ip/tcp.hpp> #include <cstdlib> #include <iostream> #include <string> using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp> namespace http = boost::beast::http; // from <boost/beast/http.hpp> // Performs an HTTP GET and prints the response int main(int argc, char** argv) { try { // Check command line arguments. if(argc != 4 && argc != 5) { std::cerr << "Usage: http-client-sync <host> <port> <target> [<HTTP version: 1.0 or 1.1(default)>]\n" << "Example:\n" << " http-client-sync www.example.com 80 /\n" << " http-client-sync www.example.com 80 / 1.0\n"; return EXIT_FAILURE; } auto const host = argv[1]; auto const port = argv[2]; auto const target = argv[3]; int version = argc == 5 && !std::strcmp("1.0", argv[4]) ? 10 : 11; // The io_context is required for all I/O boost::asio::io_context ioc; // These objects perform our I/O tcp::resolver resolver{ioc}; tcp::socket socket{ioc}; // Look up the domain name auto const results = resolver.resolve(host, port); // Make the connection on the IP address we get from a lookup boost::asio::connect(socket, results.begin(), results.end()); // Set up an HTTP GET request message http::request<http::string_body> req{http::verb::get, target, version}; req.set(http::field::host, host); req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING); // Send the HTTP request to the remote host http::write(socket, req); // This buffer is used for reading and must be persisted boost::beast::flat_buffer buffer; // Declare a container to hold the response http::response<http::dynamic_body> res; // Receive the HTTP response http::read(socket, buffer, res); // Write the message to standard out std::cout << res << std::endl; // Gracefully close the socket boost::system::error_code ec; socket.shutdown(tcp::socket::shutdown_both, ec); // not_connected happens sometimes // so don't bother reporting it. // if(ec && ec != boost::system::errc::not_connected) throw boost::system::system_error{ec}; // If we get here then the connection is closed gracefully } catch(std::exception const& e) { std::cerr << "Error: " << e.what() << std::endl; return EXIT_FAILURE; } return EXIT_SUCCESS; }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With