簡體   English   中英

提升Asio C ++ HTTPS請求不要命中服務器。 沒有錯誤

[英]Boost Asio C++ HTTPS Request not hitting server. No errors

我試圖使用Boost asio ssl C ++命中一個端點。 一切順利,沒有任何錯誤。 但請求只是沒有擊中服務器。 以下是代碼:

    string protocol,domain,port,path;
    boost::regex ex("(http|https)://([^/ :]+):?([^/ ]*)(/?[^ #?]*)\\x3f?([^ #]*)#?([^ ]*)");
    boost::cmatch what;
    if(regex_match(url.c_str(), what, ex)) 
    {
    protocol= string(what[1].first, what[1].second);
    domain= string(what[2].first, what[2].second);
    port= string(what[3].first, what[3].second);
    path= string(what[4].first, what[4].second);
    }
    // Get a list of endpoints corresponding to the server name.
    boost::asio::io_service io_service;
    boost::asio::ssl::context ctx(ssl::context::sslv23);
    ctx.set_default_verify_paths();
    ctx.set_options(boost::asio::ssl::context::default_workarounds |
    boost::asio::ssl::context::verify_none );
    ssl_socket socket(io_service, ctx);
    tcp::resolver resolver(io_service);
    tcp::resolver::query query(domain.c_str(), port.c_str());
    tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);

    socket.set_verify_mode(boost::asio::ssl::context::verify_none);
    // Try each endpoint until we successfully establish a connection.

    socket.set_verify_callback(verify_certificate);
    boost::asio::connect(socket.lowest_layer(), endpoint_iterator);
    socket.handshake(ssl_socket::client);
    socket.lowest_layer().set_option(tcp::no_delay(true));
    // Form the request. We specify the "Connection: close" header so that the
    // server will close the socket after transmitting the response. This will
    // allow us to treat all data up until the EOF as the content.
    boost::asio::streambuf request;
    std::ostream request_stream(&request);

    request_stream << "POST "<<path<<"/ssl HTTP/1.1 \r\n";
    request_stream << "Host:" << domain<<":"<<port << "\r\n";
    request_stream << "User-Agent: C/1.0";
    request_stream << "Content-Type: application/vnd.api+json; charset=utf-8 \r\n";
    request_stream << "Accept: */*\r\n";
    request_stream << "Content-Length: " << json.length() << "\r\n"; 
    request_stream << "Connection: close\r\n\r\n";  //NOTE THE Double line feed
    request_stream << json<<"\r\n";

    request_stream << std::cin.rdbuf() << std::flush;
    int a=boost::asio::write(socket, request);


     bool verify_certificate(bool preverified, boost::asio::ssl::verify_context& ctx)
       {
        /* char subject_name[256];
         X509* cert = X509_STORE_CTX_get_current_cert(ctx.native_handle());
         X509_NAME_oneline(X509_get_subject_name(cert), subject_name, 256);
         std::cout << "Verifying:\n" << subject_name << std::endl;*/

         return true;
       }

我使用的是自簽名證書,我堅信這就是問題所在。 但是,我也沒有得到任何握手錯誤。 我在這做錯了什么?

編輯:我得到以下輸出:

    Connected to: 
    Response: short read

現在我不確定為什么連接到零件是空的。 我調試並交叉檢查了主機,端口和路徑變量不為空的事實。

如果port為空,您的方法將失敗。

此外,如果用戶代理缺少行結束:

request_stream << "User-Agent: C/1.0\r\n";

我試過了

std::string url = "https://209.85.203.105:443/";

//std::string url = "https://www.google.com:443/";

它有效。

完整的演示

#include <boost/asio.hpp>
#include <boost/regex.hpp>
#include <boost/asio/ssl.hpp>
#include <iostream>

namespace ssl = boost::asio::ssl;
using tcp = boost::asio::ip::tcp;
using ssl_socket = ssl::stream<tcp::socket>;

bool verify_certificate(bool /*preverified*/, boost::asio::ssl::verify_context& /*ctx*/)
{
    /* char subject_name[256];
       X509* cert = X509_STORE_CTX_get_current_cert(ctx.native_handle());
       X509_NAME_oneline(X509_get_subject_name(cert), subject_name, 256);
       std::cout << "Verifying:\n" << subject_name << std::endl;*/

    return true;
}

