/* * IXHttpClient.h * Author: Benjamin Sergeant * Copyright (c) 2019 Machine Zone, Inc. All rights reserved. */ #pragma once #include "IXSocket.h" #include "IXWebSocketHttpHeaders.h" #include #include #include #include #include #include #include #include #include namespace ix { enum class HttpErrorCode : int { Ok = 0, CannotConnect = 1, Timeout = 2, Gzip = 3, UrlMalformed = 4, CannotCreateSocket = 5, SendError = 6, ReadError = 7, CannotReadStatusLine = 8, MissingStatus = 9, HeaderParsingError = 10, MissingLocation = 11, TooManyRedirects = 12, ChunkReadError = 13, CannotReadBody = 14, Invalid = 100 }; struct HttpResponse { int statusCode; HttpErrorCode errorCode; WebSocketHttpHeaders headers; std::string payload; std::string errorMsg; uint64_t uploadSize; uint64_t downloadSize; HttpResponse(int s = 0, const HttpErrorCode& c = HttpErrorCode::Ok, const WebSocketHttpHeaders& h = WebSocketHttpHeaders(), const std::string& p = std::string(), const std::string& e = std::string(), uint64_t u = 0, uint64_t d = 0) : statusCode(s) , errorCode(c) , headers(h) , payload(p) , errorMsg(e) , uploadSize(u) , downloadSize(d) { ; } }; using HttpResponsePtr = std::shared_ptr; using HttpParameters = std::map; using Logger = std::function; using OnResponseCallback = std::function; struct HttpRequestArgs { std::string url; std::string verb; WebSocketHttpHeaders extraHeaders; std::string body; int connectTimeout; int transferTimeout; bool followRedirects; int maxRedirects; bool verbose; bool compress; Logger logger; OnProgressCallback onProgressCallback; }; using HttpRequestArgsPtr = std::shared_ptr; class HttpClient { public: HttpClient(bool async = false); ~HttpClient(); HttpResponsePtr get(const std::string& url, HttpRequestArgsPtr args); HttpResponsePtr head(const std::string& url, HttpRequestArgsPtr args); HttpResponsePtr del(const std::string& url, HttpRequestArgsPtr args); HttpResponsePtr post(const std::string& url, const HttpParameters& httpParameters, HttpRequestArgsPtr args); HttpResponsePtr post(const std::string& url, const std::string& body, HttpRequestArgsPtr args); HttpResponsePtr put(const std::string& url, const HttpParameters& httpParameters, HttpRequestArgsPtr args); HttpResponsePtr put(const std::string& url, const std::string& body, HttpRequestArgsPtr args); HttpResponsePtr request(const std::string& url, const std::string& verb, const std::string& body, HttpRequestArgsPtr args, int redirects = 0); // Async API HttpRequestArgsPtr createRequest(const std::string& url = std::string(), const std::string& verb = HttpClient::kGet); bool performRequest(HttpRequestArgsPtr request, const OnResponseCallback& onResponseCallback); std::string serializeHttpParameters(const HttpParameters& httpParameters); std::string urlEncode(const std::string& value); const static std::string kPost; const static std::string kGet; const static std::string kHead; const static std::string kDel; const static std::string kPut; private: void log(const std::string& msg, HttpRequestArgsPtr args); bool gzipInflate(const std::string& in, std::string& out); // Async API background thread runner void run(); // Async API bool _async; std::queue> _queue; mutable std::mutex _queueMutex; std::condition_variable _condition; std::atomic _stop; std::thread _thread; std::shared_ptr _socket; std::mutex _mutex; // to protect accessing the _socket (only one socket per client) }; } // namespace ix