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

时间:2014-02-27 04:25:44

标签: c++ boost ssl https boost-asio

我想使用boost :: asio连接到HTTPS服务器。我成功地与服务器握手,但我无法让服务器响应我的POST请求。

这是相关代码(我省去了调试和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挂起,直到它抛出错误read_until:文件结束。之前的一切都成功,包括SSL握手(我刚刚想到的)。

我曾经异步地做所有事情,直到我开始调试,并开始尝试回溯问题,但无济于事。如果有人能在经过两天痛苦的调试后帮助我,那真是太棒了。

EDIT 我刚刚意识到在编写标题后添加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>
}

2 个答案:

答案 0 :(得分:6)

您需要在身体前面使用双线换行(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>
}

否则,服务器将收到内容标题行,服务器只等待136字节的内容数据(同时确保内容长度准确无误) ,这不是在这个例子中)

所以,基本上:

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

答案 1 :(得分:1)

我设法弄清楚我做错了什么。出于某种原因,我无法使用boost :: asio :: streambuf和std :: ostream方法来增强写入数据。相反,我将POST数据放在std :: string中并像这样发送:

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

结果很好。