123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257 |
- /*
- * HTTP.h
- * ------
- * Purpose: Simple HTTP client interface.
- * Notes : (currently none)
- * Authors: OpenMPT Devs
- * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
- */
- #pragma once
- #include "openmpt/all/BuildSettings.hpp"
- #include <functional>
- #include <iosfwd>
- #include <optional>
- OPENMPT_NAMESPACE_BEGIN
- struct URI
- {
- mpt::ustring scheme;
- mpt::ustring username;
- mpt::ustring password;
- mpt::ustring host;
- mpt::ustring port;
- mpt::ustring path;
- mpt::ustring query;
- mpt::ustring fragment;
- };
- class bad_uri
- : public std::runtime_error
- {
- public:
- bad_uri(const std::string &msg)
- : std::runtime_error(msg)
- {
- }
- };
- URI ParseURI(mpt::ustring str);
- namespace HTTP
- {
- class exception
- : public std::runtime_error
- {
- private:
- mpt::ustring message;
- public:
- exception(const mpt::ustring &m);
- mpt::ustring GetMessage() const;
- };
- class status_exception
- : public std::runtime_error
- {
- public:
- status_exception(uint64 status)
- : std::runtime_error(MPT_AFORMAT("HTTP status {}")(status))
- {
- return;
- }
- };
- class Abort
- : public exception
- {
- public:
- Abort() :
- exception(U_("Operation aborted."))
- {
- return;
- }
- };
- struct NativeHandle;
- class Handle
- {
- private:
- std::unique_ptr<NativeHandle> handle;
- public:
- Handle();
- Handle(const Handle &) = delete;
- Handle & operator=(const Handle &) = delete;
- explicit operator bool() const;
- bool operator!() const;
- Handle(NativeHandle h);
- Handle & operator=(NativeHandle h);
- operator NativeHandle ();
- ~Handle();
- };
- class InternetSession
- {
- private:
- Handle internet;
- public:
- InternetSession(mpt::ustring userAgent);
- operator NativeHandle ();
- template <typename TRequest>
- auto operator()(const TRequest &request) -> decltype(request(*this))
- {
- return request(*this);
- }
- template <typename TRequest>
- auto Request(const TRequest &request) -> decltype(request(*this))
- {
- return request(*this);
- }
- };
- enum class Protocol
- {
- HTTP,
- HTTPS,
- };
- enum class Port : uint16
- {
- Default = 0,
- HTTP = 80,
- HTTPS = 443,
- };
- enum class Method
- {
- Get,
- Head,
- Post,
- Put,
- Delete,
- Trace,
- Options,
- Connect,
- Patch,
- };
- using Query = std::vector<std::pair<mpt::ustring, mpt::ustring>>;
- namespace MimeType {
- inline std::string Text() { return "text/plain"; }
- inline std::string JSON() { return "application/json"; }
- inline std::string Binary() { return "application/octet-stream"; }
- }
- using AcceptMimeTypes = std::vector<std::string>;
- namespace MimeTypes {
- inline AcceptMimeTypes Text() { return {"text/*"}; }
- inline AcceptMimeTypes JSON() { return {MimeType::JSON()}; }
- inline AcceptMimeTypes Binary() { return {MimeType::Binary()}; }
- }
- using Headers = std::vector<std::pair<std::string, std::string>>;
- enum Flags
- {
- None = 0x00u,
- NoCache = 0x01u,
- AutoRedirect = 0x02u,
- };
- struct Result
- {
- uint64 Status = 0;
- std::optional<uint64> ContentLength;
- std::vector<std::byte> Data;
- void CheckStatus(uint64 expected) const
- {
- if(Status != expected)
- {
- throw status_exception(Status);
- }
- }
- };
- enum class Progress
- {
- Start = 1,
- ConnectionEstablished = 2,
- RequestOpened = 3,
- RequestSent = 4,
- ResponseReceived = 5,
- TransferBegin = 6,
- TransferRunning = 7,
- TransferDone = 8,
- };
- struct Request
- {
- Protocol protocol = Protocol::HTTPS;
- mpt::ustring host;
- Port port = Port::Default;
- mpt::ustring username;
- mpt::ustring password;
- Method method = Method::Get;
- mpt::ustring path = U_("/");
- Query query;
- mpt::ustring referrer;
- AcceptMimeTypes acceptMimeTypes;
- Flags flags = None;
- Headers headers;
- std::string dataMimeType;
- mpt::const_byte_span data;
- std::ostream *outputStream = nullptr;
- std::function<void(Progress, uint64, std::optional<uint64>)> progressCallback = nullptr;
- Request &SetURI(const URI &uri);
- #if defined(MPT_BUILD_RETRO)
- Request &InsecureTLSDowngradeWindowsXP();
- #endif // MPT_BUILD_RETRO
- Result operator()(InternetSession &internet) const;
- private:
- void progress(Progress progress, uint64 transferred, std::optional<uint64> expectedSize) const;
- };
- Result SimpleGet(InternetSession &internet, Protocol protocol, const mpt::ustring &host, const mpt::ustring &path);
- } // namespace HTTP
- OPENMPT_NAMESPACE_END
|