0

I am trying to send a get request to acounts.google.com to be able to implement a library for C++ OAuth to learn it.

I get the following code from this post: Creating a HTTPS request using Boost Asio and OpenSSL and modified it as follow:

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;
        }
    }
    
}

The problem that I have is as follow:

1- The results that I am getting is not what I am getting when I visit https://accounts.google.com/o/oauth2/v2/auth using a web browser. I essentially getting a message that they can not find the requested 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>

How should I setup the GET commend so I can get the same result that I am getting with a browser?

2- The application hangs getting data from server, apparently the following loop is not right:

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

What is the correct way of reading responce from the web server which is fast and read all data?

Edit 1

For reference based on accepted answer, I fixed the problem using the correct GET header as shown below:

// 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));
Community
  • 1
  • 1
mans
  • 17,104
  • 45
  • 172
  • 321

1 Answers1

0

A HTTP/1.1 request must have a Host header. A simple experiment with OpenSSL will show the problem, i.e. the missing 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>

When adding the Host header instead we get a different response:

$ 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<

Apart from that HTTP/1.1 implicitly uses HTTP keep-alive, i.e. server and client might keep the connection open after the response is done. This means you should not read until the end of connection but should instead properly parse the HTTP header, extract the Content-length header and/or Transfer-Encoding header and behave according to their values. Or if you want it simpler use HTTP/1.0 instead.

For more information see the HTTP/1.1 standard.

Steffen Ullrich
  • 114,247
  • 10
  • 131
  • 172