int main() {
    std::string url = "https://www.stackoverflow.com:443/";
    //std::string url = "https://209.85.203.105:443/";
    std::string json = "{ \"hello\" : \"world\" }";

    std::string protocol,domain,port,path;
    boost::regex ex("(http|https)://([^/ :]+):?([^/ ]*)(/?[^ #?]*)\\x3f?([^ #]*)#?([^ ]*)");
    boost::cmatch what;
    if(regex_match(url.c_str(), what, ex)) 
    {
        protocol= std::string(what[1].first, what[1].second);
        domain= std::string(what[2].first, what[2].second);
        port= std::string(what[3].first, what[3].second);
        path= std::string(what[4].first, what[4].second);
    }

    std::cout << "protocol: " << protocol << "\n";
    std::cout << "domain:   " << domain   << "\n";
    std::cout << "port:     " << port     << "\n";
    std::cout << "path:     " << path     << "\n";

    // Get a list of endpoints corresponding to the server name.
    boost::asio::io_service io_service;
    boost::asio::ssl::context ctx(ssl::context::sslv23);

    ctx.set_default_verify_paths();
    ctx.set_options(boost::asio::ssl::context::default_workarounds | boost::asio::ssl::context::verify_none);

    ssl_socket socket(io_service, ctx);

    tcp::resolver resolver(io_service);
    tcp::resolver::query query(domain.c_str(), port.c_str());
    tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);

    socket.set_verify_mode(boost::asio::ssl::context::verify_none);
    // Try each endpoint until we successfully establish a connection.

    socket.set_verify_callback(verify_certificate);
    std::cout << "Connecting... " << std::flush;
    boost::asio::connect(socket.lowest_layer(), endpoint_iterator);
    std::cout << "Connected to " << socket.lowest_layer().remote_endpoint() << "\n";
    socket.handshake(ssl_socket::client);
    socket.lowest_layer().set_option(tcp::no_delay(true));

    // Form the request. We specify the "Connection: close" header so that the
    // server will close the socket after transmitting the response. This will
    // allow us to treat all data up until the EOF as the content.
    boost::asio::streambuf request;
    std::ostream request_stream(&request);

    request_stream << "GET " << path << " HTTP/1.1\r\n";
    request_stream << "Host:" << domain << ":" << port << "\r\n";
    //request_stream << "Host:" << domain << "\r\n";
    request_stream << "User-Agent: C/1.0\r\n";
    //request_stream << "Content-Type: application/vnd.api+json; charset=utf-8 \r\n";
    request_stream << "Accept: */*\r\n";
    //request_stream << "Content-Length: " << json.length() << "\r\n"; 
    request_stream << "Connection: close\r\n\r\n";
    //request_stream << json << "\r\n";
    //request_stream << std::cin.rdbuf() << std::flush;

    int a = boost::asio::write(socket, request);

    std::cout << a << " byte sent\n";
    std::vector<char> response(10 * 1024);
    boost::system::error_code ec;
    auto bytes_received = boost::asio::read(socket, boost::asio::buffer(response), boost::asio::transfer_all(), ec);
    response.resize(a);

    std::cout << "Response: " << ec.message() << "\n----------------\n";
    std::cout.write(response.data(), bytes_received) << std::flush;
}

打印

protocol: https
domain:   www.stackoverflow.com
port:     443
path:     /
Connecting... Connected to 151.101.129.69:443
101 byte sent
Response: End of file
----------------
HTTP/1.1 301 Moved Permanently
Content-Type: text/html; charset=UTF-8
Location: http://stackoverflow.com/
Content-Length: 148
Accept-Ranges: bytes
Date: Thu, 08 Sep 2016 07:13:08 GMT
Via: 1.1 varnish
Connection: close
X-Served-By: cache-ams4420-AMS
X-Cache: MISS
X-Cache-Hits: 0
X-Timer: S1473318788.479431,VS0,VE342
X-DNS-Prefetch-Control: off
Set-Cookie: prov=90860619-8a76-9233-21d1-43de9920a25c; domain=.stackoverflow.com; expires=Fri, 01-Jan-2055 00:00:00 GMT; path=/; HttpOnly

<head><title>Document Moved</title></head>
<body><h1>Object Moved</h1>This document may be found <a HREF="http://stackoverflow.com/">here</a></body>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM