基于Boost.ASIO的HTTP客户端库(类似于libcurl)

62

我正在寻找一款现代的C++ HTTP库,因为libcurl的缺点很难通过C++封装来解决。首选基于Boost.ASIO的解决方案,它已成为事实上的C++ TCP库。


5
嗨,我在想你最终使用了什么?我有一个类似的情况(需要C ++ HTTP客户端)。你最后是使用下面提出的C ++网络库还是其他库?谢谢。 - skimobear
是的,我使用了cpp-netlib。它相当简约(或者说非常简约的文档缺少一些功能),正因为如此,你必须手动完成一些任务,比如HTTP基本身份验证(添加适当的标头而不是指定登录/密码)。如果他们继续开发下去,那将会非常好,目前它肯定可用(而且只需包含头文件是一个很大的优点)。 - Tronic
3
记录一下,最近我在使用cpp-netlib时遇到了问题,因为它编译时间太长了,即使是最简单的东西(使用GCC),也需要超过1GB的内存。所以至少要将您的get/post函数隔离到一个单独的源模块中,您永远不需要修改或重新编译它,并且不要在除实现该模块之外的任何地方包含此库。 - Tronic
4
两年来发生了很多事情,显然cpp-netlib正在取得明显领先。它现在可以作为库构建,避免由头文件模式引起的过度编译时间。API现在支持基于Boost.Thread和futures的“准”异步模式。还支持流式传输主体(对于大型文档很重要),API仍然易于使用,并且这个库似乎拥有最大的功能集合。 - Tronic
我有一个小项目正在进行中,是我在空闲时间开发的,但它还处于早期阶段。https://github.com/tghosgor/libashttp - Etherealone
6个回答

30

前几天有人在另一篇帖子中推荐了这个东西:

http://cpp-netlib.github.com/

我认为这是你能找到的最高级别的东西,但我不确定它是否已经成熟了(他们提议将其包含在 Boost 中,所以我认为可能已经成熟了)。


9
我花了相当一段时间才使它运作起来,结果发现目前还不支持HTTPS。显然这个项目还没有成熟,而且未来可能也不会。 - Homer6
1
不幸的是,如果它能正常工作就太好了。它缺乏很多功能,而且当我最后一次使用它时,在分块响应上它非常卡顿。这让我非常难过,因为这个库的用户界面设计非常简单且颇受欢迎。 - Bob9630
这个库非常简单,只是用于从HTTP服务器获取文件或构建自己的简单HTTP服务器/客户端。但这恰恰是我所需要的!Libcurl经常过度设计。 - vitakot
1
有趣的是,该库方便地占用了 boost::network 命名空间,但实际上与 Boost 没有任何关系,并且由于质量问题,也很难被 Boost 接受。 - rustyx

27
虽然晚了一些,但这里有一个关于一个旧问题的新答案。有一个名叫 Boost.Beast 的新开源库,它使用 Boost.Asio 提供 HTTP 和 WebSocket 功能。它尽可能地模拟了熟悉的 Asio 接口,并且有大量文档。它可以使用 bjam 或 CMake 在 clang、gcc 和 Visual Studio 上构建 - 由您选择!请注意,我也是这个库的作者。
以下是一个完整的示例程序,用于检索网页:https://github.com/boostorg/beast/
#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;
}

3
我添加了一条注释,解释我是作者。 - Vinnie Falco
3
也许值得更新一下,说明Beast虽然在撰写本文时仍处于beta版本,但已被接受并纳入Boost?请参考http://www.boost.org/doc/libs/develop/libs/beast/doc/html/beast.html。恭喜作者! - Tommy
1
是的,它支持HTTPS:https://github.com/boostorg/beast/blob/65022367bb53ab1e77d2aca7fbb264b3547be331/example/http/client/sync-ssl/http_client_sync_ssl.cpp - Vinnie Falco
@VinnieFalco 我正在尝试进行10个GET请求。我想让它们异步工作,并且当每个请求完成获取文件时,我希望每个请求都返回一个字符串作为future。我想将这些futures收集到容器中,并使用boost wait_for_any来处理每个文件的字符串准备就绪时的情况。我该如何实现这一点?我尝试使用async_composed函数返回future,但它返回的是不受wait_for_any支持的std::future。我为每个文件实现了协程函数,它可以工作,但现在我想进行修改以允许返回future,我该怎么办? - ahmed allam
使用Boost未来替代std未来,Asio中有一个编译器标志可以实现此功能。 - Vinnie Falco
显示剩余2条评论

9

现在,2012年,这个项目似乎已经死了,因为我能找到的页面自2009年以来就没有更新过。而且异步接口非常低级(像asio一样),因此不太用户友好。功能非常简单,文档也非常简单。 - Tronic
是的,但它真的有效。 - Ken

5

我终于仔细看了一下,但似乎只是服务器端的(尽管从文档中并不完全清楚)。文档非常简洁,但至少代码似乎在积极维护。 - Tronic
已经使用Pion库8个月了。主要使用服务器组件,但也用作客户端。两者都运行得非常好。到目前为止遇到的唯一问题是HttpResponse类的最大内容大小(1MB)。我们不得不从HttpResponse派生以设置更高的限制。服务器非常稳定。 - Scottymac

2

2
然而,目前这仅限于服务器端。 - Xoph

1

有一个项目试图“Boostify” libcurl: https://github.com/breese/trial.url

我将使用此作为参考来设计 Boost.Http 客户端 API。但是,我计划专注于高级抽象,并尽可能与 Beast.HTTP 作者合作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接