@_az I was right about the DNS. But now there’s another problem. When I try to send a request to the currency API I’m using from my server-side code, my exception-catching code catches an std::exception
whose what
string just says, “uninitialized”. I have no idea where the exception came from. I printed the exception type using typeid
, but it just says that it’s a struct boost::wrapexcept<class boost::system::system_error>
. I tried putting this line of code std::cerr << "Exception thrown from here\n";
at the places where I know a boost::system::error_code
object is used with an exception of that type being thrown, but none of those got printed. I’m confused.
I also printed out the certs I got from the store to my server app console window. I noticed there are some weird characters and even some sensible words (telling you what authority signed the following certificate (which certificate it’s referring to is a guess on my part)) in between some certificates. I wonder if this could cause problems. I also installed ca.cer more than once IIRC and I wonder if that could cause duplicate certs to appear in the certificate store and cause problems. I put the server console app’s output in this Gist. Notice the words and weird characters?
This is the function the exception is caught in:
// This function queries the currency API for a list of currencies
const json &cache_storage::query_list(const char *currencykey, const json &sentry)
{
boost::beast::error_code ec;
try
{
std::string host{ "bankersalgo.com" }, api_endpoint{ "/currencies_list" }, key{ currencykey };
std::string target = api_endpoint + '/' + key;
std::string port{ "443" };
int version = 11;
// The io_context is required for all IO
boost::asio::io_context ioc;
// The SSL context is required, and holds certificates
ssl::context ctx{ ssl::context::tlsv12_client };
// This holds the root certificate used for verification
load_root_certificates(ctx);
// Verify the remote server's certificate
ctx.set_verify_mode(ssl::verify_peer);
// These objects perform our IO
tcp::resolver resolver{ ioc };
ssl::stream<tcp::socket> stream{ ioc, ctx };
// Set SNI Hostname (many hosts need this to handshake successfully)
if (!SSL_set_tlsext_host_name(stream.native_handle(), host.c_str()))
{
boost::system::error_code ec{ static_cast<int>(::ERR_get_error()), boost::asio::error::get_ssl_category() };
throw boost::system::system_error{ ec };
std::cerr << "Exception thrown from here\n";
}
// Look up the domain name
const auto results = resolver.resolve(host, port);
// Make the connection on the IP address we get from a lookup
boost::asio::connect(stream.next_layer(), results.begin(), results.end());
// Set up an HTTP GET request message
http::request<http::string_body> req{ http::verb::get, target, version };
req.set(http::field::host, host);
req.set(http::field::content_type, "application/json");
req.set(http::field::accept, "application/json");
req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
req.set(http::field::content_encoding, "gzip");
// Send the HTTP request to the remote host
http::write(stream, req);
// This buffer is used for reading and must be persisted
boost::beast::flat_buffer buffer;
// Declare a container to hold the response
http::response<http::string_body> res;
// Receive the HTTP response
http::read(stream, buffer, res);
std::cout << res.body() << "\n";
// Gracefully close the stream
boost::system::error_code ec;
stream.shutdown(ec);
if (ec == boost::asio::error::eof)
{
// Rationale:
// http://stackoverflow.com/questions/25587403/boost-asio-ssl-async-shutdown-always-finishes-with-an-error
ec.assign(0, ec.category());
}
if (ec)
{
throw boost::system::system_error{ ec };
std::cerr << "Exception thrown from here\n";
}
// If we get here then the connection is closed gracefully
return json::parse(res.body());
}
catch (const boost::beast::error_code &ec)
{
std::cerr << "Line 862: Error: " << ec.message() << '\n';
}
catch (const json::exception &e)
{
std::cerr << "Line 866: Error: " << e.what() << '\n';
}
catch (const std::exception &e)
{
std::cerr << "Line 870: Error: " << e.what() << '\n';
std::cerr << "The type of the exception is " << typeid(e).name() << '\n';
}
return sentry;
}
Any replies or help is appreciated. Thanks in advance.