Ocean
HTTPClient.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) Meta Platforms, Inc. and affiliates.
3  *
4  * This source code is licensed under the MIT license found in the
5  * LICENSE file in the root directory of this source tree.
6  */
7 
8 #ifndef FACEBOOK_NETWORK_HTTP_CLIENT_H
9 #define FACEBOOK_NETWORK_HTTP_CLIENT_H
10 
11 #include "ocean/network/Network.h"
14 
15 namespace Ocean
16 {
17 
18 namespace Network
19 {
20 
21 /**
22  * This class implements a basic http client.
23  * @ingroup network
24  */
25 class OCEAN_NETWORK_EXPORT HTTPClient
26 {
27  public:
28 
29  /**
30  * Definition of individual protocol versions.
31  */
33  {
34  /// The HTTP 1.0 version.
36  /// The HTTP 1.1 version.
37  PV_HTTP_1_1
38  };
39 
40  /**
41  * This class implements a http header wrapper.
42  */
43  class HTTPHeader
44  {
45  friend class HTTPClient;
46 
47  public:
48 
49  /**
50  * Definition of individual http reply codes.
51  */
52  enum ReplyCode
53  {
54  /// Invalid reply code.
55  RC_INVALID = 0,
56  /// Continue reply code.
57  RC_CONTINUE = 100,
58  /// OK reply code.
59  RC_OK = 200,
60  /// Created reply code.
61  RC_CREATED = 201,
62  /// Accepted reply code.
63  RC_ACCEPTED = 202,
64  /// This and all future requests should be directed to the given URI
65  RC_MOVED_PERMANENTLY = 301,
66  /// Bad request reply code.
67  RC_BAD_REQUEST = 400,
68  /// Unauthorized reply code.
69  RC_UNAUTHORIZED = 401,
70  /// Payment request reply code.
71  RC_PAYMENT_REQUIRED = 402,
72  /// Forbidden reply code.
73  RC_FORBIDDEN = 403,
74  /// Not found reply code.
75  RC_NOT_FOUND = 404,
76  /// Method not allowed reply code.
77  RC_METHOD_NOT_ALLOWED = 405,
78  /// Not acceptable reply code.
79  RC_NOT_ACCEPTABLE = 406
80  };
81 
82  /**
83  * Definition of individual content encoding types.
84  */
86  {
87  /// A standard encoding.
89  /// A GZIP encoding.
90  ET_GZIP
91  };
92 
93  /**
94  * Definition of a vector holding header lines.
95  */
96  typedef std::vector<std::string> Lines;
97 
98  public:
99 
100  /**
101  * Creates a new header object.
102  */
103  HTTPHeader() = default;
104 
105  /**
106  * Returns the reply code of this header.
107  * @return The reply code
108  */
109  inline ReplyCode code() const;
110 
111  /**
112  * Returns the length of the header in bytes.
113  * @return The header length in byte
114  */
115  inline size_t length() const;
116 
117  /**
118  * Returns the length of the content in bytes.
119  * @return The content length in byte
120  */
121  inline size_t contentLength() const;
122 
123  /**
124  * Returns whether the transfer encoding is chunked.
125  * @return True, if so
126  */
127  inline bool transferEncodingChunked() const;
128 
129  /**
130  * Returns the content encoding type.
131  * @return The content encoding type
132  */
133  inline EncodingType encodingType() const;
134 
135  /**
136  * Returns the location value.
137  * @return The location value
138  */
139  inline std::string& location();
140 
141  /**
142  * Returns the lines of this header.
143  * @return The header's lines
144  */
145  inline const Lines& lines() const;
146 
147  /**
148  * Sets the reply code of this header.
149  * @param code The reply code to set
150  */
151  inline void setCode(const ReplyCode code);
152 
153  /**
154  * Sets the version of the http header.
155  * @param version The version string to set
156  */
157  inline void setVersion(const std::string& version);
158 
159  /**
160  * Sets the length of the header in bytes.
161  * @param length The length in byte
162  */
163  inline void setLength(const size_t length);
164 
165  /**
166  * Sets the length of the content in bytes.
167  * @param length The content length in byte
168  */
169  inline void setContentLength(const size_t length);
170 
171  /**
172  * Sets the transfer encoding chunked state.
173  * @param state True, if the transfer encoding is chunked
174  */
175  inline void setTransferEncodingChunked(const bool state);
176 
177  /**
178  * Sets the content encoding type.
179  * @param type The content encoding type
180  */
181  inline void setContentEncodingType(const EncodingType type);
182 
183  /**
184  * Sets the location value.
185  * @param location The location to set
186  */
187  inline void setLocation(const std::string& location);
188 
189  /**
190  * Sets the lines of this header.
191  * @param lines The lines to move
192  */
193  inline void setLines(Lines&& lines);
194 
195  /**
196  * Returns whether the code of this header is valid.
197  * @return True, if so
198  */
199  inline bool isValid() const;
200 
201  protected:
202 
203  /**
204  * Parses a header line and updates the information in a given header object.
205  * @param line The line of an header
206  * @param header The header object receiving the parsed information
207  * @return True, if succeeded
208  */
209  static bool parseHeaderLine(const std::string& line, HTTPHeader& header);
210 
211  protected:
212 
213  /// The replay code the header.
214  ReplyCode code_ = RC_INVALID;
215 
216  /// The version of the header.
217  std::string version_;
218 
219  /// The length of the header's content.
220  size_t contentLength_ = 0;
221 
222  /// The length of the header.
223  size_t length_ = 0;
224 
225  /// True, if the transfer-encoding is chunked
226  bool transferEncodingChunked_ = false;
227 
228  /// The content encoding type.
229  EncodingType encodingType_ = ET_STANDARD;
230 
231  /// The location for e.g., a redirect
232  std::string location_;
233 
234  /// The lines of this header.
236  };
237 
238  /**
239  * Definition of a vector holding characters.
240  */
241  typedef std::vector<uint8_t> Buffer;
242 
243  /**
244  * Callback for receiving progress information when performing a HTTP request.
245  * The first parameter represents how many Bytes of the payload have been received so far, with range [0, infinity)
246  * The second parameter represents the total size of the payload in bytes, with range [0, infinity). If the total size is unknown this parameter is 0.
247  */
249 
250  public:
251 
252  /**
253  * Creates a new HTTP client object.
254  * @param host The URL of the HTTP server
255  * @param port The port of the HTTP server
256  */
257  HTTPClient(const std::string& host, const Port& port = Port(80, Port::TYPE_READABLE));
258 
259  /**
260  * Destructs a HTTP client object.
261  */
263 
264  /**
265  * Connects the client with the HTTP server.
266  * @return True, if succeeded
267  */
268  bool connect();
269 
270  /**
271  * (Re-)connects the client with the HTTP server.
272  * @param host The URL of the HTTP server
273  * @param port The port of the HTTP server
274  * @return True, if succeeded
275  */
276  bool connect(const std::string& host, const Port& port = Port(80, Port::TYPE_READABLE));
277 
278  /**
279  * Invokes a HEAD request.
280  * @param uri The universal resource identifier for the HEAD request (not including the first '/' between host and URI)
281  * @param header The resulting header
282  * @param timeout The timeout this function waits for the server's response, with range (0, infinity)
283  * @return True, if succeeded
284  */
285  bool invokeHeadRequest(const std::string& uri, HTTPHeader& header, const double timeout = 5.0);
286 
287  /**
288  * Invokes a GET request.
289  * @param uri The universal resource identifier for the HEAD request (not including the first '/' between host and URI)
290  * @param data The resulting response data
291  * @param timeout The timeout this function waits for the server's response, with range (0, infinity)
292  * @param urlRedirection Optional resulting URL if the request has to be redirected
293  * @param replyCode Optional reply code of the GET request
294  * @param abort Optional flag that may be set to true by another thread to abort the request
295  * @param progressCallback Optional callback for receiving progress information
296  * @return True, if succeeded;
297  */
298  bool invokeGetRequest(const std::string& uri, Buffer& data, const double timeout = 5.0, std::string* urlRedirection = nullptr, HTTPHeader::ReplyCode* replyCode = nullptr, bool* abort = nullptr, const ProgressCallback& progressCallback = ProgressCallback());
299 
300  /**
301  * Helper function to executes an HTTP site/file request.
302  * @param url The URL of the HTTP site which is requested, beginning with "HTTP://"
303  * @param data The resulting request data
304  * @param port The port of the HTTP server
305  * @param timeout The timeout this function waits for the server's response, with range (0, infinity)
306  * @param allowRedirect True, to allow an automatic redirect of the specified URL
307  * @param redirectedURL Optional resulting URL if the request has been redirected
308  * @param replyCode Optional reply code of the GET request
309  * @param abort Optional flag that may be set to true by another thread to abort the request
310  * @param progressCallback Optional callback for receiving progress information
311  * @return True, if succeeded
312  */
313  static bool httpGetRequest(const std::string& url, Buffer& data, const Port& port = Port(80, Port::TYPE_READABLE), const double timeout = 5.0, bool allowRedirect = true, std::string* redirectedURL = nullptr, HTTPHeader::ReplyCode* replyCode = nullptr, bool* abort = nullptr, const ProgressCallback& progressCallback = ProgressCallback());
314 
315  protected:
316 
317  bool sendRequest(const std::string& uri, const std::string& requestMethod);
318 
319  /**
320  * The response event function.
321  * @param data The response data
322  * @param size The size of the data in bytes
323  */
324  void onResponse(const void* data, const size_t size);
325 
326  /**
327  * Converts a URL to a URI.
328  * @param url The URL to convert, e.g., 'http://www.website.com/index.html"
329  * @param protocol The resulting protocol, will be 'http' if successful
330  * @param host The resulting host without ending '/'
331  * @param uri The resulting URI, can be empty if the URL does not include an URI
332  * @return True, if succeeded
333  */
334  static bool url2uri(const std::string& url, std::string& protocol, std::string& host, std::string& uri);
335 
336  /**
337  * Parses a header from a given header string.
338  * @param data The header of header as string
339  * @param size The size of the given header string in bytes
340  * @param header The resulting parsed header
341  * @return True, if succeeded
342  */
343  static bool parseHeader(const char* data, const size_t size, HTTPHeader& header);
344 
345  /**
346  * Appends response data from a current request to a given buffer.
347  * @param header The header of the request
348  * @param buffer The target buffer receiving the data
349  * @param bufferPosition The current position in the target buffer
350  * @param payload The source data
351  * @param payloadSize The sizeof the source data
352  * @param pendingChunkSize Input and output size of the current chunk
353  * @return True, if the given payload was the last payload for the target buffer
354  */
355  static bool appendData(const HTTPHeader& header, Buffer& buffer, size_t& bufferPosition, const char* payload, size_t payloadSize, size_t& pendingChunkSize);
356 
357  /**
358  * Returns one line from a data buffer.
359  * @param data The data buffer
360  * @param size The size of the data buffer in bytes
361  * @param offset The offset which needs to be applied to skip the line
362  * @return The resulting line
363  */
364  static std::string line(const char* data, const size_t size, size_t& offset);
365 
366  /**
367  * Convert a hex string to a number.
368  * @param hex The hex string to be converted either lower case or upper case, without '0x' prefix
369  * @param value The resulting number
370  * @return True, if succeeded
371  */
372  static bool hexToNumber(const std::string& hex, unsigned int& value);
373 
374  /**
375  * Returns the HTTP version string for a given version number.
376  * @param version The version number for which the version string is returned
377  * @return The version string of the requested version number
378  */
379  static std::string httpVersionString(const ProtocolVersion version);
380 
381  protected:
382 
383  /// The TCP client of this HTTP client.
385 
386  /// The version of the client.
387  ProtocolVersion version_ = PV_HTTP_1_1;
388 
389  /// The URL of the HTTP server.
390  std::string host_;
391 
392  /// The port of the HTTP server.
394 
395  /// The response data queue.
397 
398  /// The lock of the client.
400 };
401 
403 {
404  return code_;
405 }
406 
407 inline size_t HTTPClient::HTTPHeader::length() const
408 {
409  return length_;
410 }
411 
413 {
414  return contentLength_;
415 }
416 
418 {
419  return transferEncodingChunked_;
420 }
421 
423 {
424  return encodingType_;
425 }
426 
427 inline std::string& HTTPClient::HTTPHeader::location()
428 {
429  return location_;
430 }
431 
433 {
434  return lines_;
435 }
436 
438 {
439  code_ = code;
440 }
441 
442 inline void HTTPClient::HTTPHeader::setVersion(const std::string& version)
443 {
444  version_ = version;
445 }
446 
447 inline void HTTPClient::HTTPHeader::setLength(const size_t length)
448 {
449  length_ = length;
450 }
451 
452 inline void HTTPClient::HTTPHeader::setContentLength(const size_t length)
453 {
454  contentLength_ = length;
455 }
456 
458 {
459  transferEncodingChunked_ = state;
460 }
461 
463 {
464  encodingType_ = type;
465 }
466 
467 inline void HTTPClient::HTTPHeader::setLocation(const std::string& location)
468 {
469  location_ = location;
470 }
471 
473 {
474  lines_ = std::move(lines);
475 }
476 
478 {
479  return code_ != RC_INVALID;
480 }
481 
482 }
483 
484 }
485 
486 #endif // FACEBOOK_NETWORK_HTTP_CLIENT_H
This class implements a container for callback functions.
Definition: Callback.h:3456
This class implements a recursive lock object.
Definition: Lock.h:31
This class implements a thread-safe buffer queue.
Definition: BufferQueue.h:29
@ TYPE_READABLE
Readable endian type which is platform specific.
Definition: Data.h:37
This class implements a http header wrapper.
Definition: HTTPClient.h:44
std::string version_
The version of the header.
Definition: HTTPClient.h:217
Lines lines_
The lines of this header.
Definition: HTTPClient.h:235
void setLines(Lines &&lines)
Sets the lines of this header.
Definition: HTTPClient.h:472
void setLength(const size_t length)
Sets the length of the header in bytes.
Definition: HTTPClient.h:447
ReplyCode code() const
Returns the reply code of this header.
Definition: HTTPClient.h:402
static bool parseHeaderLine(const std::string &line, HTTPHeader &header)
Parses a header line and updates the information in a given header object.
void setVersion(const std::string &version)
Sets the version of the http header.
Definition: HTTPClient.h:442
void setLocation(const std::string &location)
Sets the location value.
Definition: HTTPClient.h:467
std::string location_
The location for e.g., a redirect.
Definition: HTTPClient.h:232
void setCode(const ReplyCode code)
Sets the reply code of this header.
Definition: HTTPClient.h:437
EncodingType
Definition of individual content encoding types.
Definition: HTTPClient.h:86
@ ET_STANDARD
A standard encoding.
Definition: HTTPClient.h:88
void setTransferEncodingChunked(const bool state)
Sets the transfer encoding chunked state.
Definition: HTTPClient.h:457
bool isValid() const
Returns whether the code of this header is valid.
Definition: HTTPClient.h:477
size_t length() const
Returns the length of the header in bytes.
Definition: HTTPClient.h:407
void setContentEncodingType(const EncodingType type)
Sets the content encoding type.
Definition: HTTPClient.h:462
void setContentLength(const size_t length)
Sets the length of the content in bytes.
Definition: HTTPClient.h:452
std::string & location()
Returns the location value.
Definition: HTTPClient.h:427
HTTPHeader()=default
Creates a new header object.
bool transferEncodingChunked() const
Returns whether the transfer encoding is chunked.
Definition: HTTPClient.h:417
EncodingType encodingType() const
Returns the content encoding type.
Definition: HTTPClient.h:422
ReplyCode
Definition of individual http reply codes.
Definition: HTTPClient.h:53
const Lines & lines() const
Returns the lines of this header.
Definition: HTTPClient.h:432
size_t contentLength() const
Returns the length of the content in bytes.
Definition: HTTPClient.h:412
ReplyCode code_
The replay code the header.
Definition: HTTPClient.h:214
std::vector< std::string > Lines
Definition of a vector holding header lines.
Definition: HTTPClient.h:96
This class implements a basic http client.
Definition: HTTPClient.h:26
bool invokeHeadRequest(const std::string &uri, HTTPHeader &header, const double timeout=5.0)
Invokes a HEAD request.
bool invokeGetRequest(const std::string &uri, Buffer &data, const double timeout=5.0, std::string *urlRedirection=nullptr, HTTPHeader::ReplyCode *replyCode=nullptr, bool *abort=nullptr, const ProgressCallback &progressCallback=ProgressCallback())
Invokes a GET request.
BufferQueue responseQueue_
The response data queue.
Definition: HTTPClient.h:396
ProtocolVersion version_
The version of the client.
Definition: HTTPClient.h:387
static bool hexToNumber(const std::string &hex, unsigned int &value)
Convert a hex string to a number.
static std::string line(const char *data, const size_t size, size_t &offset)
Returns one line from a data buffer.
static bool appendData(const HTTPHeader &header, Buffer &buffer, size_t &bufferPosition, const char *payload, size_t payloadSize, size_t &pendingChunkSize)
Appends response data from a current request to a given buffer.
bool sendRequest(const std::string &uri, const std::string &requestMethod)
Callback< void, size_t, size_t > ProgressCallback
Callback for receiving progress information when performing a HTTP request.
Definition: HTTPClient.h:248
HTTPClient(const std::string &host, const Port &port=Port(80, Port::TYPE_READABLE))
Creates a new HTTP client object.
bool connect(const std::string &host, const Port &port=Port(80, Port::TYPE_READABLE))
(Re-)connects the client with the HTTP server.
static bool url2uri(const std::string &url, std::string &protocol, std::string &host, std::string &uri)
Converts a URL to a URI.
bool connect()
Connects the client with the HTTP server.
static bool parseHeader(const char *data, const size_t size, HTTPHeader &header)
Parses a header from a given header string.
static std::string httpVersionString(const ProtocolVersion version)
Returns the HTTP version string for a given version number.
~HTTPClient()
Destructs a HTTP client object.
TCPClient tcpClient_
The TCP client of this HTTP client.
Definition: HTTPClient.h:384
void onResponse(const void *data, const size_t size)
The response event function.
std::vector< uint8_t > Buffer
Definition of a vector holding characters.
Definition: HTTPClient.h:241
static bool httpGetRequest(const std::string &url, Buffer &data, const Port &port=Port(80, Port::TYPE_READABLE), const double timeout=5.0, bool allowRedirect=true, std::string *redirectedURL=nullptr, HTTPHeader::ReplyCode *replyCode=nullptr, bool *abort=nullptr, const ProgressCallback &progressCallback=ProgressCallback())
Helper function to executes an HTTP site/file request.
std::string host_
The URL of the HTTP server.
Definition: HTTPClient.h:390
Lock lock_
The lock of the client.
Definition: HTTPClient.h:399
Port port_
The port of the HTTP server.
Definition: HTTPClient.h:393
ProtocolVersion
Definition of individual protocol versions.
Definition: HTTPClient.h:33
@ PV_HTTP_1_0
The HTTP 1.0 version.
Definition: HTTPClient.h:35
This class wraps a port number with 16 bits.
Definition: Port.h:26
This class implements a TCP client.
Definition: TCPClient.h:27
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15