c++ - 使用 Boost Beast 通过代理发出同步 http 请求时出现问题

标签 c++ boost-asio boost-beast

我修改了 http_sync 示例以通过代理连接,我用 wireshark 进行了测试,问题是在我发送 http 连接请求后,代理返回代码 200 OK,我的程序无法读取,它在 http::read 上等待了大约 1 分钟,然后服务器断开了我的连接。 我试过解决这个问题,只是不读取响应,但是当我尝试进行 ssl 握手时,我得到一个错误:未知协议(protocol)(据 wireshark 显示,我的 ssl 握手发送一个客户端问候,然后我收到完整的服务器问候,但我的程序同时发送了一个 FIN 并给了我错误,我认为这是因为他阅读了 200 OK 而不是服务器的回答并且感到困惑)。 所以我想我的问题是,有没有办法解决这个问题?我不明白为什么 http::read 会卡住。它在没有中间代理的情况下正常工作。 这是我的代码:

using tcp = boost::asio::ip::tcp;       // from <boost/asio/ip/tcp.hpp>
namespace ssl = boost::asio::ssl;       // from <boost/asio/ssl.hpp>
namespace http = boost::beast::http;    // from <boost/beast/http.hpp>


int main(int argc, char** argv)
{
try
{
    // Check command line arguments.
    auto const target = "www.discogs.com:443";
    auto const host = "192.116.142.153";
    auto const port = "443";
    int version = 11;

    // The io_context is required for all I/O
    boost::asio::io_context ioc;

    // These objects perform our I/O

    ssl::context ctx{ ssl::context::sslv23_client };

    load_root_certificates(ctx);

    tcp::resolver resolver{ ioc };
    ssl::stream<tcp::socket> stream{ ioc, ctx };


    tcp::resolver::iterator sock = resolver.resolve("192.116.142.153", "8080");


    boost::asio::connect(stream.next_layer(), sock);

    http::request<http::string_body> req1{ http::verb::connect, target, version };
    req1.set(http::field::host, target);

    http::write(stream.next_layer(), req1);
    boost::beast::flat_buffer buffer;
    http::response<http::dynamic_body> res;
    http::read(stream.next_layer(), buffer, res);

    // Write the message to standard out
    std::cout << res << std::endl;

    // Perform the SSL handshake
    stream.handshake(ssl::stream_base::client);

    // 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(stream, 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(stream, buffer, res);

    // Write the message to standard out
    std::cout << res << std::endl;
    getchar();
    // Gracefully close the stream
    boost::system::error_code ec;
    stream.next_layer().shutdown(boost::asio::ip::tcp::socket::shutdown_send);
    if (ec == boost::asio::error::eof)
    {
        // Rationale:
        // http://stackoverflow.com/questions/25587403/boost-asio-ssl-async-shutdown-always-finishes-with-an-error
        ec.assign(0, ec.category());
    }
    if (ec)
        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;
}

最佳答案

在文档中搜索 proxy 让我找到了 skip() .这导致我使用自己的响应解析器实例:

http::response<http::empty_body> res;
http::parser<false, http::empty_body> p(res);
p.skip(true);
http::read(stream.next_layer(), buffer, p);

行得通。好吧,我将请求目标更改为有效的目标。在这种情况下,我检索了 https://www.boost.org/users/license.html通过您的 Fortinet 代理:

#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/beast.hpp>

using tcp = boost::asio::ip::tcp;    // from <boost/asio/ip/tcp.hpp>
namespace ssl = boost::asio::ssl;    // from <boost/asio/ssl.hpp>
namespace http = boost::beast::http; // from <boost/beast/http.hpp>

static void load_root_certificates(ssl::context &ctx);

int main() try {
    // Check command line arguments.
    auto const target = "www.boost.org:443";
    auto const host = "www.boost.org";
    int version = 11;

    // The io_context is required for all I/O
    boost::asio::io_context ioc;

    // These objects perform our I/O

    ssl::context ctx{ ssl::context::sslv23_client };

    load_root_certificates(ctx);

    tcp::resolver resolver{ ioc };
    ssl::stream<tcp::socket> stream{ ioc, ctx };

    stream.next_layer().connect({boost::asio::ip::address_v4::from_string("192.116.142.153"), 8080});

    {
        http::request<http::string_body> req1{ http::verb::connect, target, version };
        req1.set(http::field::host, target);

        http::write(stream.next_layer(), req1);

        boost::beast::flat_buffer buffer;

        http::response<http::empty_body> res;
        http::parser<false, http::empty_body> p(res);
        p.skip(true);
        http::read(stream.next_layer(), buffer, p);

        // Write the message to standard out
        std::cout << res << std::endl;
    }

    // Perform the SSL handshake
    stream.handshake(ssl::stream_base::client);

    // Set up an HTTP GET request message
    {
        http::request<http::string_body> req{ http::verb::get, "/users/license.html", 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(stream, req);

        boost::beast::flat_buffer buffer;
        http::response<http::dynamic_body> res;
        http::read(stream, buffer, res);
        // Write the message to standard out
        std::cout << res << std::endl;
    }

    getchar();

    // Gracefully close the stream
    boost::system::error_code ec;
    stream.next_layer().shutdown(boost::asio::ip::tcp::socket::shutdown_send);
    if (ec == boost::asio::error::eof) {
        // Rationale:
        // http://stackoverflow.com/questions/25587403/boost-asio-ssl-async-shutdown-always-finishes-with-an-error
        ec.assign(0, ec.category());
    }
    if (ec)
        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;
}


namespace detail {

static void load_root_certificates(ssl::context &ctx, boost::system::error_code &ec) {
    std::string const cert =
        /*  This is the DigiCert root certificate.

            CN = DigiCert High Assurance EV Root CA
            OU = www.digicert.com
            O = DigiCert Inc
            C = US

            Valid to: Sunday, ?November ?9, ?2031 5:00:00 PM

            Thumbprint(sha1):
            5f b7 ee 06 33 e2 59 db ad 0c 4c 9a e6 d3 8f 1a 61 c7 dc 25
        */
        "-----BEGIN CERTIFICATE-----\n"
        "MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs\n"
        "MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n"
        "d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j\n"
        "ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL\n"
        "MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3\n"
        "LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug\n"
        "RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm\n"
        "+9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW\n"
        "PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM\n"
        "xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB\n"
        "Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3\n"
        "hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg\n"
        "EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF\n"
        "MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA\n"
        "FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec\n"
        "nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z\n"
        "eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF\n"
        "hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2\n"
        "Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe\n"
        "vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep\n"
        "+OkuE6N36B9K\n"
        "-----END CERTIFICATE-----\n"
        /*  This is the GeoTrust root certificate.

            CN = GeoTrust Global CA
            O = GeoTrust Inc.
            C = US
            Valid to: Friday, ‎May ‎20, ‎2022 9:00:00 PM

            Thumbprint(sha1):
            ‎de 28 f4 a4 ff e5 b9 2f a3 c5 03 d1 a3 49 a7 f9 96 2a 82 12
        */
        "-----BEGIN CERTIFICATE-----\n"
        "MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs\n"
        "MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n"
        "d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j\n"
        "ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL\n"
        "MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3\n"
        "LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug\n"
        "RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm\n"
        "+9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW\n"
        "PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM\n"
        "xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB\n"
        "Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3\n"
        "hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg\n"
        "EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF\n"
        "MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA\n"
        "FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec\n"
        "nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z\n"
        "eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF\n"
        "hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2\n"
        "Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe\n"
        "vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep\n"
        "+OkuE6N36B9K\n"
        "-----END CERTIFICATE-----\n";

    ctx.add_certificate_authority(boost::asio::buffer(cert.data(), cert.size()), ec);
    if (ec)
        return;
}

} // namespace detail

static void load_root_certificates(ssl::context &ctx) {
    boost::system::error_code ec;
    detail::load_root_certificates(ctx, ec);
    if (ec)
        throw boost::system::system_error{ ec };
}

打印

HTTP/1.1 200 OK


HTTP/1.1 200 OK
Date: Sun, 15 Apr 2018 00:32:52 GMT
Server: Apache/2.2.15 (CentOS)
Accept-Ranges: bytes
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html; charset=UTF-8

8ee3
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
  <title>Boost Software License</title>
  <meta http-equiv="Content-Type" content="text/html; charset=us-ascii" />
  <link rel="icon" href="/favicon.ico" type="image/ico" />
  <link rel="stylesheet" type="text/css" href="../style-v2/section-boost.css" />
  <!--[if IE 7]> <style type="text/css"> body { behavior: url(/style-v2/csshover3.htc); } </style> <![endif]-->
</head><!--
Note: Editing website content is documented at:
https://www.boost.org/development/website_updating.html
-->

<body>
  <div id="heading">
    <div class="heading-inner">
  <div class="heading-placard"></div>

  <h1 class="heading-title">
  <a href="/">
  <img src="/gfx/space.png" alt= "Boost C++ Libraries" class="heading-logo" />
  <span class="heading-boost">Boost</span>
  <span class="heading-cpplibraries">C++ Libraries</span>
  </a></h1>

  <p class="heading-quote">
  <q>...one of the most highly
  regarded and expertly designed C++ library projects in the
  world.</q> <span class="heading-attribution">&mdash; <a href=
  "http://www.gotw.ca/" class="external">Herb Sutter</a> and <a href=
  "http://en.wikipedia.org/wiki/Andrei_Alexandrescu" class="external">Andrei
  Alexandrescu</a>, <a href=
  "http://safari.awprofessional.com/?XmlId=0321113586" class="external">C++
  Coding Standards</a></span></p>
</div>

  </div>

  <div id="body">
    <div id="body-inner">
      <div id="content">
        <div class="section" id="intro">
          <div class="section-0">
            <div class="section-title">
              <h1>Boost Software License</h1>
            </div>

            <div class="section-body">
              <ul class="toc">
                <li><a href="../LICENSE_1_0.txt">License text</a></li>

(剩余部分被剪掉)

关于c++ - 使用 Boost Beast 通过代理发出同步 http 请求时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49837044/

相关文章:

c++ - 即使没有传入消息,Boost ASIO UDP 客户端 async_receive_from 也会调用处理程序

c++ - 如何通过 C++ 中的升压套接字发送 ostream?

c++ - 将 STL 映射存储到 Boost ConstBufferSequence

c++ - 在 TCP 输入或文件更新上使用 boost :asio with select? 阻塞

c++ - 断开连接后重新连接 boost beast (asio) websocket 和 http 连接时出错

c++ - 使用Boost野兽和openssl的async_handshake发生内存泄漏

c++ - 在 C++ 中写入二进制 int 数组,然后在 MATLAB 中读取时出现差异

java - Eclipse 是否必须处理 C++ ABI 兼容性问题?

java - Java 和 C++ 中的整数到字节

c++ - 指针算术变化取决于输出?