2014-02-27 59 views
4

我想使用boost :: asio連接到HTTPS服務器。我設法成功地與服務器握手,但我無法設法讓服務器響應我的POST請求。使用boost :: asio連接到HTTPS服務器

這是相關的代碼(我離開了調試和試捕,以節省一些空間):

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握手(我剛剛纔知道)。

我以前一切都異步完成,直到我開始調試,並開始嘗試追溯到問題,無濟於事。如果有人能在兩個痛苦的調試日子之後幫助我,那將是非常棒的。

編輯 我才意識到這可能是有用的組成頭後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> 
} 

回答

1

我設法找出我做錯了。出於某種原因,我無法使用boost :: asio :: streambuf和std :: ostream方法獲取boost數據。相反,我把POST數據放在一個std :: string中,並且像這樣發送:

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

哪一個很好。

+1

也許你忘了將流設置爲二進制和'noskipws' – sehe

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字節的內容數據(還要確保Content-Len GTH是準確的,它是不是在這個例子中)

因此,基本上:

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

那''r \ n \ r \ n'結尾也是不必要的。 (除非它實際上是身體的一部分,這是) –

+0

可悲的是沒有幫助,我仍然無法從服務器獲得答案。 Content-Length也是準確的,但我在這個問題中忽略了一些json數據。 – vijfhoek

+0

@vijfhoek使用提琴手(或其他類型的嗅探工具)來檢查流量。檢查內容長度。考慮添加一個'連接:關閉'標題。基本上:用SSCCE **調試東西或發佈新的問題***。這是所示代碼中的錯誤。 – sehe