HttpClient.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__HTTP_CLIENT
18 #define COM_BORA_SOFTWARE__BALAU_NETWORK_HTTP_CLIENT__HTTP_CLIENT
19 
20 #include <Balau/Type/ToString.hpp>
23 #include <Balau/Resource/Url.hpp>
24 #include <Balau/Type/StdTypes.hpp>
25 
27 
33 class HttpClient {
43  public: static std::unique_ptr<HttpClient> newClient(const Resource::Url & url,
44  std::string userAgent = "Balau " + BalauVersion,
45  const char * version = "1.1");
46 
56  public: static std::unique_ptr<HttpClient> newClient(const std::string & url,
57  std::string userAgent = "Balau " + BalauVersion,
58  const char * version = "1.1");
59 
68  public: explicit HttpClient(std::string host_,
69  unsigned short port_ = 80,
70  std::string userAgent_ = "Balau " + BalauVersion,
71  const char * version_ = "1.1")
72  : host(std::move(host_))
73  , port(port_)
74  , userAgent(std::move(userAgent_))
75  , version(parseVersion(version_)) {}
76 
80  public: HttpClient(const HttpClient &) = default;
81 
85  public: HttpClient(HttpClient &&) = default;
86 
90  public: HttpClient & operator = (const HttpClient &) = default;
91 
95  public: HttpClient & operator = (HttpClient &&) = default;
96 
100  public: virtual ~HttpClient() = default;
101 
107  public: virtual CharVectorResponse get(const std::string_view & path) {
108  return sendRequest<CharVectorResponse>(Method::get, path, "");
109  }
110 
116  public: virtual EmptyResponse head(const std::string_view & path) {
117  return sendRequest<EmptyResponse>(Method::head, path, "");
118  }
119 
125  public: virtual CharVectorResponse post(const std::string_view & path, const std::string_view & body) {
126  return sendRequest<CharVectorResponse>(Method::post, path, body);
127  }
128 
130 
131  protected: std::string host;
132  protected: unsigned short port;
133  protected: std::string userAgent;
134  protected: int version;
135 
136  private: template <typename ResponseT>
137  ResponseT sendRequest(Method verb, const std::string_view & path, const std::string_view & body);
138 
139  private: int parseVersion(const char * versionString) {
140  if (std::strcmp(versionString, "1.0") == 0) {
141  return 10;
142  } else if (std::strcmp(versionString, "1.1") == 0) {
143  return 11;
144  } else {
146  Exception::NetworkException, "Invalid HTTP version supplied to client: " + ::toString(versionString)
147  );
148  }
149  }
150 };
151 
152 template <typename ResponseT>
153 ResponseT HttpClient::sendRequest(Method verb, const std::string_view & path, const std::string_view & body) {
155 
156  boost::asio::io_context ioc;
157  TCP::resolver resolver { ioc };
158  TCP::socket socket { ioc };
159 
160  auto resolverResults = resolver.resolve(host.c_str(), ::toString(port).c_str());
161  boost::asio::connect(socket, resolverResults.begin(), resolverResults.end());
162 
164 
165  StringRequest request { verb, path.empty() ? "/" : std::string(path), version };
166  request.set(Field::host, host);
167  request.set(Field::user_agent, userAgent);
168  request.set(Field::accept, "text/html");
169 
170  if (!body.empty()) {
171  request.body() = std::string(body);
172  request.prepare_payload();
173  }
174 
175  HTTP::write(socket, request);
176 
177  Buffer buffer {};
178  ResponseT response;
179  HTTP::read(socket, buffer, response);
180 
182 
183  boost::system::error_code errorCode {};
184  socket.shutdown(TCP::socket::shutdown_both, errorCode);
185 
186  // TODO clarify the following.
187  if (errorCode && errorCode != boost::system::errc::not_connected) {
188  throw boost::system::system_error { errorCode }; // TODO
189  }
190 
192 
193  return response;
194 }
195 
196 } // namespace Balau::Network::Http
197 
198 #endif // COM_BORA_SOFTWARE__BALAU_NETWORK_HTTP_CLIENT__HTTP_CLIENT
Components and utilities working on HTTP data transmission.
Definition: HttpClient.hpp:26
Pre-defined universal to-string functions.
A simple HTTP client.
Definition: HttpClient.hpp:33
virtual ~HttpClient()=default
Destroy the client instance.
static std::unique_ptr< HttpClient > newClient(const Resource::Url &url, std::string userAgent="Balau "+BalauVersion, const char *version="1.1")
Create a new HTTP or HTTPS client, according to the supplied URL.
Low level types used in networking code.
#define ThrowBalauException(ExceptionClass,...)
Throw a Balau style exception, with implicit file and line number, and optional stacktrace.
Definition: BalauException.hpp:45
boost::beast::flat_buffer Buffer
A data buffer used in HTTP code.
Definition: NetworkTypes.hpp:308
Base class of network exceptions.
Definition: NetworkExceptions.hpp:28
STL namespace.
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
Core includes, typedefs and functions.
An abstract Url (either http or https).
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
virtual CharVectorResponse post(const std::string_view &path, const std::string_view &body)
Perform a POST request.
Definition: HttpClient.hpp:125
const std::string BalauVersion
The version of the Balau library.
HttpClient & operator=(const HttpClient &)=default
Assign an HTTP client by copying the supplied instance.
HttpClient(std::string host_, unsigned short port_=80, std::string userAgent_="Balau "+BalauVersion, const char *version_="1.1")
Create an HTTP client instance.
Definition: HttpClient.hpp:68
Balau::U8String< AllocatorT > toString(LoggingLevel level)
Print the logging level as a UTF-8 string.
Definition: LoggingLevel.hpp:73
virtual EmptyResponse head(const std::string_view &path)
Perform a HEAD request.
Definition: HttpClient.hpp:116
Balau exceptions for network operations.
An abstract Url (either http or https).
Definition: Url.hpp:28