1#ifndef CPR_SESSION_H
2#define CPR_SESSION_H
3
4#include <cstdint>
5#include <fstream>
6#include <functional>
7#include <future>
8#include <memory>
9#include <queue>
10
11#include "cpr/accept_encoding.h"
12#include "cpr/async_wrapper.h"
13#include "cpr/auth.h"
14#include "cpr/bearer.h"
15#include "cpr/body.h"
16#include "cpr/callback.h"
17#include "cpr/connect_timeout.h"
18#include "cpr/cookies.h"
19#include "cpr/cprtypes.h"
20#include "cpr/curlholder.h"
21#include "cpr/http_version.h"
22#include "cpr/interface.h"
23#include "cpr/limit_rate.h"
24#include "cpr/local_port.h"
25#include "cpr/local_port_range.h"
26#include "cpr/low_speed.h"
27#include "cpr/multipart.h"
28#include "cpr/parameters.h"
29#include "cpr/payload.h"
30#include "cpr/proxies.h"
31#include "cpr/proxyauth.h"
32#include "cpr/range.h"
33#include "cpr/redirect.h"
34#include "cpr/reserve_size.h"
35#include "cpr/resolve.h"
36#include "cpr/response.h"
37#include "cpr/ssl_options.h"
38#include "cpr/timeout.h"
39#include "cpr/unix_socket.h"
40#include "cpr/user_agent.h"
41#include "cpr/util.h"
42#include "cpr/verbose.h"
43
44namespace cpr {
45
46using AsyncResponse = AsyncWrapper<Response>;
47
48class Interceptor;
49class MultiPerform;
50
51class Session : public std::enable_shared_from_this<Session> {
52 public:
53 Session();
54 Session(const Session& other) = delete;
55 Session(Session&& old) = default;
56
57 ~Session() = default;
58
59 Session& operator=(Session&& old) noexcept = default;
60 Session& operator=(const Session& other) = delete;
61
62 void SetUrl(const Url& url);
63 void SetParameters(const Parameters& parameters);
64 void SetParameters(Parameters&& parameters);
65 void SetHeader(const Header& header);
66 void UpdateHeader(const Header& header);
67 void SetTimeout(const Timeout& timeout);
68 void SetConnectTimeout(const ConnectTimeout& timeout);
69 void SetAuth(const Authentication& auth);
70// Only supported with libcurl >= 7.61.0.
71// As an alternative use SetHeader and add the token manually.
72#if LIBCURL_VERSION_NUM >= 0x073D00
73 void SetBearer(const Bearer& token);
74#endif
75 void SetUserAgent(const UserAgent& ua);
76 void SetPayload(Payload&& payload);
77 void SetPayload(const Payload& payload);
78 void SetProxies(Proxies&& proxies);
79 void SetProxies(const Proxies& proxies);
80 void SetProxyAuth(ProxyAuthentication&& proxy_auth);
81 void SetProxyAuth(const ProxyAuthentication& proxy_auth);
82 void SetMultipart(Multipart&& multipart);
83 void SetMultipart(const Multipart& multipart);
84 void SetRedirect(const Redirect& redirect);
85 void SetCookies(const Cookies& cookies);
86 void SetBody(Body&& body);
87 void SetBody(const Body& body);
88 void SetLowSpeed(const LowSpeed& low_speed);
89 void SetVerifySsl(const VerifySsl& verify);
90 void SetUnixSocket(const UnixSocket& unix_socket);
91 void SetSslOptions(const SslOptions& options);
92 void SetReadCallback(const ReadCallback& read);
93 void SetHeaderCallback(const HeaderCallback& header);
94 void SetWriteCallback(const WriteCallback& write);
95 void SetProgressCallback(const ProgressCallback& progress);
96 void SetDebugCallback(const DebugCallback& debug);
97 void SetVerbose(const Verbose& verbose);
98 void SetInterface(const Interface& iface);
99 void SetLocalPort(const LocalPort& local_port);
100 void SetLocalPortRange(const LocalPortRange& local_port_range);
101 void SetHttpVersion(const HttpVersion& version);
102 void SetRange(const Range& range);
103 void SetResolve(const Resolve& resolve);
104 void SetResolves(const std::vector<Resolve>& resolves);
105 void SetMultiRange(const MultiRange& multi_range);
106 void SetReserveSize(const ReserveSize& reserve_size);
107 void SetAcceptEncoding(const AcceptEncoding& accept_encoding);
108 void SetAcceptEncoding(AcceptEncoding&& accept_encoding);
109 void SetLimitRate(const LimitRate& limit_rate);
110
111 // For cancellable requests
112 void SetCancellationParam(std::shared_ptr<std::atomic_bool> param);
113
114 // Used in templated functions
115 void SetOption(const Url& url);
116 void SetOption(const Parameters& parameters);
117 void SetOption(Parameters&& parameters);
118 void SetOption(const Header& header);
119 void SetOption(const Timeout& timeout);
120 void SetOption(const ConnectTimeout& timeout);
121 void SetOption(const Authentication& auth);
122// Only supported with libcurl >= 7.61.0.
123// As an alternative use SetHeader and add the token manually.
124#if LIBCURL_VERSION_NUM >= 0x073D00
125 void SetOption(const Bearer& auth);
126#endif
127 void SetOption(const UserAgent& ua);
128 void SetOption(Payload&& payload);
129 void SetOption(const Payload& payload);
130 void SetOption(const LimitRate& limit_rate);
131 void SetOption(Proxies&& proxies);
132 void SetOption(const Proxies& proxies);
133 void SetOption(ProxyAuthentication&& proxy_auth);
134 void SetOption(const ProxyAuthentication& proxy_auth);
135 void SetOption(Multipart&& multipart);
136 void SetOption(const Multipart& multipart);
137 void SetOption(const Redirect& redirect);
138 void SetOption(const Cookies& cookies);
139 void SetOption(Body&& body);
140 void SetOption(const Body& body);
141 void SetOption(const ReadCallback& read);
142 void SetOption(const HeaderCallback& header);
143 void SetOption(const WriteCallback& write);
144 void SetOption(const ProgressCallback& progress);
145 void SetOption(const DebugCallback& debug);
146 void SetOption(const LowSpeed& low_speed);
147 void SetOption(const VerifySsl& verify);
148 void SetOption(const Verbose& verbose);
149 void SetOption(const UnixSocket& unix_socket);
150 void SetOption(const SslOptions& options);
151 void SetOption(const Interface& iface);
152 void SetOption(const LocalPort& local_port);
153 void SetOption(const LocalPortRange& local_port_range);
154 void SetOption(const HttpVersion& version);
155 void SetOption(const Range& range);
156 void SetOption(const MultiRange& multi_range);
157 void SetOption(const ReserveSize& reserve_size);
158 void SetOption(const AcceptEncoding& accept_encoding);
159 void SetOption(AcceptEncoding&& accept_encoding);
160 void SetOption(const Resolve& resolve);
161 void SetOption(const std::vector<Resolve>& resolves);
162
163 cpr_off_t GetDownloadFileLength();
164 /**
165 * Attempt to preallocate enough memory for specified number of characters in the response string.
166 * Pass 0 to disable this behavior and let the response string be allocated dynamically on demand.
167 *
168 * Example:
169 * cpr::Session session;
170 * session.SetUrl(cpr::Url{"http://xxx/file"});
171 * session.ResponseStringReserve(1024 * 512); // Reserve space for at least 1024 * 512 characters
172 * cpr::Response r = session.Get();
173 **/
174 void ResponseStringReserve(size_t size);
175 Response Delete();
176 Response Download(const WriteCallback& write);
177 Response Download(std::ofstream& file);
178 Response Get();
179 Response Head();
180 Response Options();
181 Response Patch();
182 Response Post();
183 Response Put();
184
185 AsyncResponse GetAsync();
186 AsyncResponse DeleteAsync();
187 AsyncResponse DownloadAsync(const WriteCallback& write);
188 AsyncResponse DownloadAsync(std::ofstream& file);
189 AsyncResponse HeadAsync();
190 AsyncResponse OptionsAsync();
191 AsyncResponse PatchAsync();
192 AsyncResponse PostAsync();
193 AsyncResponse PutAsync();
194
195 template <typename Then>
196 auto GetCallback(Then then);
197 template <typename Then>
198 auto PostCallback(Then then);
199 template <typename Then>
200 auto PutCallback(Then then);
201 template <typename Then>
202 auto HeadCallback(Then then);
203 template <typename Then>
204 auto DeleteCallback(Then then);
205 template <typename Then>
206 auto OptionsCallback(Then then);
207 template <typename Then>
208 auto PatchCallback(Then then);
209
210 std::shared_ptr<CurlHolder> GetCurlHolder();
211 std::string GetFullRequestUrl();
212
213 void PrepareDelete();
214 void PrepareGet();
215 void PrepareHead();
216 void PrepareOptions();
217 void PreparePatch();
218 void PreparePost();
219 void PreparePut();
220 void PrepareDownload(const WriteCallback& write);
221 void PrepareDownload(std::ofstream& file);
222 Response Complete(CURLcode curl_error);
223 Response CompleteDownload(CURLcode curl_error);
224
225 void AddInterceptor(const std::shared_ptr<Interceptor>& pinterceptor);
226
227 private:
228 // Interceptors should be able to call the private proceed() function
229 friend Interceptor;
230 friend MultiPerform;
231
232
233 bool hasBodyOrPayload_{false};
234 bool chunkedTransferEncoding_{false};
235 std::shared_ptr<CurlHolder> curl_;
236 Url url_;
237 Parameters parameters_;
238 Proxies proxies_;
239 ProxyAuthentication proxyAuth_;
240 Header header_;
241 AcceptEncoding acceptEncoding_;
242 /**
243 * Will be set by the read callback.
244 * Ensures that the "Transfer-Encoding" is set to "chunked", if not overriden in header_.
245 **/
246 ReadCallback readcb_;
247 HeaderCallback headercb_;
248 WriteCallback writecb_;
249 ProgressCallback progresscb_;
250 DebugCallback debugcb_;
251 CancellationCallback cancellationcb_;
252
253 size_t response_string_reserve_size_{0};
254 std::string response_string_;
255 std::string header_string_;
256 std::queue<std::shared_ptr<Interceptor>> interceptors_;
257 bool isUsedInMultiPerform{false};
258 bool isCancellable{false};
259
260 Response makeDownloadRequest();
261 Response makeRequest();
262 Response proceed();
263 Response intercept();
264 void prepareCommon();
265 void prepareCommonDownload();
266 void SetHeaderInternal();
267 std::shared_ptr<Session> GetSharedPtrFromThis();
268 CURLcode DoEasyPerform();
269};
270
271template <typename Then>
272auto Session::GetCallback(Then then) {
273 return async([shared_this = GetSharedPtrFromThis()](Then then_inner) { return then_inner(shared_this->Get()); }, std::move(then));
274}
275
276template <typename Then>
277auto Session::PostCallback(Then then) {
278 return async([shared_this = GetSharedPtrFromThis()](Then then_inner) { return then_inner(shared_this->Post()); }, std::move(then));
279}
280
281template <typename Then>
282auto Session::PutCallback(Then then) {
283 return async([shared_this = GetSharedPtrFromThis()](Then then_inner) { return then_inner(shared_this->Put()); }, std::move(then));
284}
285
286template <typename Then>
287auto Session::HeadCallback(Then then) {
288 return async([shared_this = GetSharedPtrFromThis()](Then then_inner) { return then_inner(shared_this->Head()); }, std::move(then));
289}
290
291template <typename Then>
292auto Session::DeleteCallback(Then then) {
293 return async([shared_this = GetSharedPtrFromThis()](Then then_inner) { return then_inner(shared_this->Delete()); }, std::move(then));
294}
295
296template <typename Then>
297auto Session::OptionsCallback(Then then) {
298 return async([shared_this = GetSharedPtrFromThis()](Then then_inner) { return then_inner(shared_this->Options()); }, std::move(then));
299}
300
301template <typename Then>
302auto Session::PatchCallback(Then then) {
303 return async([shared_this = GetSharedPtrFromThis()](Then then_inner) { return then_inner(shared_this->Patch()); }, std::move(then));
304}
305
306} // namespace cpr
307
308#endif
309