CppServer  1.0.4.0
C++ Server Library
http_client.cpp
Go to the documentation of this file.
1 
10 
11 namespace CppServer {
12 namespace HTTP {
13 
14 void HTTPClient::onReceived(const void* buffer, size_t size)
15 {
16  // Receive HTTP response header
17  if (_response.IsPendingHeader())
18  {
19  if (_response.ReceiveHeader(buffer, size))
21 
22  size = 0;
23  }
24 
25  // Check for HTTP response error
26  if (_response.error())
27  {
28  onReceivedResponseError(_response, "Invalid HTTP response!");
29  _response.Clear();
31  return;
32  }
33 
34  // Receive HTTP response body
35  if (_response.ReceiveBody(buffer, size))
36  {
38  _response.Clear();
39  return;
40  }
41 
42  // Check for HTTP response error
43  if (_response.error())
44  {
45  onReceivedResponseError(_response, "Invalid HTTP response!");
46  _response.Clear();
48  return;
49  }
50 }
51 
53 {
54  // Receive HTTP response body
55  if (_response.IsPendingBody())
56  {
58  _response.Clear();
59  return;
60  }
61 }
62 
63 std::future<HTTPResponse> HTTPClientEx::SendRequest(const HTTPRequest& request, const CppCommon::Timespan& timeout)
64 {
65  // Create TCP resolver if the current one is empty
66  if (!_resolver)
67  _resolver = std::make_shared<Asio::TCPResolver>(service());
68  // Create timeout check timer if the current one is empty
69  if (!_timeout)
70  _timeout = std::make_shared<Asio::Timer>(service());
71 
72  _promise = std::promise<HTTPResponse>();
73  _request = request;
74 
75  // Check if the HTTP request is valid
76  if (_request.empty() || _request.error())
77  {
78  SetPromiseError("Invalid HTTP request!");
79  return _promise.get_future();
80  }
81 
82  if (!IsConnected())
83  {
84  // Connect to the Web server
85  if (!ConnectAsync(_resolver))
86  {
87  SetPromiseError("Connection failed!");
88  return _promise.get_future();
89  }
90  }
91  else
92  {
93  // Send prepared HTTP request
94  if (!SendRequestAsync())
95  {
96  SetPromiseError("Failed to send HTTP request!");
97  return _promise.get_future();
98  }
99  }
100 
101  // Setup timeout check timer
102  auto self(this->shared_from_this());
103  auto timeout_handler = [this, self](bool canceled)
104  {
105  if (canceled)
106  return;
107 
108  // Disconnect on timeout
109  onReceivedResponseError(_response, "Timeout!");
110  _response.Clear();
111  DisconnectAsync();
112  };
113  if (!_timeout->Setup(timeout_handler, timeout) || !_timeout->WaitAsync())
114  {
115  SetPromiseError("Failed to setup timeout timer!");
116  return _promise.get_future();
117  }
118 
119  return _promise.get_future();
120 }
121 
123 {
125 
126  // Send prepared HTTP request on connect
127  if (!_request.empty() && !_request.error())
128  if (!SendRequestAsync())
129  SetPromiseError("Failed to send HTTP request!");
130 }
131 
133 {
134  // Cancel timeout check timer
135  if (_timeout)
136  _timeout->Cancel();
137 
139 }
140 
142 {
143  // Cancel timeout check timer
144  if (_timeout)
145  _timeout->Cancel();
146 
147  SetPromiseValue(response);
148 }
149 
150 void HTTPClientEx::onReceivedResponseError(const HTTPResponse& response, const std::string& error)
151 {
152  // Cancel timeout check timer
153  if (_timeout)
154  _timeout->Cancel();
155 
156  SetPromiseError(error);
157 }
158 
159 void HTTPClientEx::SetPromiseValue(const HTTPResponse& response)
160 {
161  _promise.set_value(response);
162  _request.Clear();
163 }
164 
165 void HTTPClientEx::SetPromiseError(const std::string& error)
166 {
167  _promise.set_exception(std::make_exception_ptr(std::runtime_error(error)));
168  _request.Clear();
169 }
170 
171 } // namespace HTTP
172 } // namespace CppServer
bool IsConnected() const noexcept
Is the client connected?
Definition: tcp_client.h:101
virtual void onConnected()
Handle client connected notification.
Definition: tcp_client.h:279
std::shared_ptr< Service > & service() noexcept
Get the Asio service.
Definition: tcp_client.h:63
virtual bool ConnectAsync()
Connect the client (asynchronous)
Definition: tcp_client.cpp:279
virtual bool DisconnectAsync()
Disconnect the client (asynchronous)
Definition: tcp_client.h:146
void onReceivedResponse(const HTTPResponse &response) override
Handle HTTP response received notification.
void onDisconnected() override
Handle client disconnected notification.
void onConnected() override
Handle client connected notification.
std::shared_ptr< Asio::Timer > & timeout() noexcept
Get the timeout check timer.
Definition: http_client.h:184
void onReceivedResponseError(const HTTPResponse &response, const std::string &error) override
Handle HTTP response error notification.
void onReceived(const void *buffer, size_t size) override
Handle buffer received notification.
Definition: http_client.cpp:14
HTTPResponse _response
HTTP response.
Definition: http_client.h:165
HTTPRequest _request
HTTP request.
Definition: http_client.h:163
HTTPRequest & request() noexcept
Get the HTTP request.
Definition: http_client.h:44
size_t SendRequest()
Send the current HTTP request (synchronous)
Definition: http_client.h:51
bool SendRequestAsync()
Send the current HTTP request (asynchronous)
Definition: http_client.h:107
virtual void onReceivedResponse(const HTTPResponse &response)
Handle HTTP response received notification.
Definition: http_client.h:149
virtual void onReceivedResponseHeader(const HTTPResponse &response)
Handle HTTP response header received notification.
Definition: http_client.h:140
virtual void onReceivedResponseError(const HTTPResponse &response, const std::string &error)
Handle HTTP response error notification.
Definition: http_client.h:159
void onDisconnected() override
Handle client disconnected notification.
Definition: http_client.cpp:52
HTTPRequest & Clear()
Clear the HTTP request cache.
bool empty() const noexcept
Is the HTTP request empty?
Definition: http_request.h:53
bool error() const noexcept
Is the HTTP request error flag set?
Definition: http_request.h:55
bool error() const noexcept
Is the HTTP response error flag set?
Definition: http_response.h:64
HTTPResponse & Clear()
Clear the HTTP response cache.
HTTP client definition.
C++ Server project definitions.
Definition: asio.h:56