@ -6,13 +6,14 @@
# include <cstdlib>
# include <mutex>
# include <string>
# include <LUrlParser.h>
# include <fmt/format.h>
# include <httplib.h>
# include "common/common_types.h"
# include "common/logging/log.h"
# include "common/web_result.h"
# include "web_service/web_backend.h"
# include "web_service/web_result.h"
namespace WebService {
@ -33,17 +34,16 @@ struct Client::Impl {
}
/// A generic function handles POST, GET and DELETE request together
Common: : WebResult GenericRequest ( const std : : string & method , const std : : string & path ,
const std : : string & data , bool allow_anonymous ,
const std : : string & accept ) {
WebResult GenericRequest ( const std : : string & method , const std : : string & path ,
const std : : string & data , bool allow_anonymous ,
const std : : string & accept ) {
if ( jwt . empty ( ) ) {
UpdateJWT ( ) ;
}
if ( jwt . empty ( ) & & ! allow_anonymous ) {
LOG_ERROR ( WebService , " Credentials must be provided for authenticated requests " ) ;
return Common : : WebResult { Common : : WebResult : : Code : : CredentialsMissing ,
" Credentials needed " , " " } ;
return WebResult { WebResult : : Code : : CredentialsMissing , " Credentials needed " , " " } ;
}
auto result = GenericRequest ( method , path , data , accept , jwt ) ;
@ -62,10 +62,10 @@ struct Client::Impl {
* username + token is used if jwt is empty but username and token are
* not empty anonymous if all of jwt , username and token are empty
*/
Common: : WebResult GenericRequest ( const std : : string & method , const std : : string & path ,
const std : : string & data , const std : : string & accept ,
const std : : string & jwt = " " , const std : : string & username = " " ,
const std : : string & token = " " ) {
WebResult GenericRequest ( const std : : string & method , const std : : string & path ,
const std : : string & data , const std : : string & accept ,
const std : : string & jwt = " " , const std : : string & username = " " ,
const std : : string & token = " " ) {
if ( cli = = nullptr ) {
auto parsedUrl = LUrlParser : : clParseURL : : ParseURL ( host ) ;
int port ;
@ -81,12 +81,12 @@ struct Client::Impl {
cli = std : : make_unique < httplib : : SSLClient > ( parsedUrl . m_Host . c_str ( ) , port ) ;
} else {
LOG_ERROR ( WebService , " Bad URL scheme {} " , parsedUrl . m_Scheme ) ;
return Common: : WebResult{ Common : : WebResult : : Code : : InvalidURL , " Bad URL scheme " , " " } ;
return WebResult{ WebResult : : Code : : InvalidURL , " Bad URL scheme " , " " } ;
}
}
if ( cli = = nullptr ) {
LOG_ERROR ( WebService , " Invalid URL {} " , host + path ) ;
return Common: : WebResult{ Common : : WebResult : : Code : : InvalidURL , " Invalid URL " , " " } ;
return WebResult{ WebResult : : Code : : InvalidURL , " Invalid URL " , " " } ;
}
cli - > set_timeout_sec ( TIMEOUT_SECONDS ) ;
@ -106,7 +106,7 @@ struct Client::Impl {
std : : string ( API_VERSION . begin ( ) , API_VERSION . end ( ) ) ) ;
if ( method ! = " GET " ) {
params . emplace ( std : : string ( " Content-Type " ) , std : : string ( " application/json " ) ) ;
} ;
}
httplib : : Request request ;
request . method = method ;
@ -118,29 +118,28 @@ struct Client::Impl {
if ( ! cli - > send ( request , response ) ) {
LOG_ERROR ( WebService , " {} to {} returned null " , method , host + path ) ;
return Common: : WebResult{ Common : : WebResult : : Code : : LibError , " Null response " , " " } ;
return WebResult{ WebResult : : Code : : LibError , " Null response " , " " } ;
}
if ( response . status > = 400 ) {
LOG_ERROR ( WebService , " {} to {} returned error status code: {} " , method , host + path ,
response . status ) ;
return Common : : WebResult { Common : : WebResult : : Code : : HttpError ,
std : : to_string ( response . status ) , " " } ;
return WebResult { WebResult : : Code : : HttpError , std : : to_string ( response . status ) , " " } ;
}
auto content_type = response . headers . find ( " content-type " ) ;
if ( content_type = = response . headers . end ( ) ) {
LOG_ERROR ( WebService , " {} to {} returned no content " , method , host + path ) ;
return Common: : WebResult{ Common : : WebResult : : Code : : WrongContent , " " , " " } ;
return WebResult{ WebResult : : Code : : WrongContent , " " , " " } ;
}
if ( content_type - > second . find ( accept ) = = std : : string : : npos ) {
LOG_ERROR ( WebService , " {} to {} returned wrong content: {} " , method , host + path ,
content_type - > second ) ;
return Common: : WebResult{ Common : : WebResult : : Code : : WrongContent , " Wrong content " , " " } ;
return WebResult{ WebResult : : Code : : WrongContent , " Wrong content " , " " } ;
}
return Common: : WebResult{ Common : : WebResult : : Code : : Success , " " , response . body } ;
return WebResult{ WebResult : : Code : : Success , " " , response . body } ;
}
// Retrieve a new JWT from given username and token
@ -150,7 +149,7 @@ struct Client::Impl {
}
auto result = GenericRequest ( " POST " , " /jwt/internal " , " " , " text/html " , " " , username , token ) ;
if ( result . result_code ! = Common: : WebResult: : Code : : Success ) {
if ( result . result_code ! = WebResult: : Code : : Success ) {
LOG_ERROR ( WebService , " UpdateJWT failed " ) ;
} else {
std : : lock_guard lock { jwt_cache . mutex } ;
@ -180,29 +179,28 @@ Client::Client(std::string host, std::string username, std::string token)
Client : : ~ Client ( ) = default ;
Common : : WebResult Client : : PostJson ( const std : : string & path , const std : : string & data ,
bool allow_anonymous ) {
WebResult Client : : PostJson ( const std : : string & path , const std : : string & data , bool allow_anonymous ) {
return impl - > GenericRequest ( " POST " , path , data , allow_anonymous , " application/json " ) ;
}
Common : : WebResult Client : : GetJson ( const std : : string & path , bool allow_anonymous ) {
WebResult Client : : GetJson ( const std : : string & path , bool allow_anonymous ) {
return impl - > GenericRequest ( " GET " , path , " " , allow_anonymous , " application/json " ) ;
}
Common : : WebResult Client : : DeleteJson ( const std : : string & path , const std : : string & data ,
bool allow_anonymous ) {
WebResult Client : : DeleteJson ( const std : : string & path , const std : : string & data ,
bool allow_anonymous ) {
return impl - > GenericRequest ( " DELETE " , path , data , allow_anonymous , " application/json " ) ;
}
Common : : WebResult Client : : GetPlain ( const std : : string & path , bool allow_anonymous ) {
WebResult Client : : GetPlain ( const std : : string & path , bool allow_anonymous ) {
return impl - > GenericRequest ( " GET " , path , " " , allow_anonymous , " text/plain " ) ;
}
Common : : WebResult Client : : GetImage ( const std : : string & path , bool allow_anonymous ) {
WebResult Client : : GetImage ( const std : : string & path , bool allow_anonymous ) {
return impl - > GenericRequest ( " GET " , path , " " , allow_anonymous , " image/png " ) ;
}
Common : : WebResult Client : : GetExternalJWT ( const std : : string & audience ) {
WebResult Client : : GetExternalJWT ( const std : : string & audience ) {
return impl - > GenericRequest ( " POST " , fmt : : format ( " /jwt/external/{} " , audience ) , " " , false ,
" text/html " ) ;
}