HTTP.h 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. /*
  2. * HTTP.h
  3. * ------
  4. * Purpose: Simple HTTP client interface.
  5. * Notes : (currently none)
  6. * Authors: OpenMPT Devs
  7. * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
  8. */
  9. #pragma once
  10. #include "openmpt/all/BuildSettings.hpp"
  11. #include <functional>
  12. #include <iosfwd>
  13. #include <optional>
  14. OPENMPT_NAMESPACE_BEGIN
  15. struct URI
  16. {
  17. mpt::ustring scheme;
  18. mpt::ustring username;
  19. mpt::ustring password;
  20. mpt::ustring host;
  21. mpt::ustring port;
  22. mpt::ustring path;
  23. mpt::ustring query;
  24. mpt::ustring fragment;
  25. };
  26. class bad_uri
  27. : public std::runtime_error
  28. {
  29. public:
  30. bad_uri(const std::string &msg)
  31. : std::runtime_error(msg)
  32. {
  33. }
  34. };
  35. URI ParseURI(mpt::ustring str);
  36. namespace HTTP
  37. {
  38. class exception
  39. : public std::runtime_error
  40. {
  41. private:
  42. mpt::ustring message;
  43. public:
  44. exception(const mpt::ustring &m);
  45. mpt::ustring GetMessage() const;
  46. };
  47. class status_exception
  48. : public std::runtime_error
  49. {
  50. public:
  51. status_exception(uint64 status)
  52. : std::runtime_error(MPT_AFORMAT("HTTP status {}")(status))
  53. {
  54. return;
  55. }
  56. };
  57. class Abort
  58. : public exception
  59. {
  60. public:
  61. Abort() :
  62. exception(U_("Operation aborted."))
  63. {
  64. return;
  65. }
  66. };
  67. struct NativeHandle;
  68. class Handle
  69. {
  70. private:
  71. std::unique_ptr<NativeHandle> handle;
  72. public:
  73. Handle();
  74. Handle(const Handle &) = delete;
  75. Handle & operator=(const Handle &) = delete;
  76. explicit operator bool() const;
  77. bool operator!() const;
  78. Handle(NativeHandle h);
  79. Handle & operator=(NativeHandle h);
  80. operator NativeHandle ();
  81. ~Handle();
  82. };
  83. class InternetSession
  84. {
  85. private:
  86. Handle internet;
  87. public:
  88. InternetSession(mpt::ustring userAgent);
  89. operator NativeHandle ();
  90. template <typename TRequest>
  91. auto operator()(const TRequest &request) -> decltype(request(*this))
  92. {
  93. return request(*this);
  94. }
  95. template <typename TRequest>
  96. auto Request(const TRequest &request) -> decltype(request(*this))
  97. {
  98. return request(*this);
  99. }
  100. };
  101. enum class Protocol
  102. {
  103. HTTP,
  104. HTTPS,
  105. };
  106. enum class Port : uint16
  107. {
  108. Default = 0,
  109. HTTP = 80,
  110. HTTPS = 443,
  111. };
  112. enum class Method
  113. {
  114. Get,
  115. Head,
  116. Post,
  117. Put,
  118. Delete,
  119. Trace,
  120. Options,
  121. Connect,
  122. Patch,
  123. };
  124. using Query = std::vector<std::pair<mpt::ustring, mpt::ustring>>;
  125. namespace MimeType {
  126. inline std::string Text() { return "text/plain"; }
  127. inline std::string JSON() { return "application/json"; }
  128. inline std::string Binary() { return "application/octet-stream"; }
  129. }
  130. using AcceptMimeTypes = std::vector<std::string>;
  131. namespace MimeTypes {
  132. inline AcceptMimeTypes Text() { return {"text/*"}; }
  133. inline AcceptMimeTypes JSON() { return {MimeType::JSON()}; }
  134. inline AcceptMimeTypes Binary() { return {MimeType::Binary()}; }
  135. }
  136. using Headers = std::vector<std::pair<std::string, std::string>>;
  137. enum Flags
  138. {
  139. None = 0x00u,
  140. NoCache = 0x01u,
  141. AutoRedirect = 0x02u,
  142. };
  143. struct Result
  144. {
  145. uint64 Status = 0;
  146. std::optional<uint64> ContentLength;
  147. std::vector<std::byte> Data;
  148. void CheckStatus(uint64 expected) const
  149. {
  150. if(Status != expected)
  151. {
  152. throw status_exception(Status);
  153. }
  154. }
  155. };
  156. enum class Progress
  157. {
  158. Start = 1,
  159. ConnectionEstablished = 2,
  160. RequestOpened = 3,
  161. RequestSent = 4,
  162. ResponseReceived = 5,
  163. TransferBegin = 6,
  164. TransferRunning = 7,
  165. TransferDone = 8,
  166. };
  167. struct Request
  168. {
  169. Protocol protocol = Protocol::HTTPS;
  170. mpt::ustring host;
  171. Port port = Port::Default;
  172. mpt::ustring username;
  173. mpt::ustring password;
  174. Method method = Method::Get;
  175. mpt::ustring path = U_("/");
  176. Query query;
  177. mpt::ustring referrer;
  178. AcceptMimeTypes acceptMimeTypes;
  179. Flags flags = None;
  180. Headers headers;
  181. std::string dataMimeType;
  182. mpt::const_byte_span data;
  183. std::ostream *outputStream = nullptr;
  184. std::function<void(Progress, uint64, std::optional<uint64>)> progressCallback = nullptr;
  185. Request &SetURI(const URI &uri);
  186. #if defined(MPT_BUILD_RETRO)
  187. Request &InsecureTLSDowngradeWindowsXP();
  188. #endif // MPT_BUILD_RETRO
  189. Result operator()(InternetSession &internet) const;
  190. private:
  191. void progress(Progress progress, uint64 transferred, std::optional<uint64> expectedSize) const;
  192. };
  193. Result SimpleGet(InternetSession &internet, Protocol protocol, const mpt::ustring &host, const mpt::ustring &path);
  194. } // namespace HTTP
  195. OPENMPT_NAMESPACE_END