2023-07-20 11:10:32 +02:00
# pragma once
# include <string>
# include <functional>
# include <memory>
# include "Common/File/Path.h"
# include "Common/Net/NetBuffer.h"
namespace http {
enum class RequestMethod {
GET ,
POST ,
} ;
enum class ProgressBarMode {
NONE ,
VISIBLE ,
DELAYED ,
} ;
// Abstract request.
2023-07-21 22:04:05 +02:00
class Request {
2023-07-20 11:10:32 +02:00
public :
2023-07-21 22:04:05 +02:00
Request ( RequestMethod method , const std : : string & url , const std : : string & name , bool * cancelled , ProgressBarMode mode ) ;
virtual ~ Request ( ) { }
2023-07-20 11:10:32 +02:00
2023-07-21 10:49:01 +02:00
void SetAccept ( const char * mime ) {
acceptMime_ = mime ;
}
void SetUserAgent ( const std : : string & userAgent ) {
userAgent_ = userAgent ;
}
2023-07-20 11:10:32 +02:00
// NOTE: Completion callbacks (which these are) are deferred until RunCallback is called. This is so that
// the call will end up on the thread that calls g_DownloadManager.Update().
2023-07-21 22:04:05 +02:00
void SetCallback ( std : : function < void ( Request & ) > callback ) {
2023-07-20 11:10:32 +02:00
callback_ = callback ;
}
void RunCallback ( ) {
if ( callback_ ) {
callback_ ( * this ) ;
}
}
virtual void Start ( ) = 0 ;
virtual void Join ( ) = 0 ;
2023-07-20 11:25:27 +02:00
virtual bool Done ( ) = 0 ;
2023-07-20 11:10:32 +02:00
virtual bool Failed ( ) const = 0 ;
virtual int ResultCode ( ) const = 0 ;
// Returns 1.0 when done. That one value can be compared exactly - or just use Done().
float Progress ( ) const { return progress_ . progress ; }
float SpeedKBps ( ) const { return progress_ . kBps ; }
std : : string url ( ) const { return url_ ; }
virtual const Path & outfile ( ) const = 0 ;
virtual void Cancel ( ) = 0 ;
virtual bool IsCancelled ( ) const = 0 ;
// Response
virtual Buffer & buffer ( ) = 0 ;
virtual const Buffer & buffer ( ) const = 0 ;
protected :
2023-07-21 22:04:05 +02:00
std : : function < void ( Request & ) > callback_ ;
2023-07-21 17:50:49 +02:00
RequestMethod method_ ;
2023-07-20 11:10:32 +02:00
std : : string url_ ;
std : : string name_ ;
2023-07-21 10:49:01 +02:00
const char * acceptMime_ = " */* " ;
std : : string userAgent_ ;
2023-07-20 11:10:32 +02:00
net : : RequestProgress progress_ ;
2023-07-21 17:50:49 +02:00
ProgressBarMode progressBarMode_ ;
2023-07-20 11:10:32 +02:00
} ;
using std : : shared_ptr ;
class RequestManager {
public :
~ RequestManager ( ) {
CancelAll ( ) ;
}
2023-07-21 22:04:05 +02:00
std : : shared_ptr < Request > StartDownload ( const std : : string & url , const Path & outfile , ProgressBarMode mode , const char * acceptMime = nullptr ) ;
2023-07-20 11:10:32 +02:00
2023-07-21 22:04:05 +02:00
std : : shared_ptr < Request > StartDownloadWithCallback (
2023-07-20 11:10:32 +02:00
const std : : string & url ,
const Path & outfile ,
ProgressBarMode mode ,
2023-07-21 22:04:05 +02:00
std : : function < void ( Request & ) > callback ,
2023-07-20 11:10:32 +02:00
const std : : string & name = " " ,
const char * acceptMime = nullptr ) ;
2023-07-21 22:04:05 +02:00
std : : shared_ptr < Request > AsyncPostWithCallback (
2023-07-20 11:10:32 +02:00
const std : : string & url ,
const std : : string & postData ,
const std : : string & postMime , // Use postMime = "application/x-www-form-urlencoded" for standard form-style posts, such as used by retroachievements. For encoding form data manually we have MultipartFormDataEncoder.
ProgressBarMode mode ,
2023-07-21 22:04:05 +02:00
std : : function < void ( Request & ) > callback ,
2023-07-20 11:10:32 +02:00
const std : : string & name = " " ) ;
// Drops finished downloads from the list.
void Update ( ) ;
void CancelAll ( ) ;
void WaitForAll ( ) ;
void SetUserAgent ( const std : : string & userAgent ) {
userAgent_ = userAgent ;
}
private :
2023-07-20 11:25:27 +02:00
bool IsHttpsUrl ( const std : : string & url ) ;
2023-07-21 22:04:05 +02:00
std : : vector < std : : shared_ptr < Request > > downloads_ ;
2023-07-20 11:10:32 +02:00
// These get copied to downloads_ in Update(). It's so that callbacks can add new downloads
// while running.
2023-07-21 22:04:05 +02:00
std : : vector < std : : shared_ptr < Request > > newDownloads_ ;
2023-07-20 11:10:32 +02:00
std : : string userAgent_ ;
} ;
2023-08-25 13:53:46 +02:00
inline const char * RequestMethodToString ( RequestMethod method ) {
switch ( method ) {
case RequestMethod : : GET : return " GET " ;
case RequestMethod : : POST : return " POST " ;
default : return " N/A " ;
}
}
2023-07-20 11:10:32 +02:00
} // namespace net