2021-03-27 00:18:51 +02:00
# include "cpr/session.h"
# include <algorithm>
# include <cstdlib>
2023-08-05 21:31:33 +03:00
# include <cstring>
2021-03-27 00:18:51 +02:00
# include <fstream>
# include <functional>
2023-08-05 21:31:33 +03:00
# include <iostream>
# include <stdexcept>
2021-03-27 00:18:51 +02:00
# include <string>
# include <curl/curl.h>
2023-08-05 21:31:33 +03:00
# include "cpr/async.h"
2021-03-27 00:18:51 +02:00
# include "cpr/cprtypes.h"
2023-08-05 21:31:33 +03:00
# include "cpr/interceptor.h"
2021-03-27 00:18:51 +02:00
# include "cpr/util.h"
2023-08-05 21:31:33 +03:00
# if SUPPORT_CURLOPT_SSL_CTX_FUNCTION
# include "cpr/ssl_ctx.h"
# endif
2021-03-27 00:18:51 +02:00
2023-08-05 21:31:33 +03:00
namespace cpr {
2021-03-27 00:18:51 +02:00
// Ignored here since libcurl reqires a long:
// NOLINTNEXTLINE(google-runtime-int)
constexpr long ON = 1L ;
// Ignored here since libcurl reqires a long:
// NOLINTNEXTLINE(google-runtime-int)
constexpr long OFF = 0L ;
2023-08-05 21:31:33 +03:00
CURLcode Session : : DoEasyPerform ( ) {
if ( isUsedInMultiPerform ) {
std : : cerr < < " curl_easy_perform cannot be executed if the CURL handle is used in a MultiPerform. " < < std : : endl ;
return CURLcode : : CURLE_FAILED_INIT ;
}
puts ( " about to do easy perform... " ) ;
auto r = curl_easy_perform ( curl_ - > handle ) ;
puts ( " done with easy perform... " ) ;
return r ;
}
void Session : : SetHeaderInternal ( ) {
curl_slist * chunk = nullptr ;
for ( const std : : pair < const std : : string , std : : string > & item : header_ ) {
std : : string header_string = item . first ;
if ( item . second . empty ( ) ) {
header_string + = " ; " ;
} else {
header_string + = " : " + item . second ;
}
curl_slist * temp = curl_slist_append ( chunk , header_string . c_str ( ) ) ;
if ( temp ) {
chunk = temp ;
}
}
// Set the chunked transfer encoding in case it does not already exist:
if ( chunkedTransferEncoding_ & & header_ . find ( " Transfer-Encoding " ) = = header_ . end ( ) ) {
curl_slist * temp = curl_slist_append ( chunk , " Transfer-Encoding:chunked " ) ;
if ( temp ) {
chunk = temp ;
}
}
// libcurl would prepare the header "Expect: 100-continue" by default when uploading files larger than 1 MB.
// Here we would like to disable this feature:
curl_slist * temp = curl_slist_append ( chunk , " Expect: " ) ;
if ( temp ) {
chunk = temp ;
}
curl_easy_setopt ( curl_ - > handle , CURLOPT_HTTPHEADER , chunk ) ;
curl_slist_free_all ( curl_ - > chunk ) ;
curl_ - > chunk = chunk ;
}
2021-03-27 00:18:51 +02:00
// Only supported with libcurl >= 7.61.0.
// As an alternative use SetHeader and add the token manually.
# if LIBCURL_VERSION_NUM >= 0x073D00
2023-08-05 21:31:33 +03:00
void Session : : SetBearer ( const Bearer & token ) {
// Ignore here since this has been defined by libcurl.
curl_easy_setopt ( curl_ - > handle , CURLOPT_HTTPAUTH , CURLAUTH_BEARER ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_XOAUTH2_BEARER , token . GetToken ( ) ) ;
}
2021-03-27 00:18:51 +02:00
# endif
2023-08-05 21:31:33 +03:00
Session : : Session ( ) : curl_ ( new CurlHolder ( ) ) {
2021-03-27 00:18:51 +02:00
// Set up some sensible defaults
curl_version_info_data * version_info = curl_version_info ( CURLVERSION_NOW ) ;
2023-08-05 21:31:33 +03:00
const std : : string version = " curl/ " + std : : string { version_info - > version } ;
2021-03-27 00:18:51 +02:00
curl_easy_setopt ( curl_ - > handle , CURLOPT_USERAGENT , version . c_str ( ) ) ;
2021-08-22 20:28:37 +03:00
SetRedirect ( Redirect ( ) ) ;
2021-03-27 00:18:51 +02:00
curl_easy_setopt ( curl_ - > handle , CURLOPT_NOPROGRESS , 1L ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_ERRORBUFFER , curl_ - > error . data ( ) ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_COOKIEFILE , " " ) ;
# ifdef CPR_CURL_NOSIGNAL
curl_easy_setopt ( curl_ - > handle , CURLOPT_NOSIGNAL , 1L ) ;
# endif
2023-08-05 21:31:33 +03:00
# if LIBCURL_VERSION_NUM >= 0x071900 // 7.25.0
2021-03-27 00:18:51 +02:00
curl_easy_setopt ( curl_ - > handle , CURLOPT_TCP_KEEPALIVE , 1L ) ;
# endif
}
2023-08-05 21:31:33 +03:00
Response Session : : makeDownloadRequest ( ) {
if ( ! interceptors_ . empty ( ) ) {
return intercept ( ) ;
}
2021-03-27 00:18:51 +02:00
2023-08-05 21:31:33 +03:00
const CURLcode curl_error = DoEasyPerform ( ) ;
2021-03-27 00:18:51 +02:00
2023-08-05 21:31:33 +03:00
return CompleteDownload ( curl_error ) ;
2021-03-27 00:18:51 +02:00
}
2023-08-05 21:31:33 +03:00
void Session : : prepareCommon ( ) {
assert ( curl_ - > handle ) ;
2021-03-27 00:18:51 +02:00
2023-08-05 21:31:33 +03:00
// Set Header:
SetHeaderInternal ( ) ;
const std : : string parametersContent = parameters_ . GetContent ( * curl_ ) ;
if ( ! parametersContent . empty ( ) ) {
const Url new_url { url_ + " ? " + parametersContent } ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_URL , new_url . c_str ( ) ) ;
} else {
curl_easy_setopt ( curl_ - > handle , CURLOPT_URL , url_ . c_str ( ) ) ;
}
// Proxy:
const std : : string protocol = url_ . str ( ) . substr ( 0 , url_ . str ( ) . find ( ' : ' ) ) ;
if ( proxies_ . has ( protocol ) ) {
curl_easy_setopt ( curl_ - > handle , CURLOPT_PROXY , proxies_ [ protocol ] . c_str ( ) ) ;
if ( proxyAuth_ . has ( protocol ) ) {
curl_easy_setopt ( curl_ - > handle , CURLOPT_PROXYUSERNAME , proxyAuth_ . GetUsername ( protocol ) ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_PROXYPASSWORD , proxyAuth_ . GetPassword ( protocol ) ) ;
2021-03-27 00:18:51 +02:00
}
}
2023-08-05 21:31:33 +03:00
# if LIBCURL_VERSION_NUM >= 0x071506 // 7.21.6
if ( acceptEncoding_ . empty ( ) ) {
// Enable all supported built-in compressions
curl_easy_setopt ( curl_ - > handle , CURLOPT_ACCEPT_ENCODING , " " ) ;
} else if ( acceptEncoding_ . disabled ( ) ) {
// Disable curl adding the 'Accept-Encoding' header
curl_easy_setopt ( curl_ - > handle , CURLOPT_ACCEPT_ENCODING , nullptr ) ;
} else {
curl_easy_setopt ( curl_ - > handle , CURLOPT_ACCEPT_ENCODING , acceptEncoding_ . getString ( ) . c_str ( ) ) ;
}
# endif
# if LIBCURL_VERSION_NUM >= 0x071900 // 7.25.0
# if SUPPORT_SSL_NO_REVOKE
// NOLINTNEXTLINE (google-runtime-int)
long bitmask { 0 } ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_SSL_OPTIONS , & bitmask ) ;
const bool noRevoke = bitmask & CURLSSLOPT_NO_REVOKE ;
# endif
// Fix loading certs from Windows cert store when using OpenSSL:
curl_easy_setopt ( curl_ - > handle , CURLOPT_SSL_OPTIONS , CURLSSLOPT_NATIVE_CA ) ;
// Ensure SSL no revoke is still set
# if SUPPORT_SSL_NO_REVOKE
if ( noRevoke ) {
curl_easy_setopt ( curl_ - > handle , CURLOPT_SSL_OPTIONS , CURLSSLOPT_NO_REVOKE ) ;
}
# endif
# endif
curl_ - > error [ 0 ] = ' \0 ' ;
response_string_ . clear ( ) ;
if ( response_string_reserve_size_ > 0 ) {
response_string_ . reserve ( response_string_reserve_size_ ) ;
}
header_string_ . clear ( ) ;
if ( ! this - > writecb_ . callback ) {
curl_easy_setopt ( curl_ - > handle , CURLOPT_WRITEFUNCTION , cpr : : util : : writeFunction ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_WRITEDATA , & response_string_ ) ;
}
if ( ! this - > headercb_ . callback ) {
curl_easy_setopt ( curl_ - > handle , CURLOPT_HEADERFUNCTION , cpr : : util : : writeFunction ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_HEADERDATA , & header_string_ ) ;
}
// Enable so we are able to retrive certificate information:
curl_easy_setopt ( curl_ - > handle , CURLOPT_CERTINFO , 1L ) ;
}
void Session : : prepareCommonDownload ( ) {
assert ( curl_ - > handle ) ;
// Set Header:
SetHeaderInternal ( ) ;
const std : : string parametersContent = parameters_ . GetContent ( * curl_ ) ;
if ( ! parametersContent . empty ( ) ) {
const Url new_url { url_ + " ? " + parametersContent } ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_URL , new_url . c_str ( ) ) ;
} else {
curl_easy_setopt ( curl_ - > handle , CURLOPT_URL , url_ . c_str ( ) ) ;
}
const std : : string protocol = url_ . str ( ) . substr ( 0 , url_ . str ( ) . find ( ' : ' ) ) ;
if ( proxies_ . has ( protocol ) ) {
curl_easy_setopt ( curl_ - > handle , CURLOPT_PROXY , proxies_ [ protocol ] . c_str ( ) ) ;
if ( proxyAuth_ . has ( protocol ) ) {
curl_easy_setopt ( curl_ - > handle , CURLOPT_PROXYUSERNAME , proxyAuth_ . GetUsername ( protocol ) ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_PROXYPASSWORD , proxyAuth_ . GetPassword ( protocol ) ) ;
2021-03-27 00:18:51 +02:00
}
}
2023-08-05 21:31:33 +03:00
curl_ - > error [ 0 ] = ' \0 ' ;
2021-03-27 00:18:51 +02:00
2023-08-05 21:31:33 +03:00
header_string_ . clear ( ) ;
if ( headercb_ . callback ) {
curl_easy_setopt ( curl_ - > handle , CURLOPT_HEADERFUNCTION , cpr : : util : : headerUserFunction ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_HEADERDATA , & headercb_ ) ;
} else {
curl_easy_setopt ( curl_ - > handle , CURLOPT_HEADERFUNCTION , cpr : : util : : writeFunction ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_HEADERDATA , & header_string_ ) ;
}
2021-03-27 00:18:51 +02:00
}
2023-08-05 21:31:33 +03:00
Response Session : : makeRequest ( ) {
if ( ! interceptors_ . empty ( ) ) {
return intercept ( ) ;
}
const CURLcode curl_error = DoEasyPerform ( ) ;
return Complete ( curl_error ) ;
2021-03-27 00:18:51 +02:00
}
2023-08-05 21:31:33 +03:00
void Session : : SetLimitRate ( const LimitRate & limit_rate ) {
curl_easy_setopt ( curl_ - > handle , CURLOPT_MAX_RECV_SPEED_LARGE , limit_rate . downrate ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_MAX_SEND_SPEED_LARGE , limit_rate . uprate ) ;
}
void Session : : SetReadCallback ( const ReadCallback & read ) {
readcb_ = read ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_INFILESIZE_LARGE , read . size ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_POSTFIELDSIZE_LARGE , read . size ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_READFUNCTION , cpr : : util : : readUserFunction ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_READDATA , & readcb_ ) ;
chunkedTransferEncoding_ = read . size = = - 1 ;
}
void Session : : SetHeaderCallback ( const HeaderCallback & header ) {
curl_easy_setopt ( curl_ - > handle , CURLOPT_HEADERFUNCTION , cpr : : util : : headerUserFunction ) ;
headercb_ = header ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_HEADERDATA , & headercb_ ) ;
}
void Session : : SetWriteCallback ( const WriteCallback & write ) {
curl_easy_setopt ( curl_ - > handle , CURLOPT_WRITEFUNCTION , cpr : : util : : writeUserFunction ) ;
writecb_ = write ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_WRITEDATA , & writecb_ ) ;
}
void Session : : SetProgressCallback ( const ProgressCallback & progress ) {
progresscb_ = progress ;
if ( isCancellable ) {
cancellationcb_ . SetProgressCallback ( progresscb_ ) ;
return ;
2021-03-27 00:18:51 +02:00
}
2023-08-05 21:31:33 +03:00
# if LIBCURL_VERSION_NUM < 0x072000 // 7.32.0
curl_easy_setopt ( curl_ - > handle , CURLOPT_PROGRESSFUNCTION , cpr : : util : : progressUserFunction < ProgressCallback > ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_PROGRESSDATA , & progresscb_ ) ;
# else
curl_easy_setopt ( curl_ - > handle , CURLOPT_XFERINFOFUNCTION , cpr : : util : : progressUserFunction < ProgressCallback > ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_XFERINFODATA , & progresscb_ ) ;
# endif
curl_easy_setopt ( curl_ - > handle , CURLOPT_NOPROGRESS , 0L ) ;
2021-03-27 00:18:51 +02:00
}
2023-08-05 21:31:33 +03:00
void Session : : SetDebugCallback ( const DebugCallback & debug ) {
curl_easy_setopt ( curl_ - > handle , CURLOPT_DEBUGFUNCTION , cpr : : util : : debugUserFunction ) ;
debugcb_ = debug ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_DEBUGDATA , & debugcb_ ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_VERBOSE , 1L ) ;
2021-03-27 00:18:51 +02:00
}
2023-08-05 21:31:33 +03:00
void Session : : SetUrl ( const Url & url ) {
url_ = url ;
2021-03-27 00:18:51 +02:00
}
2023-08-05 21:31:33 +03:00
void Session : : SetResolve ( const Resolve & resolve ) {
SetResolves ( { resolve } ) ;
2021-03-27 00:18:51 +02:00
}
2023-08-05 21:31:33 +03:00
void Session : : SetResolves ( const std : : vector < Resolve > & resolves ) {
curl_slist_free_all ( curl_ - > resolveCurlList ) ;
curl_ - > resolveCurlList = nullptr ;
for ( const Resolve & resolve : resolves ) {
for ( const uint16_t port : resolve . ports ) {
curl_ - > resolveCurlList = curl_slist_append ( curl_ - > resolveCurlList , ( resolve . host + " : " + std : : to_string ( port ) + " : " + resolve . addr ) . c_str ( ) ) ;
}
}
curl_easy_setopt ( curl_ - > handle , CURLOPT_RESOLVE , curl_ - > resolveCurlList ) ;
2021-03-27 00:18:51 +02:00
}
2023-08-05 21:31:33 +03:00
void Session : : SetParameters ( const Parameters & parameters ) {
parameters_ = parameters ;
}
void Session : : SetParameters ( Parameters & & parameters ) {
parameters_ = std : : move ( parameters ) ;
}
void Session : : SetHeader ( const Header & header ) {
header_ = header ;
}
void Session : : UpdateHeader ( const Header & header ) {
for ( const std : : pair < const std : : string , std : : string > & item : header ) {
header_ [ item . first ] = item . second ;
2021-08-22 20:28:37 +03:00
}
}
2023-08-05 21:31:33 +03:00
void Session : : SetTimeout ( const Timeout & timeout ) {
curl_easy_setopt ( curl_ - > handle , CURLOPT_TIMEOUT_MS , timeout . Milliseconds ( ) ) ;
2021-03-27 00:18:51 +02:00
}
2023-08-05 21:31:33 +03:00
void Session : : SetConnectTimeout ( const ConnectTimeout & timeout ) {
curl_easy_setopt ( curl_ - > handle , CURLOPT_CONNECTTIMEOUT_MS , timeout . Milliseconds ( ) ) ;
}
void Session : : SetAuth ( const Authentication & auth ) {
2021-03-27 00:18:51 +02:00
// Ignore here since this has been defined by libcurl.
2023-08-05 21:31:33 +03:00
switch ( auth . GetAuthMode ( ) ) {
case AuthMode : : BASIC :
curl_easy_setopt ( curl_ - > handle , CURLOPT_HTTPAUTH , CURLAUTH_BASIC ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_USERPWD , auth . GetAuthString ( ) ) ;
break ;
case AuthMode : : DIGEST :
curl_easy_setopt ( curl_ - > handle , CURLOPT_HTTPAUTH , CURLAUTH_DIGEST ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_USERPWD , auth . GetAuthString ( ) ) ;
break ;
case AuthMode : : NTLM :
curl_easy_setopt ( curl_ - > handle , CURLOPT_HTTPAUTH , CURLAUTH_NTLM ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_USERPWD , auth . GetAuthString ( ) ) ;
break ;
}
2021-03-27 00:18:51 +02:00
}
2023-08-05 21:31:33 +03:00
void Session : : SetUserAgent ( const UserAgent & ua ) {
2021-03-27 00:18:51 +02:00
curl_easy_setopt ( curl_ - > handle , CURLOPT_USERAGENT , ua . c_str ( ) ) ;
}
2023-08-05 21:31:33 +03:00
void Session : : SetPayload ( const Payload & payload ) {
2021-03-27 00:18:51 +02:00
hasBodyOrPayload_ = true ;
const std : : string content = payload . GetContent ( * curl_ ) ;
2021-08-22 20:28:37 +03:00
curl_easy_setopt ( curl_ - > handle , CURLOPT_POSTFIELDSIZE_LARGE , static_cast < curl_off_t > ( content . length ( ) ) ) ;
2021-03-27 00:18:51 +02:00
curl_easy_setopt ( curl_ - > handle , CURLOPT_COPYPOSTFIELDS , content . c_str ( ) ) ;
}
2023-08-05 21:31:33 +03:00
void Session : : SetPayload ( Payload & & payload ) {
2021-03-27 00:18:51 +02:00
hasBodyOrPayload_ = true ;
const std : : string content = payload . GetContent ( * curl_ ) ;
2021-08-22 20:28:37 +03:00
curl_easy_setopt ( curl_ - > handle , CURLOPT_POSTFIELDSIZE_LARGE , static_cast < curl_off_t > ( content . length ( ) ) ) ;
2021-03-27 00:18:51 +02:00
curl_easy_setopt ( curl_ - > handle , CURLOPT_COPYPOSTFIELDS , content . c_str ( ) ) ;
}
2023-08-05 21:31:33 +03:00
void Session : : SetProxies ( const Proxies & proxies ) {
2021-03-27 00:18:51 +02:00
proxies_ = proxies ;
}
2023-08-05 21:31:33 +03:00
void Session : : SetProxies ( Proxies & & proxies ) {
2021-03-27 00:18:51 +02:00
proxies_ = std : : move ( proxies ) ;
}
2023-08-05 21:31:33 +03:00
void Session : : SetProxyAuth ( ProxyAuthentication & & proxy_auth ) {
2021-07-02 17:44:48 +03:00
proxyAuth_ = std : : move ( proxy_auth ) ;
}
2023-08-05 21:31:33 +03:00
void Session : : SetProxyAuth ( const ProxyAuthentication & proxy_auth ) {
2021-07-02 17:44:48 +03:00
proxyAuth_ = proxy_auth ;
}
2023-08-05 21:31:33 +03:00
void Session : : SetMultipart ( const Multipart & multipart ) {
// Make sure, we have a empty multipart to start with:
if ( curl_ - > multipart ) {
curl_mime_free ( curl_ - > multipart ) ;
2021-03-27 00:18:51 +02:00
}
2023-08-05 21:31:33 +03:00
curl_ - > multipart = curl_mime_init ( curl_ - > handle ) ;
2021-03-27 00:18:51 +02:00
2023-08-05 21:31:33 +03:00
// Add all multipart pieces:
2021-03-27 00:18:51 +02:00
for ( const Part & part : multipart . parts ) {
2023-08-05 21:31:33 +03:00
if ( part . is_file ) {
for ( const File & file : part . files ) {
curl_mimepart * mimePart = curl_mime_addpart ( curl_ - > multipart ) ;
if ( ! part . content_type . empty ( ) ) {
curl_mime_type ( mimePart , part . content_type . c_str ( ) ) ;
}
curl_mime_filedata ( mimePart , file . filepath . c_str ( ) ) ;
curl_mime_name ( mimePart , part . name . c_str ( ) ) ;
if ( file . hasOverridenFilename ( ) ) {
curl_mime_filename ( mimePart , file . overriden_filename . c_str ( ) ) ;
}
}
2021-03-27 00:18:51 +02:00
} else {
2023-08-05 21:31:33 +03:00
curl_mimepart * mimePart = curl_mime_addpart ( curl_ - > multipart ) ;
if ( ! part . content_type . empty ( ) ) {
curl_mime_type ( mimePart , part . content_type . c_str ( ) ) ;
}
if ( part . is_buffer ) {
// Do not use formdata, to prevent having to use reinterpreter_cast:
curl_mime_name ( mimePart , part . name . c_str ( ) ) ;
curl_mime_data ( mimePart , part . data , part . datalen ) ;
curl_mime_filename ( mimePart , part . value . c_str ( ) ) ;
2021-03-27 00:18:51 +02:00
} else {
2023-08-05 21:31:33 +03:00
curl_mime_name ( mimePart , part . name . c_str ( ) ) ;
curl_mime_data ( mimePart , part . value . c_str ( ) , CURL_ZERO_TERMINATED ) ;
2021-03-27 00:18:51 +02:00
}
}
}
2023-08-05 21:31:33 +03:00
curl_easy_setopt ( curl_ - > handle , CURLOPT_MIMEPOST , curl_ - > multipart ) ;
hasBodyOrPayload_ = true ;
2021-03-27 00:18:51 +02:00
}
2023-08-05 21:31:33 +03:00
void Session : : SetMultipart ( Multipart & & multipart ) {
SetMultipart ( multipart ) ;
2021-03-27 00:18:51 +02:00
}
2023-08-05 21:31:33 +03:00
void Session : : SetRedirect ( const Redirect & redirect ) {
2021-08-22 20:28:37 +03:00
curl_easy_setopt ( curl_ - > handle , CURLOPT_FOLLOWLOCATION , redirect . follow ? 1L : 0L ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_MAXREDIRS , redirect . maximum ) ;
2023-08-05 21:31:33 +03:00
curl_easy_setopt ( curl_ - > handle , CURLOPT_UNRESTRICTED_AUTH , redirect . cont_send_cred ? 1L : 0L ) ;
2021-03-27 00:18:51 +02:00
2021-08-22 20:28:37 +03:00
// NOLINTNEXTLINE (google-runtime-int)
long mask = 0 ;
if ( any ( redirect . post_flags & PostRedirectFlags : : POST_301 ) ) {
mask | = CURL_REDIR_POST_301 ;
}
if ( any ( redirect . post_flags & PostRedirectFlags : : POST_302 ) ) {
mask | = CURL_REDIR_POST_302 ;
}
if ( any ( redirect . post_flags & PostRedirectFlags : : POST_303 ) ) {
mask | = CURL_REDIR_POST_303 ;
}
curl_easy_setopt ( curl_ - > handle , CURLOPT_POSTREDIR , mask ) ;
2021-03-27 00:18:51 +02:00
}
2023-08-05 21:31:33 +03:00
void Session : : SetCookies ( const Cookies & cookies ) {
2021-03-27 00:18:51 +02:00
curl_easy_setopt ( curl_ - > handle , CURLOPT_COOKIELIST , " ALL " ) ;
2023-08-05 21:31:33 +03:00
curl_easy_setopt ( curl_ - > handle , CURLOPT_COOKIE , cookies . GetEncoded ( * curl_ ) . c_str ( ) ) ;
2021-03-27 00:18:51 +02:00
}
2023-08-05 21:31:33 +03:00
void Session : : SetBody ( const Body & body ) {
hasBodyOrPayload_ = true ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_POSTFIELDSIZE_LARGE , static_cast < curl_off_t > ( body . str ( ) . length ( ) ) ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_POSTFIELDS , body . c_str ( ) ) ;
2021-03-27 00:18:51 +02:00
}
2023-08-05 21:31:33 +03:00
void Session : : SetBody ( Body & & body ) {
hasBodyOrPayload_ = true ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_POSTFIELDSIZE_LARGE , static_cast < curl_off_t > ( body . str ( ) . length ( ) ) ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_COPYPOSTFIELDS , body . c_str ( ) ) ;
}
void Session : : SetLowSpeed ( const LowSpeed & low_speed ) {
2021-03-27 00:18:51 +02:00
curl_easy_setopt ( curl_ - > handle , CURLOPT_LOW_SPEED_LIMIT , low_speed . limit ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_LOW_SPEED_TIME , low_speed . time ) ;
}
2023-08-05 21:31:33 +03:00
void Session : : SetVerifySsl ( const VerifySsl & verify ) {
2021-03-27 00:18:51 +02:00
curl_easy_setopt ( curl_ - > handle , CURLOPT_SSL_VERIFYPEER , verify ? ON : OFF ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_SSL_VERIFYHOST , verify ? 2L : 0L ) ;
}
2023-08-05 21:31:33 +03:00
void Session : : SetUnixSocket ( const UnixSocket & unix_socket ) {
2021-03-27 00:18:51 +02:00
curl_easy_setopt ( curl_ - > handle , CURLOPT_UNIX_SOCKET_PATH , unix_socket . GetUnixSocketString ( ) ) ;
}
2023-08-05 21:31:33 +03:00
void Session : : SetSslOptions ( const SslOptions & options ) {
2021-03-27 00:18:51 +02:00
if ( ! options . cert_file . empty ( ) ) {
curl_easy_setopt ( curl_ - > handle , CURLOPT_SSLCERT , options . cert_file . c_str ( ) ) ;
if ( ! options . cert_type . empty ( ) ) {
curl_easy_setopt ( curl_ - > handle , CURLOPT_SSLCERTTYPE , options . cert_type . c_str ( ) ) ;
}
}
if ( ! options . key_file . empty ( ) ) {
curl_easy_setopt ( curl_ - > handle , CURLOPT_SSLKEY , options . key_file . c_str ( ) ) ;
if ( ! options . key_type . empty ( ) ) {
curl_easy_setopt ( curl_ - > handle , CURLOPT_SSLKEYTYPE , options . key_type . c_str ( ) ) ;
}
if ( ! options . key_pass . empty ( ) ) {
curl_easy_setopt ( curl_ - > handle , CURLOPT_KEYPASSWD , options . key_pass . c_str ( ) ) ;
}
2023-08-05 21:31:33 +03:00
# if SUPPORT_CURLOPT_SSLKEY_BLOB
} else if ( ! options . key_blob . empty ( ) ) {
std : : string key_blob ( options . key_blob ) ;
curl_blob blob { } ;
// NOLINTNEXTLINE (readability-container-data-pointer)
blob . data = & key_blob [ 0 ] ;
blob . len = key_blob . length ( ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_SSLKEY_BLOB , & blob ) ;
if ( ! options . key_type . empty ( ) ) {
curl_easy_setopt ( curl_ - > handle , CURLOPT_SSLKEYTYPE , options . key_type . c_str ( ) ) ;
}
if ( ! options . key_pass . empty ( ) ) {
curl_easy_setopt ( curl_ - > handle , CURLOPT_KEYPASSWD , options . key_pass . c_str ( ) ) ;
}
# endif
2021-03-27 00:18:51 +02:00
}
2021-07-02 17:44:48 +03:00
if ( ! options . pinned_public_key . empty ( ) ) {
curl_easy_setopt ( curl_ - > handle , CURLOPT_PINNEDPUBLICKEY , options . pinned_public_key . c_str ( ) ) ;
}
2021-03-27 00:18:51 +02:00
# if SUPPORT_ALPN
curl_easy_setopt ( curl_ - > handle , CURLOPT_SSL_ENABLE_ALPN , options . enable_alpn ? ON : OFF ) ;
# endif
# if SUPPORT_NPN
curl_easy_setopt ( curl_ - > handle , CURLOPT_SSL_ENABLE_NPN , options . enable_npn ? ON : OFF ) ;
# endif
curl_easy_setopt ( curl_ - > handle , CURLOPT_SSL_VERIFYPEER , options . verify_peer ? ON : OFF ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_SSL_VERIFYHOST , options . verify_host ? 2L : 0L ) ;
2023-08-05 21:31:33 +03:00
# if LIBCURL_VERSION_NUM >= 0x072900 // 7.41.0
2021-03-27 00:18:51 +02:00
curl_easy_setopt ( curl_ - > handle , CURLOPT_SSL_VERIFYSTATUS , options . verify_status ? ON : OFF ) ;
# endif
2021-08-22 20:28:37 +03:00
int maxTlsVersion = options . ssl_version ;
2021-03-27 00:18:51 +02:00
# if SUPPORT_MAX_TLS_VERSION
2021-08-22 20:28:37 +03:00
maxTlsVersion | = options . max_version ;
2021-03-27 00:18:51 +02:00
# endif
2021-08-22 20:28:37 +03:00
curl_easy_setopt ( curl_ - > handle , CURLOPT_SSLVERSION ,
// Ignore here since this has been defined by libcurl.
maxTlsVersion ) ;
2021-03-27 00:18:51 +02:00
# if SUPPORT_SSL_NO_REVOKE
if ( options . ssl_no_revoke ) {
curl_easy_setopt ( curl_ - > handle , CURLOPT_SSL_OPTIONS , CURLSSLOPT_NO_REVOKE ) ;
}
# endif
if ( ! options . ca_info . empty ( ) ) {
curl_easy_setopt ( curl_ - > handle , CURLOPT_CAINFO , options . ca_info . c_str ( ) ) ;
}
if ( ! options . ca_path . empty ( ) ) {
curl_easy_setopt ( curl_ - > handle , CURLOPT_CAPATH , options . ca_path . c_str ( ) ) ;
}
2023-08-05 21:31:33 +03:00
# if SUPPORT_CURLOPT_SSL_CTX_FUNCTION
# ifdef OPENSSL_BACKEND_USED
if ( ! options . ca_buffer . empty ( ) ) {
curl_easy_setopt ( curl_ - > handle , CURLOPT_SSL_CTX_FUNCTION , sslctx_function_load_ca_cert_from_buffer ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_SSL_CTX_DATA , options . ca_buffer . c_str ( ) ) ;
}
# endif
# endif
2021-03-27 00:18:51 +02:00
if ( ! options . crl_file . empty ( ) ) {
curl_easy_setopt ( curl_ - > handle , CURLOPT_CRLFILE , options . crl_file . c_str ( ) ) ;
}
if ( ! options . ciphers . empty ( ) ) {
curl_easy_setopt ( curl_ - > handle , CURLOPT_SSL_CIPHER_LIST , options . ciphers . c_str ( ) ) ;
}
# if SUPPORT_TLSv13_CIPHERS
if ( ! options . tls13_ciphers . empty ( ) ) {
curl_easy_setopt ( curl_ - > handle , CURLOPT_TLS13_CIPHERS , options . ciphers . c_str ( ) ) ;
}
# endif
# if SUPPORT_SESSIONID_CACHE
2021-08-22 20:28:37 +03:00
curl_easy_setopt ( curl_ - > handle , CURLOPT_SSL_SESSIONID_CACHE , options . session_id_cache ? ON : OFF ) ;
2021-03-27 00:18:51 +02:00
# endif
}
2023-08-05 21:31:33 +03:00
void Session : : SetVerbose ( const Verbose & verbose ) {
curl_easy_setopt ( curl_ - > handle , CURLOPT_VERBOSE , verbose . verbose ? ON : OFF ) ;
}
void Session : : SetInterface ( const Interface & iface ) {
if ( iface . str ( ) . empty ( ) ) {
curl_easy_setopt ( curl_ - > handle , CURLOPT_INTERFACE , nullptr ) ;
} else {
curl_easy_setopt ( curl_ - > handle , CURLOPT_INTERFACE , iface . c_str ( ) ) ;
}
}
void Session : : SetLocalPort ( const LocalPort & local_port ) {
curl_easy_setopt ( curl_ - > handle , CURLOPT_LOCALPORT , static_cast < long > ( static_cast < uint16_t > ( local_port ) ) ) ;
}
void Session : : SetLocalPortRange ( const LocalPortRange & local_port_range ) {
curl_easy_setopt ( curl_ - > handle , CURLOPT_LOCALPORTRANGE , static_cast < long > ( static_cast < uint16_t > ( local_port_range ) ) ) ;
}
void Session : : SetHttpVersion ( const HttpVersion & version ) {
switch ( version . code ) {
case HttpVersionCode : : VERSION_NONE :
curl_easy_setopt ( curl_ - > handle , CURLOPT_HTTP_VERSION , CURL_HTTP_VERSION_NONE ) ;
break ;
case HttpVersionCode : : VERSION_1_0 :
curl_easy_setopt ( curl_ - > handle , CURLOPT_HTTP_VERSION , CURL_HTTP_VERSION_1_0 ) ;
break ;
case HttpVersionCode : : VERSION_1_1 :
curl_easy_setopt ( curl_ - > handle , CURLOPT_HTTP_VERSION , CURL_HTTP_VERSION_1_1 ) ;
break ;
# if LIBCURL_VERSION_NUM >= 0x072100 // 7.33.0
case HttpVersionCode : : VERSION_2_0 :
curl_easy_setopt ( curl_ - > handle , CURLOPT_HTTP_VERSION , CURL_HTTP_VERSION_2_0 ) ;
break ;
# endif
# if LIBCURL_VERSION_NUM >= 0x072F00 // 7.47.0
case HttpVersionCode : : VERSION_2_0_TLS :
curl_easy_setopt ( curl_ - > handle , CURLOPT_HTTP_VERSION , CURL_HTTP_VERSION_2TLS ) ;
break ;
# endif
# if LIBCURL_VERSION_NUM >= 0x073100 // 7.49.0
case HttpVersionCode : : VERSION_2_0_PRIOR_KNOWLEDGE :
curl_easy_setopt ( curl_ - > handle , CURLOPT_HTTP_VERSION , CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE ) ;
break ;
# endif
# if LIBCURL_VERSION_NUM >= 0x074200 // 7.66.0
case HttpVersionCode : : VERSION_3_0 :
curl_easy_setopt ( curl_ - > handle , CURLOPT_HTTP_VERSION , CURL_HTTP_VERSION_3 ) ;
break ;
# endif
default : // Should not happen
throw std : : invalid_argument ( " Invalid/Unknown HTTP version type. " ) ;
}
}
void Session : : SetRange ( const Range & range ) {
const std : : string range_str = range . str ( ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_RANGE , range_str . c_str ( ) ) ;
}
void Session : : SetMultiRange ( const MultiRange & multi_range ) {
const std : : string multi_range_str = multi_range . str ( ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_RANGE , multi_range_str . c_str ( ) ) ;
}
void Session : : SetReserveSize ( const ReserveSize & reserve_size ) {
ResponseStringReserve ( reserve_size . size ) ;
}
void Session : : SetAcceptEncoding ( const AcceptEncoding & accept_encoding ) {
acceptEncoding_ = accept_encoding ;
}
void Session : : SetAcceptEncoding ( AcceptEncoding & & accept_encoding ) {
acceptEncoding_ = std : : move ( accept_encoding ) ;
2021-07-02 17:44:48 +03:00
}
2021-03-27 00:18:51 +02:00
2023-08-05 21:31:33 +03:00
cpr_off_t Session : : GetDownloadFileLength ( ) {
2021-08-22 20:28:37 +03:00
cpr_off_t downloadFileLenth = - 1 ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_URL , url_ . c_str ( ) ) ;
2023-08-05 21:31:33 +03:00
const std : : string protocol = url_ . str ( ) . substr ( 0 , url_ . str ( ) . find ( ' : ' ) ) ;
2021-08-22 20:28:37 +03:00
if ( proxies_ . has ( protocol ) ) {
curl_easy_setopt ( curl_ - > handle , CURLOPT_PROXY , proxies_ [ protocol ] . c_str ( ) ) ;
if ( proxyAuth_ . has ( protocol ) ) {
2023-08-05 21:31:33 +03:00
curl_easy_setopt ( curl_ - > handle , CURLOPT_PROXYUSERNAME , proxyAuth_ . GetUsername ( protocol ) ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_PROXYPASSWORD , proxyAuth_ . GetPassword ( protocol ) ) ;
2021-08-22 20:28:37 +03:00
}
}
curl_easy_setopt ( curl_ - > handle , CURLOPT_HTTPGET , 1 ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_NOBODY , 1 ) ;
2023-08-05 21:31:33 +03:00
if ( DoEasyPerform ( ) = = CURLE_OK ) {
// NOLINTNEXTLINE (google-runtime-int)
long status_code { } ;
curl_easy_getinfo ( curl_ - > handle , CURLINFO_RESPONSE_CODE , & status_code ) ;
if ( 200 = = status_code ) {
curl_easy_getinfo ( curl_ - > handle , CURLINFO_CONTENT_LENGTH_DOWNLOAD_T , & downloadFileLenth ) ;
}
2021-08-22 20:28:37 +03:00
}
return downloadFileLenth ;
}
2023-08-05 21:31:33 +03:00
void Session : : ResponseStringReserve ( size_t size ) {
response_string_reserve_size_ = size ;
}
Response Session : : Delete ( ) {
2021-07-02 17:44:48 +03:00
PrepareDelete ( ) ;
2021-03-27 00:18:51 +02:00
return makeRequest ( ) ;
}
2023-08-05 21:31:33 +03:00
Response Session : : Download ( const WriteCallback & write ) {
PrepareDownload ( write ) ;
return makeDownloadRequest ( ) ;
}
2021-03-27 00:18:51 +02:00
2023-08-05 21:31:33 +03:00
Response Session : : Download ( std : : ofstream & file ) {
PrepareDownload ( file ) ;
2021-03-27 00:18:51 +02:00
return makeDownloadRequest ( ) ;
}
2023-08-05 21:31:33 +03:00
Response Session : : Get ( ) {
PrepareGet ( ) ;
return makeRequest ( ) ;
}
2021-03-27 00:18:51 +02:00
2023-08-05 21:31:33 +03:00
Response Session : : Head ( ) {
PrepareHead ( ) ;
return makeRequest ( ) ;
}
Response Session : : Options ( ) {
PrepareOptions ( ) ;
return makeRequest ( ) ;
}
Response Session : : Patch ( ) {
PreparePatch ( ) ;
return makeRequest ( ) ;
}
Response Session : : Post ( ) {
PreparePost ( ) ;
return makeRequest ( ) ;
}
Response Session : : Put ( ) {
PreparePut ( ) ;
return makeRequest ( ) ;
}
std : : shared_ptr < Session > Session : : GetSharedPtrFromThis ( ) {
try {
return shared_from_this ( ) ;
} catch ( std : : bad_weak_ptr & ) {
throw std : : runtime_error ( " Failed to get a shared pointer from this. The reason is probably that the session object is not managed by a shared pointer, which is required to use this functionality. " ) ;
}
}
AsyncResponse Session : : GetAsync ( ) {
auto shared_this = shared_from_this ( ) ;
return async ( [ shared_this ] ( ) { return shared_this - > Get ( ) ; } ) ;
}
AsyncResponse Session : : DeleteAsync ( ) {
return async ( [ shared_this = GetSharedPtrFromThis ( ) ] ( ) { return shared_this - > Delete ( ) ; } ) ;
}
AsyncResponse Session : : DownloadAsync ( const WriteCallback & write ) {
return async ( [ shared_this = GetSharedPtrFromThis ( ) , write ] ( ) { return shared_this - > Download ( write ) ; } ) ;
}
AsyncResponse Session : : DownloadAsync ( std : : ofstream & file ) {
return async ( [ shared_this = GetSharedPtrFromThis ( ) , & file ] ( ) { return shared_this - > Download ( file ) ; } ) ;
}
AsyncResponse Session : : HeadAsync ( ) {
return async ( [ shared_this = GetSharedPtrFromThis ( ) ] ( ) { return shared_this - > Head ( ) ; } ) ;
}
AsyncResponse Session : : OptionsAsync ( ) {
return async ( [ shared_this = GetSharedPtrFromThis ( ) ] ( ) { return shared_this - > Options ( ) ; } ) ;
}
AsyncResponse Session : : PatchAsync ( ) {
return async ( [ shared_this = GetSharedPtrFromThis ( ) ] ( ) { return shared_this - > Patch ( ) ; } ) ;
}
AsyncResponse Session : : PostAsync ( ) {
return async ( [ shared_this = GetSharedPtrFromThis ( ) ] ( ) { return shared_this - > Post ( ) ; } ) ;
}
AsyncResponse Session : : PutAsync ( ) {
return async ( [ shared_this = GetSharedPtrFromThis ( ) ] ( ) { return shared_this - > Put ( ) ; } ) ;
}
std : : shared_ptr < CurlHolder > Session : : GetCurlHolder ( ) {
return curl_ ;
}
std : : string Session : : GetFullRequestUrl ( ) {
const std : : string parametersContent = parameters_ . GetContent ( * curl_ ) ;
return url_ . str ( ) + ( parametersContent . empty ( ) ? " " : " ? " ) + parametersContent ;
}
void Session : : PrepareDelete ( ) {
curl_easy_setopt ( curl_ - > handle , CURLOPT_HTTPGET , 0L ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_NOBODY , 0L ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_CUSTOMREQUEST , " DELETE " ) ;
prepareCommon ( ) ;
2021-03-27 00:18:51 +02:00
}
2023-08-05 21:31:33 +03:00
void Session : : PrepareGet ( ) {
2021-03-27 00:18:51 +02:00
// In case there is a body or payload for this request, we create a custom GET-Request since a
// GET-Request with body is based on the HTTP RFC **not** a leagal request.
if ( hasBodyOrPayload_ ) {
curl_easy_setopt ( curl_ - > handle , CURLOPT_NOBODY , 0L ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_CUSTOMREQUEST , " GET " ) ;
} else {
curl_easy_setopt ( curl_ - > handle , CURLOPT_NOBODY , 0L ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_CUSTOMREQUEST , nullptr ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_HTTPGET , 1L ) ;
}
2021-08-22 20:28:37 +03:00
prepareCommon ( ) ;
2021-07-02 17:44:48 +03:00
}
2021-03-27 00:18:51 +02:00
2023-08-05 21:31:33 +03:00
void Session : : PrepareHead ( ) {
2021-03-27 00:18:51 +02:00
curl_easy_setopt ( curl_ - > handle , CURLOPT_NOBODY , 1L ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_CUSTOMREQUEST , nullptr ) ;
2021-08-22 20:28:37 +03:00
prepareCommon ( ) ;
2021-07-02 17:44:48 +03:00
}
2021-03-27 00:18:51 +02:00
2023-08-05 21:31:33 +03:00
void Session : : PrepareOptions ( ) {
2021-03-27 00:18:51 +02:00
curl_easy_setopt ( curl_ - > handle , CURLOPT_NOBODY , 0L ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_CUSTOMREQUEST , " OPTIONS " ) ;
2021-07-02 17:44:48 +03:00
prepareCommon ( ) ;
}
2021-03-27 00:18:51 +02:00
2023-08-05 21:31:33 +03:00
void Session : : PreparePatch ( ) {
2021-03-27 00:18:51 +02:00
curl_easy_setopt ( curl_ - > handle , CURLOPT_NOBODY , 0L ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_CUSTOMREQUEST , " PATCH " ) ;
2021-07-02 17:44:48 +03:00
prepareCommon ( ) ;
}
2021-03-27 00:18:51 +02:00
2023-08-05 21:31:33 +03:00
void Session : : PreparePost ( ) {
2021-03-27 00:18:51 +02:00
curl_easy_setopt ( curl_ - > handle , CURLOPT_NOBODY , 0L ) ;
// In case there is no body or payload set it to an empty post:
if ( hasBodyOrPayload_ ) {
curl_easy_setopt ( curl_ - > handle , CURLOPT_CUSTOMREQUEST , nullptr ) ;
} else {
curl_easy_setopt ( curl_ - > handle , CURLOPT_POSTFIELDS , readcb_ . callback ? nullptr : " " ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_CUSTOMREQUEST , " POST " ) ;
}
2021-07-02 17:44:48 +03:00
prepareCommon ( ) ;
}
2021-03-27 00:18:51 +02:00
2023-08-05 21:31:33 +03:00
void Session : : PreparePut ( ) {
2021-03-27 00:18:51 +02:00
curl_easy_setopt ( curl_ - > handle , CURLOPT_NOBODY , 0L ) ;
2023-08-05 21:31:33 +03:00
if ( ! hasBodyOrPayload_ & & readcb_ . callback ) {
/**
* Yes , this one has to be CURLOPT_POSTFIELDS even if we are performing a PUT request .
* In case we don ' t set this one , performing a POST - request with PUT won ' t work .
* It in theory this only enforces the usage of the readcallback for POST requests , but works here as well .
* */
curl_easy_setopt ( curl_ - > handle , CURLOPT_POSTFIELDS , nullptr ) ;
}
2021-03-27 00:18:51 +02:00
curl_easy_setopt ( curl_ - > handle , CURLOPT_CUSTOMREQUEST , " PUT " ) ;
2023-08-05 21:31:33 +03:00
curl_easy_setopt ( curl_ - > handle , CURLOPT_RANGE , nullptr ) ;
2021-08-22 20:28:37 +03:00
prepareCommon ( ) ;
2021-07-02 17:44:48 +03:00
}
2021-03-27 00:18:51 +02:00
2023-08-05 21:31:33 +03:00
void Session : : PrepareDownload ( std : : ofstream & file ) {
curl_easy_setopt ( curl_ - > handle , CURLOPT_NOBODY , 0L ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_HTTPGET , 1 ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_WRITEFUNCTION , cpr : : util : : writeFileFunction ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_WRITEDATA , & file ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_CUSTOMREQUEST , nullptr ) ;
2021-03-27 00:18:51 +02:00
2023-08-05 21:31:33 +03:00
prepareCommonDownload ( ) ;
2021-03-27 00:18:51 +02:00
}
2023-08-05 21:31:33 +03:00
void Session : : PrepareDownload ( const WriteCallback & write ) {
curl_easy_setopt ( curl_ - > handle , CURLOPT_NOBODY , 0L ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_HTTPGET , 1 ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_CUSTOMREQUEST , nullptr ) ;
2021-03-27 00:18:51 +02:00
2023-08-05 21:31:33 +03:00
SetWriteCallback ( write ) ;
2021-03-27 00:18:51 +02:00
2023-08-05 21:31:33 +03:00
prepareCommonDownload ( ) ;
}
2021-03-27 00:18:51 +02:00
2023-08-05 21:31:33 +03:00
Response Session : : Complete ( CURLcode curl_error ) {
curl_slist * raw_cookies { nullptr } ;
curl_easy_getinfo ( curl_ - > handle , CURLINFO_COOKIELIST , & raw_cookies ) ;
Cookies cookies = util : : parseCookies ( raw_cookies ) ;
curl_slist_free_all ( raw_cookies ) ;
// Reset the has no body property:
hasBodyOrPayload_ = false ;
2021-03-27 00:18:51 +02:00
2023-08-05 21:31:33 +03:00
std : : string errorMsg = curl_ - > error . data ( ) ;
return Response ( curl_ , std : : move ( response_string_ ) , std : : move ( header_string_ ) , std : : move ( cookies ) , Error ( curl_error , std : : move ( errorMsg ) ) ) ;
}
2021-03-27 00:18:51 +02:00
2023-08-05 21:31:33 +03:00
Response Session : : CompleteDownload ( CURLcode curl_error ) {
2021-08-22 20:28:37 +03:00
if ( ! headercb_ . callback ) {
curl_easy_setopt ( curl_ - > handle , CURLOPT_HEADERFUNCTION , nullptr ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_HEADERDATA , 0 ) ;
}
2021-03-27 00:18:51 +02:00
curl_slist * raw_cookies { nullptr } ;
curl_easy_getinfo ( curl_ - > handle , CURLINFO_COOKIELIST , & raw_cookies ) ;
Cookies cookies = util : : parseCookies ( raw_cookies ) ;
curl_slist_free_all ( raw_cookies ) ;
std : : string errorMsg = curl_ - > error . data ( ) ;
2023-08-05 21:31:33 +03:00
return Response ( curl_ , " " , std : : move ( header_string_ ) , std : : move ( cookies ) , Error ( curl_error , std : : move ( errorMsg ) ) ) ;
2021-03-27 00:18:51 +02:00
}
2023-08-05 21:31:33 +03:00
void Session : : AddInterceptor ( const std : : shared_ptr < Interceptor > & pinterceptor ) {
interceptors_ . push ( pinterceptor ) ;
2021-07-02 17:44:48 +03:00
}
2021-03-27 00:18:51 +02:00
2023-08-05 21:31:33 +03:00
Response Session : : proceed ( ) {
prepareCommon ( ) ;
return makeRequest ( ) ;
2021-07-02 17:44:48 +03:00
}
2021-03-27 00:18:51 +02:00
2023-08-05 21:31:33 +03:00
Response Session : : intercept ( ) {
// At least one interceptor exists -> Execute its intercept function
const std : : shared_ptr < Interceptor > interceptor = interceptors_ . front ( ) ;
interceptors_ . pop ( ) ;
return interceptor - > intercept ( * this ) ;
2021-03-27 00:18:51 +02:00
}
// clang-format off
2023-08-05 21:31:33 +03:00
void Session : : SetOption ( const Resolve & resolve ) { SetResolve ( resolve ) ; }
void Session : : SetOption ( const std : : vector < Resolve > & resolves ) { SetResolves ( resolves ) ; }
void Session : : SetOption ( const ReadCallback & read ) { SetReadCallback ( read ) ; }
void Session : : SetOption ( const HeaderCallback & header ) { SetHeaderCallback ( header ) ; }
void Session : : SetOption ( const WriteCallback & write ) { SetWriteCallback ( write ) ; }
void Session : : SetOption ( const ProgressCallback & progress ) { SetProgressCallback ( progress ) ; }
void Session : : SetOption ( const DebugCallback & debug ) { SetDebugCallback ( debug ) ; }
void Session : : SetOption ( const Url & url ) { SetUrl ( url ) ; }
void Session : : SetOption ( const Parameters & parameters ) { SetParameters ( parameters ) ; }
void Session : : SetOption ( Parameters & & parameters ) { SetParameters ( std : : move ( parameters ) ) ; }
void Session : : SetOption ( const Header & header ) { SetHeader ( header ) ; }
void Session : : SetOption ( const Timeout & timeout ) { SetTimeout ( timeout ) ; }
void Session : : SetOption ( const ConnectTimeout & timeout ) { SetConnectTimeout ( timeout ) ; }
void Session : : SetOption ( const Authentication & auth ) { SetAuth ( auth ) ; }
void Session : : SetOption ( const LimitRate & limit_rate ) { SetLimitRate ( limit_rate ) ; }
2021-03-27 00:18:51 +02:00
// Only supported with libcurl >= 7.61.0.
// As an alternative use SetHeader and add the token manually.
# if LIBCURL_VERSION_NUM >= 0x073D00
2023-08-05 21:31:33 +03:00
void Session : : SetOption ( const Bearer & auth ) { SetBearer ( auth ) ; }
2021-03-27 00:18:51 +02:00
# endif
2023-08-05 21:31:33 +03:00
void Session : : SetOption ( const UserAgent & ua ) { SetUserAgent ( ua ) ; }
void Session : : SetOption ( const Payload & payload ) { SetPayload ( payload ) ; }
void Session : : SetOption ( Payload & & payload ) { SetPayload ( std : : move ( payload ) ) ; }
void Session : : SetOption ( const Proxies & proxies ) { SetProxies ( proxies ) ; }
void Session : : SetOption ( Proxies & & proxies ) { SetProxies ( std : : move ( proxies ) ) ; }
void Session : : SetOption ( ProxyAuthentication & & proxy_auth ) { SetProxyAuth ( std : : move ( proxy_auth ) ) ; }
void Session : : SetOption ( const ProxyAuthentication & proxy_auth ) { SetProxyAuth ( proxy_auth ) ; }
void Session : : SetOption ( const Multipart & multipart ) { SetMultipart ( multipart ) ; }
void Session : : SetOption ( Multipart & & multipart ) { SetMultipart ( std : : move ( multipart ) ) ; }
void Session : : SetOption ( const Redirect & redirect ) { SetRedirect ( redirect ) ; }
void Session : : SetOption ( const Cookies & cookies ) { SetCookies ( cookies ) ; }
void Session : : SetOption ( const Body & body ) { SetBody ( body ) ; }
void Session : : SetOption ( Body & & body ) { SetBody ( std : : move ( body ) ) ; }
void Session : : SetOption ( const LowSpeed & low_speed ) { SetLowSpeed ( low_speed ) ; }
void Session : : SetOption ( const VerifySsl & verify ) { SetVerifySsl ( verify ) ; }
void Session : : SetOption ( const Verbose & verbose ) { SetVerbose ( verbose ) ; }
void Session : : SetOption ( const UnixSocket & unix_socket ) { SetUnixSocket ( unix_socket ) ; }
void Session : : SetOption ( const SslOptions & options ) { SetSslOptions ( options ) ; }
void Session : : SetOption ( const Interface & iface ) { SetInterface ( iface ) ; }
void Session : : SetOption ( const LocalPort & local_port ) { SetLocalPort ( local_port ) ; }
void Session : : SetOption ( const LocalPortRange & local_port_range ) { SetLocalPortRange ( local_port_range ) ; }
void Session : : SetOption ( const HttpVersion & version ) { SetHttpVersion ( version ) ; }
void Session : : SetOption ( const Range & range ) { SetRange ( range ) ; }
void Session : : SetOption ( const MultiRange & multi_range ) { SetMultiRange ( multi_range ) ; }
void Session : : SetOption ( const ReserveSize & reserve_size ) { SetReserveSize ( reserve_size . size ) ; }
void Session : : SetOption ( const AcceptEncoding & accept_encoding ) { SetAcceptEncoding ( accept_encoding ) ; }
void Session : : SetOption ( AcceptEncoding & & accept_encoding ) { SetAcceptEncoding ( accept_encoding ) ; }
2021-03-27 00:18:51 +02:00
// clang-format on
2023-08-05 21:31:33 +03:00
void Session : : SetCancellationParam ( std : : shared_ptr < std : : atomic_bool > param ) {
cancellationcb_ = CancellationCallback { std : : move ( param ) } ;
isCancellable = true ;
# if LIBCURL_VERSION_NUM < 0x072000 // 7.32.0
curl_easy_setopt ( curl_ - > handle , CURLOPT_PROGRESSFUNCTION , cpr : : util : : progressUserFunction < CancellationCallback > ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_PROGRESSDATA , & cancellationcb_ ) ;
# else
curl_easy_setopt ( curl_ - > handle , CURLOPT_XFERINFOFUNCTION , cpr : : util : : progressUserFunction < CancellationCallback > ) ;
curl_easy_setopt ( curl_ - > handle , CURLOPT_XFERINFODATA , & cancellationcb_ ) ;
# endif
curl_easy_setopt ( curl_ - > handle , CURLOPT_NOPROGRESS , 0L ) ;
}
2021-03-27 00:18:51 +02:00
} // namespace cpr