#ifndef _UTIL_HTTP_CLIENT_H #define _UTIL_HTTP_CLIENT_H #include #include #include #include #include #include "cstr_util.h" #include "utils_config.h" #if _WIN32 #include #include #else #include #include #include #endif #if HAVE_OPENSSL #include "openssl/ssl.h" #endif struct HeaderNameCompare { bool operator()(const std::string& a, const std::string& b) const { return cstr_stricmp(a.c_str(), b.c_str()) < 0; } }; typedef std::map HeaderMap; std::string decodeURIComponent(std::string str); class HttpClientOptions { public: bool https = false; }; class HttpBody { public: virtual size_t pullData(char* buf, size_t len) = 0; virtual bool isFinished() = 0; virtual std::string contentType() = 0; virtual bool hasLength() = 0; virtual size_t length() = 0; }; class HttpFullBody: public HttpBody { public: virtual size_t pullData(char* buf, size_t len); virtual bool isFinished(); virtual bool hasLength(); virtual std::string contentType(); virtual size_t length(); protected: virtual std::string body() = 0; private: void pull(); std::string buff; bool pulled; size_t len; }; class QueryData: public HttpFullBody { public: QueryData(); QueryData(std::string data); std::string contentType(); std::map> data; std::string toQuery(); void append(std::string key, std::string value); void set(std::string key, std::string value); protected: std::string body(); }; class AIException: std::exception { public: AIException(int code); const char* what(); private: int code; }; class SocketError: std::exception { public: SocketError(); const char* what(); private: int code; std::string message; }; class Socket { public: Socket(std::string host, std::string protocol); ~Socket(); void connect(); size_t send(const char* data, size_t len, int flags = 0); template size_t send(const char(&data)[T], int flags = 0) { return this->send(data, T, flags); } size_t send(std::string data, int flags = 0); size_t recv(char* data, size_t len, int flags = 0); template size_t recv(char(&data)[T], int flags = 0) { return this->recv(data, T, flags); } std::string recv(size_t len, int flags = 0); void close(); private: #if HAVE_OPENSSL SSL_CTX* ssl_ctx = nullptr; BIO* web = nullptr; SSL* ssl = nullptr; #endif std::string host; std::string protocol; int socket = -1; bool closed = false; addrinfo* addr = nullptr; }; class Request { public: Request(std::string host, std::string path, std::string method, HeaderMap headers, HttpClientOptions options); ~Request(); void send(); HeaderMap headers; HttpClientOptions options; void setBody(HttpBody* body) { if (this->body != nullptr) delete this->body; this->body = body; } private: HttpBody* body = nullptr; std::string host; std::string path; std::string method; }; class Response { public: Response(Request req, Socket socket); private: Request req; Socket socket; }; class HttpClient { public: HttpClient(std::string host); Request request(std::string path, std::string method); HttpClientOptions options; HeaderMap headers; private: std::string host; }; #endif