mirror of https://github.com/vitalif/grive2
Implement normal reliable HTTP logging (in Agent)
Flushes on every call so may be slightly slow, but in return always provides full information in case of a segfault or a failed assertion.pull/40/head
parent
9b8e0c826b
commit
9402bff12e
|
@ -112,7 +112,7 @@ int Main( int argc, char **argv )
|
|||
( "path,p", po::value<std::string>(), "Path to sync")
|
||||
( "dir,s", po::value<std::string>(), "Subdirectory to sync")
|
||||
( "verbose,V", "Verbose mode. Enable more messages than normal.")
|
||||
( "log-xml", "Log more HTTP responses as XML for debugging.")
|
||||
( "log-http", po::value<std::string>(), "Log all HTTP responses in this file for debugging.")
|
||||
( "new-rev", "Create new revisions in server for updated files.")
|
||||
( "debug,d", "Enable debug level messages. Implies -v.")
|
||||
( "log,l", po::value<std::string>(), "Set log output filename." )
|
||||
|
@ -147,12 +147,18 @@ int Main( int argc, char **argv )
|
|||
|
||||
Log( "config file name %1%", config.Filename(), log::verbose );
|
||||
|
||||
std::auto_ptr<http::Agent> http( new http::CurlAgent );
|
||||
if ( vm.count( "log-http" ) )
|
||||
http->SetLog( new http::ResponseLog( vm["log-http"].as<std::string>(), ".txt" ) );
|
||||
|
||||
if ( vm.count( "auth" ) )
|
||||
{
|
||||
OAuth2 token( http, client_id, client_secret ) ;
|
||||
|
||||
std::cout
|
||||
<< "-----------------------\n"
|
||||
<< "Please go to this URL and get an authentication code:\n\n"
|
||||
<< OAuth2::MakeAuthURL( client_id )
|
||||
<< token.MakeAuthURL()
|
||||
<< std::endl ;
|
||||
|
||||
std::cout
|
||||
|
@ -161,7 +167,6 @@ int Main( int argc, char **argv )
|
|||
std::string code ;
|
||||
std::cin >> code ;
|
||||
|
||||
OAuth2 token( client_id, client_secret ) ;
|
||||
token.Auth( code ) ;
|
||||
|
||||
// save to config
|
||||
|
@ -184,8 +189,8 @@ int Main( int argc, char **argv )
|
|||
return -1;
|
||||
}
|
||||
|
||||
OAuth2 token( refresh_token, client_id, client_secret ) ;
|
||||
AuthAgent agent( token, std::auto_ptr<http::Agent>( new http::CurlAgent ) ) ;
|
||||
OAuth2 token( http, refresh_token, client_id, client_secret ) ;
|
||||
AuthAgent agent( token, http ) ;
|
||||
v2::Syncer2 syncer( &agent );
|
||||
|
||||
Drive drive( &syncer, config.GetAll() ) ;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include "ResponseLog.hh"
|
||||
|
||||
namespace gr {
|
||||
|
||||
|
@ -35,6 +36,9 @@ class Agent
|
|||
public :
|
||||
virtual ~Agent() {}
|
||||
|
||||
virtual ResponseLog* GetLog() const = 0 ;
|
||||
virtual void SetLog( ResponseLog* ) = 0 ;
|
||||
|
||||
virtual long Put(
|
||||
const std::string& url,
|
||||
const std::string& data,
|
||||
|
|
|
@ -118,6 +118,16 @@ CurlAgent::~CurlAgent()
|
|||
::curl_easy_cleanup( m_pimpl->curl );
|
||||
}
|
||||
|
||||
ResponseLog* CurlAgent::GetLog() const
|
||||
{
|
||||
return m_log.get();
|
||||
}
|
||||
|
||||
void CurlAgent::SetLog(ResponseLog *log)
|
||||
{
|
||||
m_log.reset( log );
|
||||
}
|
||||
|
||||
std::size_t CurlAgent::HeaderCallback( void *ptr, size_t size, size_t nmemb, CurlAgent *pthis )
|
||||
{
|
||||
char *str = static_cast<char*>(ptr) ;
|
||||
|
@ -130,6 +140,9 @@ std::size_t CurlAgent::HeaderCallback( void *ptr, size_t size, size_t nmemb, Cur
|
|||
if ( pthis->m_pimpl->error )
|
||||
pthis->m_pimpl->error_headers += line;
|
||||
|
||||
if ( pthis->m_log.get() )
|
||||
pthis->m_log->Write( str, size*nmemb );
|
||||
|
||||
static const std::string loc = "Location: " ;
|
||||
std::size_t pos = line.find( loc ) ;
|
||||
if ( pos != line.npos )
|
||||
|
@ -144,6 +157,8 @@ std::size_t CurlAgent::HeaderCallback( void *ptr, size_t size, size_t nmemb, Cur
|
|||
std::size_t CurlAgent::Receive( void* ptr, size_t size, size_t nmemb, CurlAgent *pthis )
|
||||
{
|
||||
assert( pthis != 0 ) ;
|
||||
if ( pthis->m_log.get() )
|
||||
pthis->m_log->Write( (const char*)ptr, size*nmemb );
|
||||
if ( pthis->m_pimpl->error && pthis->m_pimpl->error_data.size() < 65536 )
|
||||
{
|
||||
// Do not feed error responses to destination stream
|
||||
|
@ -284,6 +299,7 @@ long CurlAgent::Custom(
|
|||
{
|
||||
Trace("HTTP %2% \"%1%\"", url, method ) ;
|
||||
|
||||
Init() ;
|
||||
CURL *curl = m_pimpl->curl ;
|
||||
|
||||
::curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, method.c_str() );
|
||||
|
|
|
@ -40,7 +40,10 @@ class CurlAgent : public Agent
|
|||
public :
|
||||
CurlAgent() ;
|
||||
~CurlAgent() ;
|
||||
|
||||
|
||||
ResponseLog* GetLog() const ;
|
||||
void SetLog( ResponseLog *log ) ;
|
||||
|
||||
long Put(
|
||||
const std::string& url,
|
||||
const std::string& post_data,
|
||||
|
@ -92,6 +95,7 @@ private :
|
|||
private :
|
||||
struct Impl ;
|
||||
std::auto_ptr<Impl> m_pimpl ;
|
||||
std::auto_ptr<ResponseLog> m_log ;
|
||||
} ;
|
||||
|
||||
} } // end of namespace
|
||||
|
|
|
@ -28,19 +28,9 @@ namespace gr { namespace http {
|
|||
|
||||
ResponseLog::ResponseLog(
|
||||
const std::string& prefix,
|
||||
const std::string& suffix,
|
||||
DataStream *next ) :
|
||||
m_enabled ( true ),
|
||||
m_next ( next )
|
||||
const std::string& suffix )
|
||||
{
|
||||
Reset( prefix, suffix, next ) ;
|
||||
}
|
||||
|
||||
ResponseLog::ResponseLog( DataStream *next ) :
|
||||
m_enabled ( false ),
|
||||
m_next ( next )
|
||||
{
|
||||
assert( m_next != 0 ) ;
|
||||
Reset( prefix, suffix ) ;
|
||||
}
|
||||
|
||||
std::size_t ResponseLog::Write( const char *data, std::size_t count )
|
||||
|
@ -49,15 +39,14 @@ std::size_t ResponseLog::Write( const char *data, std::size_t count )
|
|||
{
|
||||
assert( m_log.rdbuf() != 0 ) ;
|
||||
m_log.rdbuf()->sputn( data, count ) ;
|
||||
m_log.flush();
|
||||
}
|
||||
|
||||
return m_next->Write( data, count ) ;
|
||||
return count;
|
||||
}
|
||||
|
||||
std::size_t ResponseLog::Read( char *data, std::size_t count )
|
||||
{
|
||||
assert( m_next != 0 ) ;
|
||||
return m_next->Read( data, count ) ;
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
std::string ResponseLog::Filename( const std::string& prefix, const std::string& suffix )
|
||||
|
@ -65,19 +54,12 @@ std::string ResponseLog::Filename( const std::string& prefix, const std::string&
|
|||
return prefix + DateTime::Now().Format( "%F.%H%M%S" ) + suffix ;
|
||||
}
|
||||
|
||||
void ResponseLog::Enable( bool enable )
|
||||
void ResponseLog::Reset( const std::string& prefix, const std::string& suffix )
|
||||
{
|
||||
m_enabled = enable ;
|
||||
}
|
||||
|
||||
void ResponseLog::Reset( const std::string& prefix, const std::string& suffix, DataStream *next )
|
||||
{
|
||||
assert( next != 0 ) ;
|
||||
|
||||
if ( m_log.is_open() )
|
||||
m_log.close() ;
|
||||
|
||||
const std::string fname = Filename(prefix, suffix) ;
|
||||
const std::string fname = Filename( prefix, suffix ) ;
|
||||
|
||||
// reset previous stream state. don't care if file can be opened
|
||||
// successfully previously
|
||||
|
@ -88,12 +70,13 @@ void ResponseLog::Reset( const std::string& prefix, const std::string& suffix, D
|
|||
if ( m_log )
|
||||
{
|
||||
Trace( "logging HTTP response: %1%", fname ) ;
|
||||
m_enabled = true ;
|
||||
m_enabled = true ;
|
||||
}
|
||||
else
|
||||
{
|
||||
Trace( "cannot open log file %1%", fname ) ;
|
||||
|
||||
m_next = next ;
|
||||
m_enabled = false ;
|
||||
}
|
||||
}
|
||||
|
||||
}} // end of namespace
|
||||
|
|
|
@ -31,23 +31,19 @@ class ResponseLog : public DataStream
|
|||
public :
|
||||
ResponseLog(
|
||||
const std::string& prefix,
|
||||
const std::string& suffix,
|
||||
DataStream *next ) ;
|
||||
ResponseLog( DataStream *next ) ;
|
||||
|
||||
const std::string& suffix ) ;
|
||||
|
||||
std::size_t Write( const char *data, std::size_t count ) ;
|
||||
std::size_t Read( char *data, std::size_t count ) ;
|
||||
|
||||
void Enable( bool enable = true ) ;
|
||||
void Reset( const std::string& prefix, const std::string& suffix, DataStream *next ) ;
|
||||
void Reset( const std::string& prefix, const std::string& suffix ) ;
|
||||
|
||||
private :
|
||||
static std::string Filename( const std::string& prefix, const std::string& suffix ) ;
|
||||
|
||||
private :
|
||||
bool m_enabled ;
|
||||
bool m_enabled ;
|
||||
std::ofstream m_log ;
|
||||
DataStream *m_next ;
|
||||
} ;
|
||||
|
||||
} } // end of namespace
|
||||
|
|
|
@ -20,8 +20,6 @@
|
|||
|
||||
#include "ValBuilder.hh"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace gr {
|
||||
|
||||
ValBuilder::ValBuilder( )
|
||||
|
@ -106,7 +104,8 @@ void ValBuilder::End( Val::TypeEnum type )
|
|||
{
|
||||
if ( m_ctx.top().val.Type() == type )
|
||||
{
|
||||
assert( m_ctx.top().key.Is<void>() ) ;
|
||||
if( !m_ctx.top().key.Is<void>() )
|
||||
BOOST_THROW_EXCEPTION( Error() << Unexpected_(m_ctx.top().key) ) ;
|
||||
|
||||
// get top Val from stack
|
||||
Val current ;
|
||||
|
@ -130,8 +129,12 @@ void ValBuilder::EndObject()
|
|||
|
||||
Val ValBuilder::Result() const
|
||||
{
|
||||
assert( m_ctx.size() == 1U ) ;
|
||||
return m_ctx.top().val ;
|
||||
if ( !m_ctx.size() )
|
||||
BOOST_THROW_EXCEPTION( Error() << NoKey_( Val(std::string("")) ) ) ;
|
||||
Val r = m_ctx.top().val;
|
||||
if ( m_ctx.size() > 0 )
|
||||
BOOST_THROW_EXCEPTION( Error() << Unexpected_(m_ctx.top().val) ) ;
|
||||
return r;
|
||||
}
|
||||
|
||||
} // end of namespace
|
||||
|
|
|
@ -31,13 +31,23 @@ namespace gr {
|
|||
|
||||
using namespace http ;
|
||||
|
||||
AuthAgent::AuthAgent( const OAuth2& auth, std::auto_ptr<Agent> real_agent ) :
|
||||
AuthAgent::AuthAgent( OAuth2& auth, std::auto_ptr<Agent> real_agent ) :
|
||||
m_auth ( auth ),
|
||||
m_agent ( real_agent )
|
||||
{
|
||||
assert( m_agent.get() != 0 ) ;
|
||||
}
|
||||
|
||||
http::ResponseLog* AuthAgent::GetLog() const
|
||||
{
|
||||
return m_agent->GetLog();
|
||||
}
|
||||
|
||||
void AuthAgent::SetLog( http::ResponseLog *log )
|
||||
{
|
||||
return m_agent->SetLog( log );
|
||||
}
|
||||
|
||||
Header AuthAgent::AppendHeader( const Header& hdr ) const
|
||||
{
|
||||
Header h(hdr) ;
|
||||
|
|
|
@ -34,7 +34,10 @@ namespace gr {
|
|||
class AuthAgent : public http::Agent
|
||||
{
|
||||
public :
|
||||
AuthAgent( const OAuth2& auth, std::auto_ptr<http::Agent> real_agent ) ;
|
||||
AuthAgent( OAuth2& auth, std::auto_ptr<http::Agent> real_agent ) ;
|
||||
|
||||
http::ResponseLog* GetLog() const ;
|
||||
void SetLog( http::ResponseLog *log ) ;
|
||||
|
||||
long Put(
|
||||
const std::string& url,
|
||||
|
@ -82,7 +85,7 @@ private :
|
|||
const http::Header& hdr ) ;
|
||||
|
||||
private :
|
||||
OAuth2 m_auth ;
|
||||
OAuth2& m_auth ;
|
||||
const std::auto_ptr<http::Agent> m_agent ;
|
||||
} ;
|
||||
|
||||
|
|
|
@ -33,9 +33,11 @@ namespace gr {
|
|||
const std::string token_url = "https://accounts.google.com/o/oauth2/token" ;
|
||||
|
||||
OAuth2::OAuth2(
|
||||
std::auto_ptr<http::Agent>& agent,
|
||||
const std::string& refresh_code,
|
||||
const std::string& client_id,
|
||||
const std::string& client_secret ) :
|
||||
m_agent( agent ),
|
||||
m_refresh( refresh_code ),
|
||||
m_client_id( client_id ),
|
||||
m_client_secret( client_secret )
|
||||
|
@ -44,8 +46,10 @@ OAuth2::OAuth2(
|
|||
}
|
||||
|
||||
OAuth2::OAuth2(
|
||||
std::auto_ptr<http::Agent>& agent,
|
||||
const std::string& client_id,
|
||||
const std::string& client_secret ) :
|
||||
m_agent( agent ),
|
||||
m_client_id( client_id ),
|
||||
m_client_secret( client_secret )
|
||||
{
|
||||
|
@ -61,32 +65,26 @@ void OAuth2::Auth( const std::string& auth_code )
|
|||
"&grant_type=authorization_code" ;
|
||||
|
||||
http::ValResponse resp ;
|
||||
http::CurlAgent http ;
|
||||
|
||||
DisableLog dlog( log::debug ) ;
|
||||
http.Post( token_url, post, &resp, http::Header() ) ;
|
||||
m_agent->Post( token_url, post, &resp, http::Header() ) ;
|
||||
|
||||
Val jresp = resp.Response() ;
|
||||
m_access = jresp["access_token"].Str() ;
|
||||
m_refresh = jresp["refresh_token"].Str() ;
|
||||
}
|
||||
|
||||
std::string OAuth2::MakeAuthURL(
|
||||
const std::string& client_id,
|
||||
const std::string& state )
|
||||
std::string OAuth2::MakeAuthURL()
|
||||
{
|
||||
http::CurlAgent h ;
|
||||
|
||||
return "https://accounts.google.com/o/oauth2/auth"
|
||||
"?scope=" +
|
||||
h.Escape( "https://www.googleapis.com/auth/userinfo.email" ) + "+" +
|
||||
h.Escape( "https://www.googleapis.com/auth/userinfo.profile" ) + "+" +
|
||||
h.Escape( "https://docs.google.com/feeds/" ) + "+" +
|
||||
h.Escape( "https://docs.googleusercontent.com/" ) + "+" +
|
||||
h.Escape( "https://spreadsheets.google.com/feeds/" ) +
|
||||
m_agent->Escape( "https://www.googleapis.com/auth/userinfo.email" ) + "+" +
|
||||
m_agent->Escape( "https://www.googleapis.com/auth/userinfo.profile" ) + "+" +
|
||||
m_agent->Escape( "https://docs.google.com/feeds/" ) + "+" +
|
||||
m_agent->Escape( "https://docs.googleusercontent.com/" ) + "+" +
|
||||
m_agent->Escape( "https://spreadsheets.google.com/feeds/" ) +
|
||||
"&redirect_uri=urn:ietf:wg:oauth:2.0:oob"
|
||||
"&response_type=code"
|
||||
"&client_id=" + client_id ;
|
||||
"&client_id=" + m_client_id ;
|
||||
}
|
||||
|
||||
void OAuth2::Refresh( )
|
||||
|
@ -98,10 +96,8 @@ void OAuth2::Refresh( )
|
|||
"&grant_type=refresh_token" ;
|
||||
|
||||
http::ValResponse resp ;
|
||||
http::CurlAgent http ;
|
||||
|
||||
DisableLog dlog( log::debug ) ;
|
||||
http.Post( token_url, post, &resp, http::Header() ) ;
|
||||
|
||||
m_agent->Post( token_url, post, &resp, http::Header() ) ;
|
||||
|
||||
m_access = resp.Response()["access_token"].Str() ;
|
||||
}
|
||||
|
|
|
@ -19,7 +19,9 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "http/Agent.hh"
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
namespace gr {
|
||||
|
||||
|
@ -27,34 +29,35 @@ class OAuth2
|
|||
{
|
||||
public :
|
||||
OAuth2(
|
||||
std::auto_ptr<http::Agent>& agent,
|
||||
const std::string& client_id,
|
||||
const std::string& client_secret ) ;
|
||||
OAuth2(
|
||||
std::auto_ptr<http::Agent>& agent,
|
||||
const std::string& refresh_code,
|
||||
const std::string& client_id,
|
||||
const std::string& client_secret ) ;
|
||||
|
||||
std::string Str() const ;
|
||||
|
||||
static std::string MakeAuthURL(
|
||||
const std::string& client_id,
|
||||
const std::string& state = std::string() ) ;
|
||||
|
||||
std::string MakeAuthURL() ;
|
||||
|
||||
void Auth( const std::string& auth_code ) ;
|
||||
void Refresh( ) ;
|
||||
|
||||
|
||||
std::string RefreshToken( ) const ;
|
||||
std::string AccessToken( ) const ;
|
||||
|
||||
|
||||
// adding HTTP auth header
|
||||
std::string HttpHeader( ) const ;
|
||||
|
||||
|
||||
private :
|
||||
std::string m_access ;
|
||||
std::string m_refresh ;
|
||||
std::auto_ptr<http::Agent> m_agent ;
|
||||
|
||||
const std::string m_client_id ;
|
||||
const std::string m_client_secret ;
|
||||
} ;
|
||||
|
||||
|
||||
} // end of namespace
|
||||
|
|
|
@ -38,7 +38,6 @@ const std::string default_root_folder = ".";
|
|||
|
||||
Config::Config( const po::variables_map& vm )
|
||||
{
|
||||
m_cmd.Add( "log-xml", Val(vm.count("log-xml") > 0) ) ;
|
||||
m_cmd.Add( "new-rev", Val(vm.count("new-rev") > 0) ) ;
|
||||
m_cmd.Add( "force", Val(vm.count("force") > 0 ) ) ;
|
||||
m_cmd.Add( "path", Val(vm.count("path") > 0
|
||||
|
|
Loading…
Reference in New Issue