HttpsClient.hpp
Go to the documentation of this file.
1 // @formatter:off
2 //
3 // Balau core C++ library
4 //
5 // Copyright (C) 2017 Bora Software (contact@borasoftware.com)
6 //
7 // Licensed under the Boost Software License - Version 1.0 - August 17th, 2003.
8 // See the LICENSE file for the full license text.
9 //
10 
16 
17 #ifndef COM_BORA_SOFTWARE__BALAU_NETWORK_HTTP_CLIENT__HTTPS_CLIENT
18 #define COM_BORA_SOFTWARE__BALAU_NETWORK_HTTP_CLIENT__HTTPS_CLIENT
19 
21 #include <Balau/Network/Utilities/root_certificates.hpp>
22 
23 namespace Balau::Network::Http {
24 
33 class HttpsClient : public HttpClient {
42  public: explicit HttpsClient(std::string host_,
43  unsigned short port_ = 443,
44  std::string userAgent_ = "Balau " + BalauVersion,
45  const char * version_ = "1.1")
46  : HttpClient(std::move(host_), port_, std::move(userAgent_), version_) {}
47 
51  public: HttpsClient(const HttpsClient &) = default;
52 
56  public: HttpsClient(HttpsClient &&) = default;
57 
61  public: HttpsClient & operator = (const HttpsClient &) = default;
62 
66  public: HttpsClient & operator = (HttpsClient &&) = default;
67 
71  public: CharVectorResponse get(const std::string_view & path) override {
72  return sendRequest<CharVectorResponse>(Method::get, path, "");
73  }
74 
78  public: EmptyResponse head(const std::string_view & path) override {
79  return sendRequest<EmptyResponse>(Method::head, path, "");
80  }
81 
85  public: CharVectorResponse post(const std::string_view & path, const std::string_view & body) override {
86  return sendRequest<CharVectorResponse>(Method::post, path, body);
87  }
88 
90 
91  private: template <typename ResponseT>
92  ResponseT sendRequest(Method verb, const std::string_view & path, const std::string_view & body) {
94 
95  boost::asio::io_context ioc;
96  SSL::context ctx { SSL::context::tls_client };
97  load_root_certificates(ctx);
98  TCP::resolver resolver { ioc };
99  SSL::stream<TCP::socket> stream { ioc, ctx };
100 
101  if (!SSL_set_tlsext_host_name(stream.native_handle(), host.c_str())) {
102  boost::system::error_code errorCode { static_cast<int>(::ERR_get_error()), boost::asio::error::get_ssl_category() };
103  throw boost::system::system_error{errorCode}; // TODO
104  }
105 
106  auto resolverResults = resolver.resolve(host.c_str(), ::toString(port).c_str());
107  boost::asio::connect(stream.next_layer(), resolverResults.begin(), resolverResults.end());
108  stream.handshake(SSL::stream_base::client);
109 
111 
112  StringRequest request { verb, path.empty() ? "/" : std::string(path), version };
113  request.set(Field::host, host);
114  request.set(Field::user_agent, userAgent);
115  request.set(Field::accept, "text/html");
116 
117  if (!body.empty()) {
118  request.body() = std::string(body);
119  request.prepare_payload();
120  }
121 
122  HTTP::write(stream, request);
123 
124  Buffer buffer {};
125  ResponseT response;
126  HTTP::read(stream, buffer, response);
127  boost::system::error_code errorCode {};
128  stream.shutdown(errorCode);
129 
131 
132  if (errorCode == boost::asio::error::eof) {
133  errorCode.assign(0, errorCode.category());
134  } else if (errorCode == boost::asio::ssl::error::stream_truncated) {
135  // NOP?
136  } else if (errorCode) {
137  throw boost::system::system_error { errorCode }; // TODO
138  }
139 
141 
142  return response;
143  }
144 };
145 
146 } // namespace Balau::Network::Http
147 
148 #endif // COM_BORA_SOFTWARE__BALAU_NETWORK_HTTP_CLIENT__HTTPS_CLIENT
Components and utilities working on HTTP data transmission.
Definition: HttpClient.hpp:26
A simple HTTP client.
Definition: HttpClient.hpp:33
boost::beast::flat_buffer Buffer
A data buffer used in HTTP code.
Definition: NetworkTypes.hpp:308
STL namespace.
HttpsClient & operator=(const HttpsClient &)=default
Assign an HTTPS client by copying the supplied instance.
EmptyResponse head(const std::string_view &path) override
Perform a HEAD request.
Definition: HttpsClient.hpp:78
boost::beast::http::verb Method
The HTTP method (GET, HEAD, POST).
Definition: NetworkTypes.hpp:298
Response< EmptyBody > EmptyResponse
A response with an empty body.
Definition: NetworkTypes.hpp:293
A simple HTTPS client.
Definition: HttpsClient.hpp:33
CharVectorResponse post(const std::string_view &path, const std::string_view &body) override
Perform a POST request.
Definition: HttpsClient.hpp:85
Request< StringBody > StringRequest
A request with a string body.
Definition: NetworkTypes.hpp:267
Response< CharVectorBody > CharVectorResponse
A response with a char vector body.
Definition: NetworkTypes.hpp:288
A simple HTTP client.
HttpsClient(std::string host_, unsigned short port_=443, std::string userAgent_="Balau "+BalauVersion, const char *version_="1.1")
Create an HTTPS client instance.
Definition: HttpsClient.hpp:42
const std::string BalauVersion
The version of the Balau library.
Balau::U8String< AllocatorT > toString(LoggingLevel level)
Print the logging level as a UTF-8 string.
Definition: LoggingLevel.hpp:73