c++ - 向 ssl 服务器发送 GET 命令以获取结果

标签 c++ ssl https http-headers boost-asio

我正在尝试向 acounts.google.com 发送一个获取请求,以便能够为 C++ OAuth 实现一个库来学习它。

我从这篇文章中得到以下代码:Creating a HTTPS request using Boost Asio and OpenSSL并修改如下:

int main()
{
    try
    {
        std::string request = "/o/oauth2/v2/auth";
        boost::system::error_code ec;
        using namespace boost::asio;

        // what we need
        io_service svc;
        ssl::context ctx(svc, ssl::context::method::sslv23_client);
        ssl::stream<ip::tcp::socket> ssock(svc, ctx);
        ip::tcp::resolver resolver(svc);
        auto it = resolver.resolve({ "accounts.google.com", "443" }); // https://accouts.google.com:443
        boost::asio::connect(ssock.lowest_layer(), it);

        ssock.handshake(ssl::stream_base::handshake_type::client);

        // send request
        std::string fullResuest = "GET " + request + " HTTP/1.1\r\n\r\n";
        boost::asio::write(ssock, buffer(fullResuest));

        // read response
        std::string response;

        do
        {
            char buf[1024];
            size_t bytes_transferred = ssock.read_some(buffer(buf), ec);
            if (!ec) response.append(buf, buf + bytes_transferred);
            std::cout << "Response received: '" << response << "'\n"; // I add this to see what I am getting from the server, so it should not be here.
                        
        } while (!ec);

        // print and exit
        std::cout << "Response received: '" << response << "'\n";
    }
    catch (const std::exception& e)
    {
        std::cerr << e.what() << std::endl;
        if (std::string const * extra = boost::get_error_info<my_tag_error_info>(e))
        {
            std::cout << *extra << std::endl;
        }
    }
    
}

我遇到的问题如下:

1- 我得到的结果不是我访问 https://accounts.google.com/o/oauth2/v2/auth 时得到的结果使用网络浏览器。我基本上收到一条消息,说他们找不到请求的 URL/o/oauth2/v2/auth

<p>The requested URL <code>/o/oauth2/v2/auth</code> was not found on this server.  <ins>ThatÔÇÖs all we know.</ins>

我应该如何设置 GET 命令才能获得与浏览器相同的结果?

2- 应用程序挂起从服务器获取数据,显然以下循环不正确:

 do
 {
      char buf[1024];
      size_t bytes_transferred = ssock.read_some(buffer(buf), ec);
      if (!ec) response.append(buf, buf + bytes_transferred);
 } while (!ec);

从快速读取所有数据的网络服务器读取响应的正确方法是什么?

编辑 1

为了引用基于接受的答案,我使用正确的 GET header 修复了问题,如下所示:

// send request
    std::string fullResuest = "GET " + request + " HTTP/1.1\r\n";
    fullResuest+= "Host: " + server + "\r\n";
    fullResuest += "Accept: */*\r\n";
    fullResuest += "Connection: close\r\n\r\n";
    boost::asio::write(ssock, buffer(fullResuest));

最佳答案

HTTP/1.1 请求必须有一个 Host header 。使用 OpenSSL 的简单实验将显示问题,即缺少 header :

$ openssl s_client -connect accounts.google.com:443
...
GET /o/oauth2/v2/auth HTTP/1.1

...   The requested URL <code>/o/oauth2/v2/auth</code> was not found on this server.  <ins>That’s all we know.</ins>

当添加 Host header 时,我们会得到不同的响应:

$ openssl s_client -connect accounts.google.com:443
...
GET /o/oauth2/v2/auth HTTP/1.1
Host: accounts.google.com

... >Required parameter is missing: response_type<

除此之外,HTTP/1.1 隐式使用 HTTP keep-alive,即服务器和客户端可能会在响应完成后保持连接打开。这意味着您不应该在连接结束之前阅读,而是应该正确解析 HTTP header ,提取 Content-length header 和/或 Transfer-Encoding header 并根据到他们的值(value)观。或者,如果您希望它更简单,请改用 HTTP/1.0。

有关详细信息,请参阅 the HTTP/1.1 standard .

关于c++ - 向 ssl 服务器发送 GET 命令以获取结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43720574/

相关文章:

c++ - 让它在 C++ 中发出蜂鸣声

java - 如何使用自签名证书运行 Java HTTP 服务器并信任浏览器?

node.js - Node HTTPS - 从 process.env 读取密码时 mac 验证失败

node.js - 需要帮助建立nodejs (NPM) localhost https

oracle - utl_http : ORA-24263: Certificate of the remote server does not match the target address

c++ - stdio.h 在 C++ 中不是标准的?

c++ - 在 Windows 上分发( native C++)库

C++文件同步问题

ssl - https无处不在

使用 wolfssl 进行证书完整性检查