简体   繁体   English

使用boost :: asio连接到HTTPS服务器

[英]Connecting to an HTTPS server with boost::asio

I want to connect to an HTTPS server using boost::asio. 我想使用boost :: asio连接到HTTPS服务器。 I managed to successfully shake hands with the server, but I just can't manage to get the server to respond to my POST request. 我成功地与服务器握手,但我无法让服务器响应我的POST请求。

This is the related code (I left out debugging and try-catch to save some space): 这是相关的代码(我省去了调试和try-catch以节省一些空间):

HTTPSClient::HTTPSClient()
{
    ssl::context context(ssl::context::sslv23);
    context.set_verify_mode(ssl::verify_peer);
    context.set_default_verify_paths();
    context.load_verify_file("certificate.pem");
    mSSLSocket = new ssl::stream<ip::tcp::socket>(mIOService, context);
}

void HTTPSClient::SendRequest(const ptree &crPTree, const std::string cHost, 
    const std::string cURI)
{
    tcp::resolver resolver(mIOService);
    tcp::resolver::query query(cHost, "https");
    resolver.async_resolve(query, boost::bind(&HTTPSClient::HandleResolve, this, 
        placeholders::error, placeholders::iterator, request));
}

void HTTPSClient::HandleResolve(const error_code &crError, 
    const iterator &criEndpoints, HTTPSRequest &rRequest)
{
    async_connect(mSSLSocket->lowest_layer(), criEndpoints, 
        boost::bind(&HTTPSClient::HandleConnect, this, placeholders::error, 
        rRequest));
}

void HTTPSClient::HandleConnect(const error_code &crError, HTTPSRequest &rRequest)
{
    mSSLSocket->lowest_layer().set_option(ip::tcp::no_delay(true));
    mSSLSocket->set_verify_callback(ssl::rfc2818_verification(rRequest.mcHost));
    mSSLSocket->handshake(ssl::stream_base::client);

    // Write the json into a stringstream
    std::ostringstream json;
    boost::property_tree::write_json(json, rRequest.mcPTree);
    std::string result;
    result = json.str();

    // Form the request
    streambuf request;
    std::ostream requestStream(&request);
    requestStream << "POST " << rRequest.mcURI << " HTTP/1.1\r\n";
    requestStream << "Host: " << rRequest.mcHost << "\r\n";
    requestStream << "Accept: application/json\r\n";
    requestStream << "Content-Type: application/json; charset=UTF-8\r\n";
    requestStream << "Content-Length: " << result.length() << "\r\n";
    requestStream << result << "\r\n\r\n";

    write(*mSSLSocket, request);

    streambuf response;
    read_until(*mSSLSocket, response, "\r\n");
    std::istream responseStream(&response);
}

read_until hangs until it throws the error read_until: End of file. read_until挂起,直到它抛出错误read_until:文件结束。 Everything before that goes successfully, including the SSL handshake (which I just recently figured out). 之前的一切都成功,包括SSL握手(我刚刚想到的)。

I used to do everything asynchronously until I started debugging, and started trying to backtrace to the problem, to no avail. 我曾经异步地做所有事情,直到我开始调试,并开始尝试回溯问题,但无济于事。 It would be awesome if someone could help me out after two painful days of debugging. 如果有人能在经过两天痛苦的调试后帮助我,那真是太棒了。

EDIT I just realized it might be useful to add the contents of requestStream after composing the header: 编辑我刚刚意识到在编写标题后添加requestStream的内容可能很有用:

POST /authenticate HTTP/1.1
Host: <hostname>
Accept: application/json
Content-Type: application/json; charset=UTF-8
Content-Length: 136
{
    "username": "vijfhoek",
    "password": "test123",
    <other json content>
}

You need a double linefeed before the body (POST contents) 身体前需要双线换行(POST内容)

POST /authenticate HTTP/1.1
Host: <hostname>
Accept: application/json
Content-Type: application/json; charset=UTF-8
Content-Length: 136

{
    "username": "vijfhoek",
    "password": "test123",
    <other json content>
}

Otherwise, the content will have been received by the server as header lines and the server just keeps waiting for 136 bytes of content data (also make sure that Content-Length is accurate, which it isn't in this example) 否则,内容将被服务器作为标题行接收,服务器只是等待136字节的内容数据(同时确保Content-Length是准确的,在本例中不是这样)

So, basically: 所以,基本上:

requestStream << "Content-Length: " << result.length() << "\r\n";
requestStream << "\r\n"; // THIS LINE ADDED

I managed to figure out what I was doing wrong. 我设法弄清楚我做错了什么。 For some reason, I couldn't get boost to write data using the boost::asio::streambuf and std::ostream approach. 出于某种原因,我无法使用boost :: asio :: streambuf和std :: ostream方法来增强写入数据。 Instead, I put the POST data in a std::string and sent it like this: 相反,我将POST数据放在std :: string中并像这样发送:

write(*mSSLSocket, boost::asio::buffer(requestString));

Which worked out fine. 哪个好了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM