HTTPClient.h 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. #pragma once
  2. #include <stddef.h> // for size_t
  3. #include <cstdint> // for uint8_t, int32_t
  4. #include <memory> // for make_unique, unique_ptr
  5. #include <string> // for string
  6. #include <string_view> // for string_view
  7. #include <utility> // for pair
  8. #include <vector> // for vector
  9. #include "SocketStream.h" // for SocketStream
  10. #include "URLParser.h" // for URLParser
  11. #ifndef BELL_DISABLE_FMT
  12. #include "fmt/core.h" // for format
  13. #endif
  14. #include "picohttpparser.h" // for phr_header
  15. namespace bell {
  16. class HTTPClient {
  17. public:
  18. // most basic header type, represents by a key-val
  19. typedef std::pair<std::string, std::string> ValueHeader;
  20. typedef std::vector<ValueHeader> Headers;
  21. // Helper over ValueHeader, formatting a HTTP bytes range
  22. struct RangeHeader {
  23. static ValueHeader range(int32_t from, int32_t to) {
  24. #ifndef BELL_DISABLE_FMT
  25. return ValueHeader{"Range", fmt::format("bytes={}-{}", from, to)};
  26. #else
  27. return ValueHeader{
  28. "Range", "bytes=" + std::to_string(from) + "-" + std::to_string(to)};
  29. #endif
  30. }
  31. static ValueHeader last(int32_t nbytes) {
  32. #ifndef BELL_DISABLE_FMT
  33. return ValueHeader{"Range", fmt::format("bytes=-{}", nbytes)};
  34. #else
  35. return ValueHeader{"Range", "bytes=-" + std::to_string(nbytes)};
  36. #endif
  37. }
  38. };
  39. class Response {
  40. public:
  41. Response(){};
  42. ~Response();
  43. /**
  44. * Initializes a connection with a given url.
  45. */
  46. void connect(const std::string& url);
  47. void rawRequest(const std::string& method, const std::string& url,
  48. const std::vector<uint8_t>& content, Headers& headers);
  49. void get(const std::string& url, Headers headers = {});
  50. void post(const std::string& url, Headers headers = {},
  51. const std::vector<uint8_t>& body = {});
  52. std::string_view body();
  53. std::vector<uint8_t> bytes();
  54. std::string_view header(const std::string& headerName);
  55. bell::SocketStream& stream() { return this->socketStream; }
  56. size_t contentLength();
  57. size_t totalLength();
  58. private:
  59. bell::URLParser urlParser;
  60. bell::SocketStream socketStream;
  61. struct phr_header phResponseHeaders[32];
  62. const size_t HTTP_BUF_SIZE = 1024;
  63. std::vector<uint8_t> httpBuffer = std::vector<uint8_t>(HTTP_BUF_SIZE);
  64. std::vector<uint8_t> rawBody = std::vector<uint8_t>();
  65. size_t httpBufferAvailable;
  66. size_t contentSize = 0;
  67. bool hasContentSize = false;
  68. Headers responseHeaders;
  69. void readResponseHeaders();
  70. void readRawBody();
  71. };
  72. enum class Method : uint8_t { GET = 0, POST = 1 };
  73. struct Request {
  74. std::string url;
  75. Method method;
  76. Headers headers;
  77. };
  78. static std::unique_ptr<Response> get(const std::string& url,
  79. Headers headers = {}) {
  80. auto response = std::make_unique<Response>();
  81. response->connect(url);
  82. response->get(url, headers);
  83. return response;
  84. }
  85. static std::unique_ptr<Response> post(const std::string& url,
  86. Headers headers = {},
  87. const std::vector<uint8_t>& body = {}) {
  88. auto response = std::make_unique<Response>();
  89. response->connect(url);
  90. response->post(url, headers, body);
  91. return response;
  92. }
  93. };
  94. } // namespace bell