1/*
2 * IXHttpClient.h
3 * Author: Benjamin Sergeant
4 * Copyright (c) 2019 Machine Zone, Inc. All rights reserved.
5 */
6
7#pragma once
8
9#include "IXHttp.h"
10#include "IXSocket.h"
11#include "IXSocketTLSOptions.h"
12#include "IXWebSocketHttpHeaders.h"
13#include <algorithm>
14#include <atomic>
15#include <condition_variable>
16#include <functional>
17#include <map>
18#include <memory>
19#include <mutex>
20#include <queue>
21#include <thread>
22
23namespace ix
24{
25 class HttpClient
26 {
27 public:
28 HttpClient(bool async = false);
29 ~HttpClient();
30
31 HttpResponsePtr get(const std::string& url, HttpRequestArgsPtr args);
32 HttpResponsePtr head(const std::string& url, HttpRequestArgsPtr args);
33 HttpResponsePtr Delete(const std::string& url, HttpRequestArgsPtr args);
34
35 HttpResponsePtr post(const std::string& url,
36 const HttpParameters& httpParameters,
37 const HttpFormDataParameters& httpFormDataParameters,
38 HttpRequestArgsPtr args);
39 HttpResponsePtr post(const std::string& url,
40 const std::string& body,
41 HttpRequestArgsPtr args);
42
43 HttpResponsePtr put(const std::string& url,
44 const HttpParameters& httpParameters,
45 const HttpFormDataParameters& httpFormDataParameters,
46 HttpRequestArgsPtr args);
47 HttpResponsePtr put(const std::string& url,
48 const std::string& body,
49 HttpRequestArgsPtr args);
50
51 HttpResponsePtr patch(const std::string& url,
52 const HttpParameters& httpParameters,
53 const HttpFormDataParameters& httpFormDataParameters,
54 HttpRequestArgsPtr args);
55 HttpResponsePtr patch(const std::string& url,
56 const std::string& body,
57 HttpRequestArgsPtr args);
58
59 HttpResponsePtr request(const std::string& url,
60 const std::string& verb,
61 const std::string& body,
62 HttpRequestArgsPtr args,
63 int redirects = 0);
64
65 HttpResponsePtr request(const std::string& url,
66 const std::string& verb,
67 const HttpParameters& httpParameters,
68 const HttpFormDataParameters& httpFormDataParameters,
69 HttpRequestArgsPtr args);
70
71 void setForceBody(bool value);
72
73 // Async API
74 HttpRequestArgsPtr createRequest(const std::string& url = std::string(),
75 const std::string& verb = HttpClient::kGet);
76
77 bool performRequest(HttpRequestArgsPtr request,
78 const OnResponseCallback& onResponseCallback);
79
80 // TLS
81 void setTLSOptions(const SocketTLSOptions& tlsOptions);
82
83 std::string serializeHttpParameters(const HttpParameters& httpParameters);
84
85 std::string serializeHttpFormDataParameters(
86 const std::string& multipartBoundary,
87 const HttpFormDataParameters& httpFormDataParameters,
88 const HttpParameters& httpParameters = HttpParameters());
89
90 std::string generateMultipartBoundary();
91
92 std::string urlEncode(const std::string& value);
93
94 const static std::string kPost;
95 const static std::string kGet;
96 const static std::string kHead;
97 const static std::string kDelete;
98 const static std::string kPut;
99 const static std::string kPatch;
100
101 private:
102 void log(const std::string& msg, HttpRequestArgsPtr args);
103
104 // Async API background thread runner
105 void run();
106 // Async API
107 bool _async;
108 std::queue<std::pair<HttpRequestArgsPtr, OnResponseCallback>> _queue;
109 mutable std::mutex _queueMutex;
110 std::condition_variable _condition;
111 std::atomic<bool> _stop;
112 std::thread _thread;
113
114 std::unique_ptr<Socket> _socket;
115 std::recursive_mutex _mutex; // to protect accessing the _socket (only one socket per
116 // client) the mutex needs to be recursive as this function
117 // might be called recursively to follow HTTP redirections
118
119 SocketTLSOptions _tlsOptions;
120
121 bool _forceBody;
122 };
123} // namespace ix
124