HTTPClient.h 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  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::string& content, Headers& headers);
  49. void get(const std::string& url, Headers headers = {});
  50. std::string_view body();
  51. std::vector<uint8_t> bytes();
  52. std::string_view header(const std::string& headerName);
  53. bell::SocketStream& stream() { return this->socketStream; }
  54. size_t contentLength();
  55. size_t totalLength();
  56. private:
  57. bell::URLParser urlParser;
  58. bell::SocketStream socketStream;
  59. struct phr_header phResponseHeaders[32];
  60. const size_t HTTP_BUF_SIZE = 1024;
  61. std::vector<uint8_t> httpBuffer = std::vector<uint8_t>(HTTP_BUF_SIZE);
  62. std::vector<uint8_t> rawBody = std::vector<uint8_t>();
  63. size_t httpBufferAvailable;
  64. size_t contentSize = 0;
  65. bool hasContentSize = false;
  66. Headers responseHeaders;
  67. void readResponseHeaders();
  68. void readRawBody();
  69. };
  70. enum class Method : uint8_t { GET = 0, POST = 1 };
  71. struct Request {
  72. std::string url;
  73. Method method;
  74. Headers headers;
  75. };
  76. static std::unique_ptr<Response> get(const std::string& url,
  77. Headers headers = {}) {
  78. auto response = std::make_unique<Response>();
  79. response->connect(url);
  80. response->get(url, headers);
  81. return response;
  82. }
  83. };
  84. } // namespace bell