added the http::Header class. should add it long ago.

pull/40/head
Nestal Wan 2012-06-03 16:42:51 +08:00
parent 81f71f8406
commit c17ba4e880
12 changed files with 197 additions and 70 deletions

View File

@ -23,7 +23,7 @@
#include "Entry.hh"
#include "http/Agent.hh"
// #include "http/ResponseLog.hh"
#include "http/ResponseLog.hh"
#include "http/XmlResponse.hh"
#include "protocol/Json.hh"
#include "protocol/OAuth2.hh"
@ -56,8 +56,8 @@ Drive::Drive( OAuth2& auth, const Json& options ) :
m_auth( auth ),
m_state( state_file, options )
{
m_http_hdr.push_back( "Authorization: Bearer " + m_auth.AccessToken() ) ;
m_http_hdr.push_back( "GData-Version: 3.0" ) ;
m_http_hdr.Add( "Authorization: Bearer " + m_auth.AccessToken() ) ;
m_http_hdr.Add( "GData-Version: 3.0" ) ;
Log( "Reading local directories", log::info ) ;
m_state.FromLocal( "." ) ;
@ -127,7 +127,8 @@ void Drive::SyncFolders( http::Agent *http )
Log( "Synchronizing folders", log::info ) ;
http::XmlResponse xml ;
http->Get( feed_base + "/-/folder?max-results=50&showroot=true", &xml, m_http_hdr ) ;
http::ResponseLog log( "dir-", ".xml", &xml ) ;
http->Get( feed_base + "/-/folder?max-results=50&showroot=true", &log, m_http_hdr ) ;
xml::Node resp = xml.Response() ;

View File

@ -21,6 +21,7 @@
#include "State.hh"
#include "http/Header.hh"
#include "util/Exception.hh"
#include <string>
@ -52,11 +53,11 @@ private :
void file();
private :
OAuth2& m_auth ;
std::vector<std::string> m_http_hdr ;
OAuth2& m_auth ;
http::Header m_http_hdr ;
std::string m_resume_link ;
State m_state ;
std::string m_resume_link ;
State m_state ;
} ;
} // end of namespace

View File

