2022-10-05 08:41:05 -04:00
|
|
|
#pragma once
|
|
|
|
|
2024-06-07 05:20:39 -04:00
|
|
|
#include <Geode/loader/Loader.hpp> // another great circular dependency fix
|
2023-12-30 12:42:53 -05:00
|
|
|
#include <matjson.hpp>
|
2022-12-04 11:39:40 -05:00
|
|
|
#include "Result.hpp"
|
2024-06-07 05:20:39 -04:00
|
|
|
#include "Task.hpp"
|
2024-01-03 21:12:23 -05:00
|
|
|
#include <chrono>
|
2024-06-07 05:20:39 -04:00
|
|
|
#include <optional>
|
2022-10-05 08:41:05 -04:00
|
|
|
|
|
|
|
namespace geode::utils::web {
|
2022-11-28 12:09:39 -05:00
|
|
|
GEODE_DLL void openLinkInBrowser(std::string const& url);
|
2024-06-07 05:20:39 -04:00
|
|
|
|
|
|
|
// https://curl.se/libcurl/c/CURLOPT_HTTPAUTH.html
|
|
|
|
namespace http_auth {
|
|
|
|
constexpr static long BASIC = 0x0001;
|
|
|
|
constexpr static long DIGEST = 0x0002;
|
|
|
|
constexpr static long DIGEST_IE = 0x0004;
|
|
|
|
constexpr static long BEARER = 0x0008;
|
|
|
|
constexpr static long NEGOTIATE = 0x0010;
|
|
|
|
constexpr static long NTLM = 0x0020;
|
|
|
|
constexpr static long NTLM_WB = 0x0040;
|
|
|
|
constexpr static long ANY = 0x0080;
|
|
|
|
constexpr static long ANYSAFE = 0x0100;
|
|
|
|
constexpr static long ONLY = 0x0200;
|
|
|
|
constexpr static long AWS_SIGV4 = 0x0400;
|
|
|
|
}
|
2022-12-04 11:39:40 -05:00
|
|
|
|
2024-06-23 15:45:12 -04:00
|
|
|
// https://curl.se/libcurl/c/CURLOPT_HTTP_VERSION.html
|
|
|
|
enum class HttpVersion {
|
|
|
|
DEFAULT,
|
|
|
|
VERSION_1_0,
|
|
|
|
VERSION_1_1,
|
|
|
|
VERSION_2_0,
|
|
|
|
VERSION_2TLS,
|
|
|
|
VERSION_2_PRIOR_KNOWLEDGE,
|
|
|
|
VERSION_3 = 30,
|
|
|
|
VERSION_3ONLY = 31
|
|
|
|
};
|
|
|
|
|
2024-06-07 05:20:39 -04:00
|
|
|
// https://curl.se/libcurl/c/CURLOPT_PROXYTYPE.html
|
|
|
|
enum class ProxyType {
|
|
|
|
HTTP, // HTTP
|
|
|
|
HTTPS, // HTTPS
|
|
|
|
HTTPS2, // HTTPS (attempt to use HTTP/2)
|
|
|
|
SOCKS4, // Socks4
|
|
|
|
SOCKS4A, // Socks4 with hostname resolution
|
|
|
|
SOCKS5, // Socks5
|
|
|
|
SOCKS5H, // Socks5 with hostname resolution
|
|
|
|
};
|
2022-10-12 17:22:43 -04:00
|
|
|
|
2024-06-07 05:20:39 -04:00
|
|
|
struct ProxyOpts {
|
|
|
|
std::string address; // Proxy address/FQDN
|
|
|
|
std::optional<std::uint16_t> port; // Proxy port
|
|
|
|
ProxyType type = ProxyType::HTTP; // Proxy type
|
|
|
|
long auth = http_auth::BASIC; // HTTP proxy auth method
|
|
|
|
std::string username; // Proxy username
|
|
|
|
std::string password; // Proxy password
|
|
|
|
bool tunneling = false; // Enable HTTP tunneling
|
|
|
|
bool certVerification = true; // Enable HTTPS certificate verification
|
|
|
|
};
|
2022-10-12 17:22:43 -04:00
|
|
|
|
2024-06-07 05:20:39 -04:00
|
|
|
class WebRequest;
|
2022-10-12 17:22:43 -04:00
|
|
|
|
2024-06-07 05:20:39 -04:00
|
|
|
class GEODE_DLL WebResponse final {
|
2022-10-12 17:22:43 -04:00
|
|
|
private:
|
2022-12-12 07:40:05 -05:00
|
|
|
class Impl;
|
2022-10-12 17:22:43 -04:00
|
|
|
|
2024-06-07 05:20:39 -04:00
|
|
|
std::shared_ptr<Impl> m_impl;
|
2022-10-12 17:22:43 -04:00
|
|
|
|
2024-06-07 05:20:39 -04:00
|
|
|
friend class WebRequest;
|
2022-10-12 17:22:43 -04:00
|
|
|
|
|
|
|
public:
|
2024-06-07 05:20:39 -04:00
|
|
|
// Must be default-constructible for use in Promise
|
|
|
|
WebResponse();
|
|
|
|
|
|
|
|
bool ok() const;
|
|
|
|
int code() const;
|
|
|
|
|
|
|
|
Result<std::string> string() const;
|
|
|
|
Result<matjson::Value> json() const;
|
|
|
|
ByteVector data() const;
|
2024-06-08 11:11:08 -04:00
|
|
|
Result<> into(std::filesystem::path const& path) const;
|
2024-06-23 15:45:12 -04:00
|
|
|
|
2024-06-07 05:20:39 -04:00
|
|
|
std::vector<std::string> headers() const;
|
|
|
|
std::optional<std::string> header(std::string_view name) const;
|
2022-10-12 17:22:43 -04:00
|
|
|
};
|
|
|
|
|
2024-06-07 05:20:39 -04:00
|
|
|
class GEODE_DLL WebProgress final {
|
2022-10-12 21:50:41 -04:00
|
|
|
private:
|
2024-01-03 20:17:27 -05:00
|
|
|
class Impl;
|
2023-09-08 10:17:45 -04:00
|
|
|
|
2024-06-07 05:20:39 -04:00
|
|
|
std::shared_ptr<Impl> m_impl;
|
2022-10-12 21:50:41 -04:00
|
|
|
|
2024-06-07 05:20:39 -04:00
|
|
|
friend class WebRequest;
|
|
|
|
|
2022-10-12 21:50:41 -04:00
|
|
|
public:
|
2024-06-07 05:20:39 -04:00
|
|
|
// Must be default-constructible for use in Promise
|
|
|
|
WebProgress();
|
2024-01-09 18:10:58 -05:00
|
|
|
|
2024-06-07 05:20:39 -04:00
|
|
|
size_t downloaded() const;
|
|
|
|
size_t downloadTotal() const;
|
|
|
|
std::optional<float> downloadProgress() const;
|
2024-01-09 18:10:58 -05:00
|
|
|
|
2024-06-07 05:20:39 -04:00
|
|
|
size_t uploaded() const;
|
|
|
|
size_t uploadTotal() const;
|
|
|
|
std::optional<float> uploadProgress() const;
|
2022-10-12 21:50:41 -04:00
|
|
|
};
|
|
|
|
|
2024-06-07 05:20:39 -04:00
|
|
|
using WebTask = Task<WebResponse, WebProgress>;
|
2022-10-12 17:22:43 -04:00
|
|
|
|
2024-06-07 05:20:39 -04:00
|
|
|
class GEODE_DLL WebRequest final {
|
|
|
|
private:
|
|
|
|
class Impl;
|
2022-10-30 14:59:20 -04:00
|
|
|
|
2024-06-07 05:20:39 -04:00
|
|
|
std::shared_ptr<Impl> m_impl;
|
2022-10-12 17:22:43 -04:00
|
|
|
|
|
|
|
public:
|
2024-06-07 05:20:39 -04:00
|
|
|
WebRequest();
|
|
|
|
~WebRequest();
|
2022-10-12 17:22:43 -04:00
|
|
|
|
2024-06-07 05:20:39 -04:00
|
|
|
WebTask send(std::string_view method, std::string_view url);
|
|
|
|
WebTask post(std::string_view url);
|
|
|
|
WebTask get(std::string_view url);
|
|
|
|
WebTask put(std::string_view url);
|
|
|
|
WebTask patch(std::string_view url);
|
2022-10-12 17:22:43 -04:00
|
|
|
|
2024-06-07 05:20:39 -04:00
|
|
|
WebRequest& header(std::string_view name, std::string_view value);
|
|
|
|
WebRequest& param(std::string_view name, std::string_view value);
|
|
|
|
template <std::integral T>
|
|
|
|
WebRequest& param(std::string_view name, T value) {
|
|
|
|
return this->param(name, std::to_string(value));
|
|
|
|
}
|
2022-10-12 17:22:43 -04:00
|
|
|
|
2024-06-23 15:45:12 -04:00
|
|
|
/**
|
|
|
|
* Sets the request's user agent.
|
|
|
|
* Defaults to not sending the User-Agent: header.
|
|
|
|
*
|
|
|
|
* @param name
|
|
|
|
* @return WebRequest&
|
|
|
|
*/
|
2024-06-07 05:20:39 -04:00
|
|
|
WebRequest& userAgent(std::string_view name);
|
2022-10-12 17:22:43 -04:00
|
|
|
|
2024-06-23 15:45:12 -04:00
|
|
|
/**
|
|
|
|
* Sets the response's encoding. Valid values include: br, gzip, deflate, ...
|
|
|
|
* You can set multiple encoding types by calling this method with a comma separated list
|
|
|
|
* of the encodings of your choosing.
|
|
|
|
* Defaults to not sending an Accept-Encoding: header, and in turn, does not decompress received contents automatically.
|
|
|
|
*
|
|
|
|
* @example
|
|
|
|
* auto req = web::WebRequest()
|
|
|
|
* .acceptEncoding("gzip, deflate")
|
|
|
|
* .get(url);
|
|
|
|
*
|
|
|
|
* @param encodingType Target response encoding type. An empty string ("") will use all built-in supported encodings.
|
|
|
|
* @return WebRequest&
|
|
|
|
*/
|
|
|
|
WebRequest& acceptEncoding(std::string_view encodingType);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets the maximum amount of seconds to allow the entire transfer operation to take.
|
|
|
|
* The default timeout is 0, which means the request never times out during transfer.
|
|
|
|
*
|
|
|
|
* @param time
|
|
|
|
* @return WebRequest&
|
|
|
|
*/
|
2024-06-07 05:20:39 -04:00
|
|
|
WebRequest& timeout(std::chrono::seconds time);
|
2022-10-30 14:59:20 -04:00
|
|
|
|
2024-06-23 15:45:12 -04:00
|
|
|
/**
|
|
|
|
* Sets the target byte range to request.
|
|
|
|
* Defaults to receiving the full request.
|
|
|
|
*
|
|
|
|
* @param byteRange a pair of ints, first value is what byte to start from, second value is the last byte to get (both inclusive)
|
|
|
|
* @return WebRequest&
|
|
|
|
*/
|
|
|
|
WebRequest& downloadRange(std::pair<std::uint64_t, std::uint64_t> byteRange);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Enable or disables peer verification in SSL handshake.
|
|
|
|
* The default is true.
|
|
|
|
*
|
|
|
|
* @param enabled
|
|
|
|
* @return WebRequest&
|
|
|
|
*/
|
2024-06-07 05:20:39 -04:00
|
|
|
WebRequest& certVerification(bool enabled);
|
2024-06-23 15:45:12 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Enables or disabled getting the body of a request. For HTTP(S), this does a HEAD request.
|
|
|
|
* For most other protocols it means just not asking to transfer the body data.
|
|
|
|
* The default is true.
|
|
|
|
*
|
|
|
|
* @param enabled
|
|
|
|
* @return WebRequest&
|
|
|
|
*/
|
|
|
|
WebRequest& transferBody(bool enabled);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Follow HTTP 3xx redirects.
|
|
|
|
* The default is true.
|
|
|
|
*
|
|
|
|
* @param enabled
|
|
|
|
* @return WebRequest&
|
|
|
|
*/
|
|
|
|
WebRequest& followRedirects(bool enabled);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets the Certificate Authority (CA) bundle content.
|
|
|
|
* Defaults to not sending a CA bundle.
|
|
|
|
*
|
|
|
|
* @param content
|
|
|
|
* @return WebRequest&
|
|
|
|
*/
|
2024-06-07 05:20:39 -04:00
|
|
|
WebRequest& CABundleContent(std::string_view content);
|
2024-06-23 15:45:12 -04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets the request's proxy.
|
|
|
|
* Defaults to not using a proxy.
|
|
|
|
*
|
|
|
|
* @param proxyOpts
|
|
|
|
* @return WebRequest&
|
|
|
|
*/
|
2024-06-07 05:20:39 -04:00
|
|
|
WebRequest& proxyOpts(ProxyOpts const& proxyOpts);
|
2022-10-13 09:36:36 -04:00
|
|
|
|
2024-06-23 15:45:12 -04:00
|
|
|
/**
|
|
|
|
* Sets the request's HTTP version.
|
|
|
|
* The default is HttpVersion::VERSION_2TLS.
|
|
|
|
*
|
|
|
|
* @param httpVersion
|
|
|
|
* @return WebRequest&
|
|
|
|
*/
|
|
|
|
WebRequest& version(HttpVersion httpVersion);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets the body of the request to a byte vector.
|
|
|
|
*
|
|
|
|
* @param raw The raw bytes to set as the body.
|
|
|
|
* @return WebRequest&
|
|
|
|
*/
|
2024-06-07 05:20:39 -04:00
|
|
|
WebRequest& body(ByteVector raw);
|
2024-06-23 15:45:12 -04:00
|
|
|
/**
|
|
|
|
* Sets the body of the request to a string.
|
|
|
|
*
|
|
|
|
* @param str The string to set as the body.
|
|
|
|
* @return WebRequest&
|
|
|
|
*/
|
2024-06-07 05:20:39 -04:00
|
|
|
WebRequest& bodyString(std::string_view str);
|
2024-06-23 15:45:12 -04:00
|
|
|
/**
|
|
|
|
* Sets the body of the request to a json object.
|
|
|
|
*
|
|
|
|
* @param json
|
|
|
|
* @return WebRequest&
|
|
|
|
*/
|
2024-06-07 05:20:39 -04:00
|
|
|
WebRequest& bodyJSON(matjson::Value const& json);
|
2024-06-30 10:32:06 -04:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets the request method as a string
|
|
|
|
*
|
|
|
|
* @return std::string
|
|
|
|
*/
|
|
|
|
std::string getMethod() const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets the request URL
|
|
|
|
*
|
|
|
|
* @return std::string
|
|
|
|
*/
|
|
|
|
std::string getUrl() const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets the request headers
|
|
|
|
*
|
|
|
|
* @return std::unordered_map<std::string, std::string>
|
|
|
|
*/
|
|
|
|
std::unordered_map<std::string, std::string> getHeaders() const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets the parameters inside the URL
|
|
|
|
*
|
|
|
|
* @return std::unordered_map<std::string, std::string>
|
|
|
|
*/
|
|
|
|
std::unordered_map<std::string, std::string> getUrlParams() const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets the post body stream
|
|
|
|
*
|
|
|
|
* @return std::optional<ByteVector>
|
|
|
|
*/
|
|
|
|
std::optional<ByteVector> getBody() const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets the request timeout in seconds
|
|
|
|
*
|
|
|
|
* @return std::optional<std::chrono::seconds>
|
|
|
|
*/
|
|
|
|
std::optional<std::chrono::seconds> getTimeout() const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets HTTP versions applied to the request
|
|
|
|
*
|
|
|
|
* @return HttpVersion
|
|
|
|
*/
|
|
|
|
HttpVersion getHttpVersion() const;
|
2024-06-07 05:20:39 -04:00
|
|
|
};
|
2022-10-05 08:41:05 -04:00
|
|
|
}
|