Creating a HTTPS request using Boost Asio and OpenSSL
Asked Answered
C

2

7

I have created a simple HTTP request wherein I am sending GET,POST and PUT requests to the server. Next I want to switch to HTTPS connection using boost asio library, how should I proceed?

I have an Executor Class that resolves and connects to the server and a RequestCreator Class that creates the request.

Cobble answered 14/10, 2016 at 6:58 Comment(0)
N
13

I happen to just have posted such a thing in a comment (...):

You just connect over ssl. @Milind coliru.stacked-crooked.com/a/9546326fd1def416

So perhaps it is helpful to you.

Live On Coliru

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

int main() {
    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);
    ssock.lowest_layer().connect({ {}, 8087 }); // http://localhost:8087 for test
    ssock.handshake(ssl::stream_base::handshake_type::client);

    // send request
    std::string request("GET /newGame?name=david HTTP/1.1\r\n\r\n");
    boost::asio::write(ssock, buffer(request));

    // 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);
    } while (!ec);

    // print and exit
    std::cout << "Response received: '" << response << "'\n";
}

To emulate a server for demo purposes I've been using the certificate and params from the Asio samples (https://mcmap.net/q/1478329/-where-can-i-download-a-ca-pem-file-for-boost-asio-ssl).

UPDATE Here's a version that uses resolver to resolve the endpoint (Coliru doesn't allow us to do that, but it does work on non-restricted machines).

Live On Coliru

ip::tcp::resolver resolver(svc);
auto it = resolver.resolve({"localhost", "8087"}); // http://localhost:8087 for test
boost::asio::connect(ssock.lowest_layer(), it);

// and the rest unaltered
ssock.handshake(ssl::stream_base::handshake_type::client);
Nikolaus answered 14/10, 2016 at 12:13 Comment(9)
This dosen't seem to work as i am using resolver and not endpoint tcp::resolver resolver(ioService); tcp::resolver::query query(cli.getIP(), "8080");Cobble
Don't give link to boost website or github sample code, i have tried all of those(almost all)Cobble
Do you have any custom code that just makes a connection using resolver @NikolausCobble
@Cobble Found the time to answer your comment, see the UPDATE. What online samples have you found that were more confusing than this?Nikolaus
You have used auto here which is compiler dependent, right ?Cobble
and how do you gracefully close the connection/socket if any error arises ? @NikolausCobble
auto is not compiler dependent. It's standards version dependent in the sense that c++11 introduced it. All compilers support it in c++11 mode. What do you mean by graceful close? Perhaps it is time to search for existing answers to your different questions. If all else fails, you can ask a new questionNikolaus
I am basically taking the result of resolver.resolve(query) in boost::asio::ip::tcp::resolver::iteratorCobble
I just suggested what I think you should do. The comment thread is not well suited as a personal support forum. Also, by reusing/posting questions on the main site you (a) make it possible for many more people to help (b) make it possible for many more people to find your solutionsNikolaus
P
1

Simple example:

#include<string>
#include<iostream>

#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/beast.hpp>

using namespace boost::beast;
using namespace boost::asio;

using std::string;
using std::cout;


int
main() {

    const string host = "www.google.com";
    const string path = "/";
    const string port = "443";

    io_service svc;

    ssl::context ctx(ssl::context::sslv23_client);
    ssl::stream<ip::tcp::socket> ssocket = { svc, ctx };
    ip::tcp::resolver resolver(svc);
    auto it = resolver.resolve(host, port);
    connect(ssocket.lowest_layer(), it);
    ssocket.handshake(ssl::stream_base::handshake_type::client);
    http::request<http::string_body> req{ http::verb::get, path, 11 };
    req.set(http::field::host, host);
    http::write(ssocket, req);
    http::response<http::string_body> res;
    flat_buffer buffer;
    http::read(ssocket, buffer, res);
    cout << "Headers" << std::endl;
    cout << res.base() << std::endl << std::endl;
    cout << "Body" << std::endl;
    cout << res.body() << std::endl << std::endl;
}
Polyanthus answered 17/4, 2022 at 21:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.