@ -20,6 +20,7 @@
#include "Resource.hh"
#include "CommonUri.hh"
#include "http/Agent.hh"
#include "http/Download.hh"
// #include "http/ResponseLog.hh"
#include "http/StringResponse.hh"
@ -33,6 +34,8 @@
#include "xml/Node.hh"
#include "xml/NodeSet.hh"
#include <boost/exception/all.hpp>
#include <cassert>
// for debugging
@ -291,7 +294,7 @@ Resource* Resource::FindChild( const std::string& name )
}
// try to change the state to "sync"
void Resource::Sync( http::Agent *http, const http::Headers& auth )
void Resource::Sync( http::Agent *http, const http::Header& auth )
{
assert( m_state != unknown ) ;
@ -370,25 +373,27 @@ void Resource::DeleteLocal()
fs::rename( Path(), dest ) ;
}
void Resource::DeleteRemote( http::Agent *http, const http::Headers& auth )
void Resource::DeleteRemote( http::Agent *http, const http::Header& auth )
{
http::Headers hdr( auth ) ;
hdr.push_back( "If-Match: " + m_entry.ETag() ) ;
http::Header hdr( auth ) ;
hdr.Add( "If-Match: " + m_entry.ETag() ) ;
http::StringResponse str ;
try
{
http->Custom( "DELETE", http->Unescape(m_entry.SelfHref()) , &str, hdr ) ;
}
catch ( Exception& )
catch ( Exception& e )
{
// don't rethrow here. there are some cases that I don't know why
// the delete will fail.
Trace( "response = %1%", str.Response() ) ;
Trace( "Exception %1% %2%",
boost::diagnostic_information(e),
str.Response() ) ;
}
}
void Resource::Download( http::Agent* http, const fs::path& file, const http::Headers& auth ) const
void Resource::Download( http::Agent* http, const fs::path& file, const http::Header& auth ) const
{
http::Download dl( file.string(), http::Download::NoChecksum() ) ;
long r = http->Get( m_entry.ContentSrc(), &dl, auth ) ;
@ -396,7 +401,7 @@ void Resource::Download( http::Agent* http, const fs::path& file, const http::He
os::SetFileTime( file, m_entry.MTime() ) ;
}
bool Resource::EditContent( http::Agent* http, const http::Headers& auth )
bool Resource::EditContent( http::Agent* http, const http::Header& auth )
{
assert( m_parent != 0 ) ;
@ -414,7 +419,7 @@ bool Resource::EditContent( http::Agent* http, const http::Headers& auth )
return Upload( http, m_entry.EditLink(), auth, false ) ;
}
bool Resource::Create( http::Agent* http, const http::Headers& auth )
bool Resource::Create( http::Agent* http, const http::Header& auth )
{
assert( m_parent != 0 ) ;
assert( m_parent->IsFolder() ) ;
@ -431,8 +436,8 @@ bool Resource::Create( http::Agent* http, const http::Headers& auth )
std::string meta = (boost::format(xml_meta) % "folder" % Name() ).str() ;
http::Headers hdr( auth ) ;
hdr.push_back( "Content-Type: application/atom+xml" ) ;
http::Header hdr( auth ) ;
hdr.Add( "Content-Type: application/atom+xml" ) ;
http::XmlResponse xml ;
// http::ResponseLog log( "create", ".xml", &xml ) ;
@ -452,7 +457,7 @@ bool Resource::Create( http::Agent* http, const http::Headers& auth )
}
}
bool Resource::Upload( http::Agent* http, const std::string& link, const http::Headers& auth, bool post )
bool Resource::Upload( http::Agent* http, const std::string& link, const http::Header& auth, bool post )
{
StdioFile file( Path() ) ;
@ -466,12 +471,12 @@ bool Resource::Upload( http::Agent* http, const std::string& link, const http::H
std::ostringstream xcontent_len ;
xcontent_len << "X-Upload-Content-Length: " << data.size() ;
http::Headers hdr( auth ) ;
hdr.push_back( "Content-Type: application/atom+xml" ) ;
hdr.push_back( "X-Upload-Content-Type: application/octet-stream" ) ;
hdr.push_back( xcontent_len.str() ) ;
hdr.push_back( "If-Match: " + m_entry.ETag() ) ;
hdr.push_back( "Expect:" ) ;
http::Header hdr( auth ) ;
hdr.Add( "Content-Type: application/atom+xml" ) ;
hdr.Add( "X-Upload-Content-Type: application/octet-stream" ) ;
hdr.Add( xcontent_len.str() ) ;
hdr.Add( "If-Match: " + m_entry.ETag() ) ;
hdr.Add( "Expect:" ) ;
std::string meta = (boost::format( xml_meta ) % m_entry.Kind() % Name()).str() ;
@ -481,9 +486,9 @@ bool Resource::Upload( http::Agent* http, const std::string& link, const http::H
else
http->Put( link, meta, &str, hdr ) ;
http::Headers uphdr ;
uphdr.push_back( "Expect:" ) ;
uphdr.push_back( "Accept:" ) ;
http::Header uphdr ;
uphdr.Add( "Expect:" ) ;
uphdr.Add( "Accept:" ) ;
// the content upload URL is in the "Location" HTTP header
std::string uplink = http->RedirLocation() ;

View File

@ -20,7 +20,6 @@
#pragma once
#include "Entry.hh"
#include "http/Agent.hh"
#include "util/Exception.hh"
#include "util/FileSystem.hh"
@ -30,6 +29,12 @@
namespace gr {
namespace http
{
class Agent ;
class Header ;
}
class Json ;
/*! \brief A resource can be a file or a folder in the google drive
@ -72,7 +77,7 @@ public :
void FromRemote( const Entry& remote, const DateTime& last_sync ) ;
void FromLocal( const DateTime& last_sync ) ;
void Sync( http::Agent *http, const http::Headers& auth ) ;
void Sync( gr::http::Agent* http, const http::Header& auth ) ;
Json Serialize() const ;
@ -119,16 +124,16 @@ private :
friend std::ostream& operator<<( std::ostream& os, State s ) ;
private :
void Download( http::Agent* http, const fs::path& file, const http::Headers& auth ) const ;
bool EditContent( http::Agent* http, const http::Headers& auth ) ;
bool Create( http::Agent* http, const http::Headers& auth ) ;
bool Upload( http::Agent* http, const std::string& link, const http::Headers& auth, bool post ) ;
void Download( http::Agent* http, const fs::path& file, const http::Header& auth ) const ;
bool EditContent( http::Agent* http, const http::Header& auth ) ;
bool Create( http::Agent* http, const http::Header& auth ) ;
bool Upload( http::Agent* http, const std::string& link, const http::Header& auth, bool post ) ;
void FromRemoteFolder( const Entry& remote, const DateTime& last_sync ) ;
void FromRemoteFile( const Entry& remote, const DateTime& last_sync ) ;
void DeleteLocal() ;
void DeleteRemote( http::Agent* http, const http::Headers& auth ) ;
void DeleteRemote( http::Agent* http, const http::Header& auth ) ;
private :
Entry m_entry ;

View File

@ -22,6 +22,7 @@
#include "Resource.hh"
#include "CommonUri.hh"
#include "http/Agent.hh"
#include "util/Crypt.hh"
#include "util/Log.hh"
#include "protocol/Json.hh"
@ -219,7 +220,7 @@ void State::Write( const fs::path& filename ) const
fs << result ;
}
void State::Sync( http::Agent *http, const http::Headers& auth )
void State::Sync( http::Agent *http, const http::Header& auth )
{
std::for_each( m_res.begin(), m_res.end(),
boost::bind( &Resource::Sync, _1, http, auth ) ) ;

View File

@ -21,7 +21,6 @@
#include "ResourceTree.hh"
#include "http/Agent.hh"
#include "util/DateTime.hh"
#include "util/FileSystem.hh"
@ -29,6 +28,12 @@
namespace gr {
namespace http
{
class Agent ;
class Header ;
}
class Json ;
class Resource ;
class Entry ;
@ -52,7 +57,7 @@ public :
Resource* FindByID( const std::string& id ) ;
Resource* Find( const fs::path& path ) ;
void Sync( http::Agent *http, const http::Headers& auth ) ;
void Sync( http::Agent *http, const http::Header& auth ) ;
iterator begin() ;
iterator end() ;

View File

@ -126,9 +126,9 @@ std::size_t Agent::Receive( void* ptr, size_t size, size_t nmemb, Receivable *re
}
long Agent::ExecCurl(
const std::string& url,
Receivable *dest,
const http::Headers& hdr )
const std::string& url,
Receivable *dest,
const http::Header& hdr )
{
CURL *curl = m_pimpl->curl ;
assert( curl != 0 ) ;
@ -158,6 +158,7 @@ long Agent::ExecCurl(
<< HttpResponse( http_code )
<< Url( url )
<< expt::ErrMsg( error )
<< HttpHeader( hdr )
) ;
}
@ -168,7 +169,7 @@ long Agent::Put(
const std::string& url,
const std::string& data,
Receivable *dest,
const http::Headers& hdr )
const Header& hdr )
{
Trace("HTTP PUT \"%1%\"", url ) ;
@ -189,7 +190,7 @@ long Agent::Put(
long Agent::Get(
const std::string& url,
Receivable *dest,
const http::Headers& hdr )
const Header& hdr )
{
Trace("HTTP GET \"%1%\"", url ) ;
@ -206,7 +207,7 @@ long Agent::Post(
const std::string& url,
const std::string& data,
Receivable *dest,
const http::Headers& hdr )
const Header& hdr )
{
Trace("HTTP POST \"%1%\" with \"%2%\"", url, data ) ;
@ -228,22 +229,23 @@ long Agent::Custom(
const std::string& method,
const std::string& url,
Receivable *dest,
const http::Headers& hdr )
const Header& hdr )
{
Trace("HTTP %2% \"%1%\"", url, method ) ;
CURL *curl = m_pimpl->curl ;
::curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, method.c_str() );
::curl_easy_setopt(curl, CURLOPT_VERBOSE, 1 );
return ExecCurl( url, dest, hdr ) ;
}
void Agent::SetHeader( const http::Headers& hdr )
void Agent::SetHeader( const Header& hdr )
{
// set headers
struct curl_slist *curl_hdr = 0 ;
for ( Headers::const_iterator i = hdr.begin() ; i != hdr.end() ; ++i )
for ( Header::iterator i = hdr.begin() ; i != hdr.end() ; ++i )
curl_hdr = curl_slist_append( curl_hdr, i->c_str() ) ;
::curl_easy_setopt( m_pimpl->curl, CURLOPT_HTTPHEADER, curl_hdr ) ;

View File

@ -19,14 +19,14 @@
#pragma once
#include "Header.hh"
#include <memory>
#include <string>
#include <vector>
namespace gr { namespace http {
typedef std::vector<std::string> Headers ;
class Receivable ;
/*! \class Agent
@ -44,27 +44,27 @@ public :
void SetLogFile( const std::string& prefix ) ;
long Put(
const std::string& url,
const std::string& data,
Receivable *dest,
const http::Headers& hdr = http::Headers() ) ;
const std::string& url,
const std::string& data,
Receivable *dest,
const Header& hdr = Header() ) ;
long Get(
const std::string& url,
Receivable *dest,
const http::Headers& hdr = http::Headers() ) ;
const std::string& url,
Receivable *dest,
const Header& hdr = Header() ) ;
long Post(
const std::string& url,
const std::string& data,
Receivable *dest,
const http::Headers& hdr = http::Headers() ) ;
const std::string& url,
const std::string& data,
Receivable *dest,
const Header& hdr = Header() ) ;
long Custom(
const std::string& method,
const std::string& url,
Receivable *dest,
const http::Headers& hdr = http::Headers() ) ;
const std::string& method,
const std::string& url,
Receivable *dest,
const Header& hdr = Header() ) ;
std::string RedirLocation() const ;
@ -75,11 +75,11 @@ private :
static std::size_t HeaderCallback( void *ptr, size_t size, size_t nmemb, Agent *pthis ) ;
static std::size_t Receive( void* ptr, size_t size, size_t nmemb, Receivable *recv ) ;
void SetHeader( const http::Headers& hdr ) ;
void SetHeader( const Header& hdr ) ;
long ExecCurl(
const std::string& url,
Receivable *dest,
const http::Headers& hdr) ;
const std::string& url,
Receivable *dest,
const Header& hdr ) ;
void Init() ;

View File

@ -19,6 +19,7 @@
#pragma once
#include "Header.hh"
#include "util/Exception.hh"
namespace gr { namespace http {
@ -37,4 +38,7 @@ typedef boost::error_info<struct HttpResponseStrTag, std::string> HttpResponseTe
// URL
typedef boost::error_info<struct UrlTag, std::string> Url ;
// HTTP headers
typedef boost::error_info<struct HeaderTag, Header> HttpHeader ;
} } // end of namespace

View File

@ -0,0 +1,53 @@
/*
grive: an GPL program to sync a local directory with Google Drive
Copyright (C) 2012 Wan Wai Ho
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation version 2
of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "Header.hh"
#include <algorithm>
#include <iterator>
#include <ostream>
namespace gr { namespace http {
Header::Header()
{
}
void Header::Add( const std::string& str )
{
m_vec.push_back( str ) ;
}
Header::iterator Header::begin() const
{
return m_vec.begin() ;
}
Header::iterator Header::end() const
{
return m_vec.end() ;
}
std::ostream& operator<<( std::ostream& os, const Header& h )
{
std::copy( h.begin(), h.end(), std::ostream_iterator<std::string>( os, "\n" ) ) ;
return os ;
}
} } // end of namespace

View File

@ -0,0 +1,50 @@
/*
grive: an GPL program to sync a local directory with Google Drive
Copyright (C) 2012 Wan Wai Ho
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation version 2
of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#pragma once
#include <iosfwd>
#include <string>
#include <vector>
namespace gr { namespace http {
class Header
{
private :
typedef std::vector<std::string> Vec ;
public :
typedef Vec::const_iterator iterator ;
public :
Header() ;
void Add( const std::string& str ) ;
iterator begin() const ;
iterator end() const ;
private :
Vec m_vec ;
} ;
std::ostream& operator<<( std::ostream& os, const Header& h ) ;
}} // end of namespace

View File

@ -39,7 +39,7 @@ DefaultLog::DefaultLog( const std::string& filename ) :
m_file( filename.c_str() ),
m_log( m_file )
{
m_enabled[log::debug] = false ;
m_enabled[log::debug] = true ;
m_enabled[log::verbose] = true ;
m_enabled[log::info] = true ;
m_enabled[log::warning] = true ;