From 9402bff12e50621fcd7f70779b78b552a3d5dae6 Mon Sep 17 00:00:00 2001 From: Vitaliy Filippov Date: Wed, 30 Sep 2015 15:01:50 +0300 Subject: [PATCH] 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. --- grive/src/main.cc | 15 ++++++++---- libgrive/src/http/Agent.hh | 4 +++ libgrive/src/http/CurlAgent.cc | 16 ++++++++++++ libgrive/src/http/CurlAgent.hh | 6 ++++- libgrive/src/http/ResponseLog.cc | 39 +++++++++--------------------- libgrive/src/http/ResponseLog.hh | 12 +++------ libgrive/src/json/ValBuilder.cc | 13 ++++++---- libgrive/src/protocol/AuthAgent.cc | 12 ++++++++- libgrive/src/protocol/AuthAgent.hh | 7 ++++-- libgrive/src/protocol/OAuth2.cc | 32 +++++++++++------------- libgrive/src/protocol/OAuth2.hh | 19 +++++++++------ libgrive/src/util/Config.cc | 1 - 12 files changed, 99 insertions(+), 77 deletions(-) diff --git a/grive/src/main.cc b/grive/src/main.cc index 07fd613..a6efff5 100644 --- a/grive/src/main.cc +++ b/grive/src/main.cc @@ -112,7 +112,7 @@ int Main( int argc, char **argv ) ( "path,p", po::value(), "Path to sync") ( "dir,s", po::value(), "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(), "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(), "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( new http::CurlAgent ); + if ( vm.count( "log-http" ) ) + http->SetLog( new http::ResponseLog( vm["log-http"].as(), ".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( 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() ) ; diff --git a/libgrive/src/http/Agent.hh b/libgrive/src/http/Agent.hh index 5f4d5de..09d3b87 100644 --- a/libgrive/src/http/Agent.hh +++ b/libgrive/src/http/Agent.hh @@ -20,6 +20,7 @@ #pragma once #include +#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, diff --git a/libgrive/src/http/CurlAgent.cc b/libgrive/src/http/CurlAgent.cc index 04c1143..2e9d566 100644 --- a/libgrive/src/http/CurlAgent.cc +++ b/libgrive/src/http/CurlAgent.cc @@ -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(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() ); diff --git a/libgrive/src/http/CurlAgent.hh b/libgrive/src/http/CurlAgent.hh index e06fd21..044e2bc 100644 --- a/libgrive/src/http/CurlAgent.hh +++ b/libgrive/src/http/CurlAgent.hh @@ -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 m_pimpl ; + std::auto_ptr m_log ; } ; } } // end of namespace diff --git a/libgrive/src/http/ResponseLog.cc b/libgrive/src/http/ResponseLog.cc index 9de4ac0..b26856e 100644 --- a/libgrive/src/http/ResponseLog.cc +++ b/libgrive/src/http/ResponseLog.cc @@ -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 diff --git a/libgrive/src/http/ResponseLog.hh b/libgrive/src/http/ResponseLog.hh index 046b5c9..9c3b63a 100644 --- a/libgrive/src/http/ResponseLog.hh +++ b/libgrive/src/http/ResponseLog.hh @@ -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 diff --git a/libgrive/src/json/ValBuilder.cc b/libgrive/src/json/ValBuilder.cc index c5658ff..7a0068e 100644 --- a/libgrive/src/json/ValBuilder.cc +++ b/libgrive/src/json/ValBuilder.cc @@ -20,8 +20,6 @@ #include "ValBuilder.hh" -#include - 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() ) ; + if( !m_ctx.top().key.Is() ) + 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 diff --git a/libgrive/src/protocol/AuthAgent.cc b/libgrive/src/protocol/AuthAgent.cc index 6af5be2..145c05d 100644 --- a/libgrive/src/protocol/AuthAgent.cc +++ b/libgrive/src/protocol/AuthAgent.cc @@ -31,13 +31,23 @@ namespace gr { using namespace http ; -AuthAgent::AuthAgent( const OAuth2& auth, std::auto_ptr real_agent ) : +AuthAgent::AuthAgent( OAuth2& auth, std::auto_ptr 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) ; diff --git a/libgrive/src/protocol/AuthAgent.hh b/libgrive/src/protocol/AuthAgent.hh index 797b240..4ceeaff 100644 --- a/libgrive/src/protocol/AuthAgent.hh +++ b/libgrive/src/protocol/AuthAgent.hh @@ -34,7 +34,10 @@ namespace gr { class AuthAgent : public http::Agent { public : - AuthAgent( const OAuth2& auth, std::auto_ptr real_agent ) ; + AuthAgent( OAuth2& auth, std::auto_ptr 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 m_agent ; } ; diff --git a/libgrive/src/protocol/OAuth2.cc b/libgrive/src/protocol/OAuth2.cc index a13c8e3..6dbd754 100644 --- a/libgrive/src/protocol/OAuth2.cc +++ b/libgrive/src/protocol/OAuth2.cc @@ -33,9 +33,11 @@ namespace gr { const std::string token_url = "https://accounts.google.com/o/oauth2/token" ; OAuth2::OAuth2( + std::auto_ptr& 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& 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() ; } diff --git a/libgrive/src/protocol/OAuth2.hh b/libgrive/src/protocol/OAuth2.hh index e8713f3..71c1c01 100644 --- a/libgrive/src/protocol/OAuth2.hh +++ b/libgrive/src/protocol/OAuth2.hh @@ -19,7 +19,9 @@ #pragma once +#include "http/Agent.hh" #include +#include namespace gr { @@ -27,34 +29,35 @@ class OAuth2 { public : OAuth2( + std::auto_ptr& agent, const std::string& client_id, const std::string& client_secret ) ; OAuth2( + std::auto_ptr& 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 m_agent ; const std::string m_client_id ; const std::string m_client_secret ; } ; - + } // end of namespace diff --git a/libgrive/src/util/Config.cc b/libgrive/src/util/Config.cc index c1c53ea..69ac344 100644 --- a/libgrive/src/util/Config.cc +++ b/libgrive/src/util/Config.cc @@ -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