62

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.

Tronic
  • 10,250
  • 2
  • 41
  • 53
  • 5
    Hi. just wondering what you ended up using? I have a similar scenario (c++ http client needed). Did you end up using the C++ network library proposed below or another library? thx. – skimobear Sep 14 '10 at 13:31
  • Yeah, I used cpp-netlib. It is rather minimalistic (or the *very* minimalistic documentation is missing features) and because of that you have to do things such as HTTP basic auth by hand (adding the appropriate header rather than specifying login/password). It is going to be very good if they just continue development and it is certainly usable currently (and being header only is a big plus). – Tronic Oct 24 '10 at 00:03
  • 3
    For the record, recently I have run into a problem with cpp-netlib because it takes way too long to compile and you will need more than 1 GB RAM even for the most simple things (with GCC). So at the very least isolate your get/post functions into a separate source module that you never need to modify or recompile, and don't #include this library anywhere else than in the implementation of that. – Tronic Dec 09 '10 at 18:45
  • 4
    A lot has happened in two years and apparently cpp-netlib is taking a clear lead. It can be built as a library now, avoiding those excessive compile times caused by header-only mode. The API now supports kind-of async mode based on Boost.Thread and futures. Streaming the body is also supported (important for large documents), the API is still simple to use and this library appears to have the largest feature set of the pack. – Tronic Mar 19 '12 at 01:02
  • I have a little project going on that I develop on my free time but it is in its early stages. https://github.com/tghosgor/libashttp – Etherealone Feb 04 '15 at 17:44

6 Answers6

30

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).

Community
  • 1
  • 1
Manuel
  • 12,749
  • 1
  • 27
  • 35
  • 9
    I spent a fair amount of time getting this going only to find out that HTTPS is not supported yet. This is clearly not mature yet, if it ever will be. – Homer6 Jul 23 '12 at 18:09
  • 1
    Unfortunately it would be great if it worked. It is missing a lot of functionality and when I last used it, it choked heavily on chunked responses. It made me very sad as the design of the user interfaces for this library are very simple and quite preferred. – Bob9630 Sep 11 '12 at 23:38
  • This library is simple, just for getting files from HTTP servers or to build your own simple HTTP server/client. But that’s exactly what I need! Libcurl is often overkill. – vitakot Oct 30 '12 at 23:07
  • 1
    It's also funny how the library conveniently appropriates the `boost::network` namespace, all the while not having any relation with Boost, nor having much chance of ever being accepted into Boost, given the quality issues. – rustyx Feb 12 '19 at 13:37
27

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;
}
Vinnie Falco
  • 5,173
  • 28
  • 43
  • 3
    I added a note explaining that I am the author. – Vinnie Falco May 31 '17 at 03:34
  • 3
    Maybe worth updating to note that Beast, although still in beta at the time of writing, has been accepted for incorporation into Boost? Cf. http://www.boost.org/doc/libs/develop/libs/beast/doc/html/beast.html Congratulations to the author! – Tommy Sep 21 '17 at 15:45
  • @Vinnie Falco Does it support https ? This example doesn't work with `https://www.example.com/` – Alexandre A. Sep 28 '18 at 11:20
  • I guess I have to build Boost::asio with the OpenSSL :) – Alexandre A. Sep 28 '18 at 11:26
  • 1
    Yes it supports HTTPS: https://github.com/boostorg/beast/blob/65022367bb53ab1e77d2aca7fbb264b3547be331/example/http/client/sync-ssl/http_client_sync_ssl.cpp – Vinnie Falco Sep 29 '18 at 13:12
  • @VinnieFalco i am trying to make 10 get requests.i want to make them work asynchronously,and i want each request to return string as future when it finishes getting the file,i want to gather these futures in container and use boost wait_for_ any to process each file when its string is ready.how can i make this happen?i tried to use async_composed function to return future but it returns std::future which is not supported by wait_for_any. i implemented the function as coroutine for each file and it worked ,but now i want to make modification to allow for returning future,what can i do?? – ahmed allam Apr 24 '20 at 09:29
  • Use the Boost future instead of the std one, there is a compiler flag for that in Asio. – Vinnie Falco Apr 25 '20 at 14:14
9

asio author implement:

Ken
  • 1,141
  • 12
  • 12
  • Now, in 2012, this project appears rather dead as the pages I can find on it haven't been updated since 2009. Also the async interface is very low level (like asio) and thus not very user-friendly. Very minimal functionality, very minimal documentation. – Tronic Mar 19 '12 at 00:53
  • Yes, but it is really worked. – Ken Jul 16 '12 at 00:19
5

You should also check out the Pion Network Library:

http://pion.org/projects/pion-network-library

Mike Dickey
  • 51
  • 1
  • 1
  • I finally had a proper look on this but it appears to be server only (although not entirely clear from the documentation). Very minimal docs but at least the code seems to be actively maintained. – Tronic Mar 19 '12 at 00:57
  • Have been using the Pion library for 8 months. Primarily use the Server components, but have also used it was a client. Both work really well. The only issue encountered so far is the maximum content size (1MB) of the HttpResponse class. We had to derive from HttpResponse in order to set a higher limit. The server is rock solid. – Scottymac Apr 27 '12 at 18:03
2

Boost.Http - a new player here: https://github.com/BoostGSoC14/boost.http, docs - http://boostgsoc14.github.io/boost.http/

Dmitri Sosnik
  • 517
  • 1
  • 12
  • 20
1

There's this project trying to "Boostify" libcurl: https://github.com/breese/trial.url

I'll use this as a reference to design Boost.Http client API. However, I plan to focus on high-level abstractions and try to collaborate as much as possible with Beast.HTTP author.

vinipsmaker
  • 2,215
  • 2
  • 19
  • 33