HTTPClient.h 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. #pragma once
  2. #include <memory>
  3. #include <stdexcept>
  4. #include <string>
  5. #include <string_view>
  6. #include <unordered_map>
  7. #include <variant>
  8. #include <vector>
  9. #include <cassert>
  10. #include "BellSocket.h"
  11. #include "ByteStream.h"
  12. #include "SocketStream.h"
  13. #include "URLParser.h"
  14. #ifndef BELL_DISABLE_FMT
  15. #include "fmt/core.h"
  16. #endif
  17. #include "picohttpparser.h"
  18. namespace bell {
  19. class HTTPClient {
  20. public:
  21. // most basic header type, represents by a key-val
  22. typedef std::pair<std::string, std::string> ValueHeader;
  23. typedef std::vector<ValueHeader> Headers;
  24. // Helper over ValueHeader, formatting a HTTP bytes range
  25. struct RangeHeader {
  26. static ValueHeader range(int32_t from, int32_t to) {
  27. #ifndef BELL_DISABLE_FMT
  28. return ValueHeader{"Range", fmt::format("bytes={}-{}", from, to)};
  29. #else
  30. return ValueHeader{"Range", "bytes=" + std::to_string(from) + "-" + std::to_string(to)};
  31. #endif
  32. }
  33. static ValueHeader last(int32_t nbytes) {
  34. #ifndef BELL_DISABLE_FMT
  35. return ValueHeader{"Range", fmt::format("bytes=-{}", nbytes)};
  36. #else
  37. return ValueHeader{"Range", "bytes=-" + std::to_string(nbytes)};
  38. #endif
  39. }
  40. };
  41. class Response {
  42. public:
  43. Response(){};
  44. ~Response();
  45. /**
  46. * Initializes a connection with a given url.
  47. */
  48. void connect(const std::string& url);
  49. void rawRequest(const std::string& method, const std::string& url,
  50. const std::string& content, Headers& headers);
  51. void get(const std::string& url, Headers headers = {});
  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. };
  86. } // namespace bell