Try to replace avhttp by Curl
This commit is contained in:
+53
-133
@@ -38,8 +38,7 @@ I have lost my enthusiasm for local caching until a faster time stamp retrieval
|
||||
mechanism can be found, or github gets more servers. But note that the occasionally
|
||||
slow response is the exception rather than the norm. Normally the response is
|
||||
down around a 1/3 of a second. The information we would use is in the header
|
||||
named "Last-Modified" as seen below. This would need parsing, but avhttp may
|
||||
offer some help there, if not, then boost async probably does.
|
||||
named "Last-Modified" as seen below.
|
||||
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
@@ -62,23 +61,9 @@ Access-Control-Expose-Headers: ETag, Link, X-RateLimit-Limit, X-RateLimit-Remain
|
||||
Access-Control-Allow-Origin: *
|
||||
X-GitHub-Request-Id: 411087C2:659E:50FD6E6:52E67F66
|
||||
Vary: Accept-Encoding
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
// when WIN32_LEAN_AND_MEAN is defined, some useless includes in <window.h>
|
||||
// are skipped, and this avoid some compil issues
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
// defines needed by avhttp
|
||||
// Minimal Windows version is XP: Google for _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x0501
|
||||
#define WINVER 0x0501
|
||||
#endif
|
||||
|
||||
#include <kicad_curl/kicad_curl_easy.h> // Include before any wx file
|
||||
#include <sstream>
|
||||
#include <boost/ptr_container/ptr_map.hpp>
|
||||
#include <set>
|
||||
@@ -88,10 +73,6 @@ Vary: Accept-Encoding
|
||||
#include <wx/uri.h>
|
||||
|
||||
#include <fctsys.h>
|
||||
// Under Windows Mingw/msys, avhttp.hpp should be included after fctsys.h
|
||||
// in fact after wx/wx.h, included by fctsys.h,
|
||||
// to avoid issues (perhaps due to incompatible defines)
|
||||
#include <avhttp.hpp> // chinese SSL magic
|
||||
|
||||
#include <io_mgr.h>
|
||||
#include <richio.h>
|
||||
@@ -103,6 +84,7 @@ Vary: Accept-Encoding
|
||||
#include <fp_lib_table.h> // ExpandSubstitutions()
|
||||
#include <github_getliblist.h>
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
@@ -139,7 +121,7 @@ GITHUB_PLUGIN::~GITHUB_PLUGIN()
|
||||
|
||||
const wxString GITHUB_PLUGIN::PluginName() const
|
||||
{
|
||||
return wxT( "Github" );
|
||||
return "Github";
|
||||
}
|
||||
|
||||
|
||||
@@ -212,7 +194,8 @@ MODULE* GITHUB_PLUGIN::FootprintLoad( const wxString& aLibraryPath,
|
||||
|
||||
if( it != m_gh_cache->end() ) // fp_name is present
|
||||
{
|
||||
wxMemoryInputStream mis( &m_zip_image[0], m_zip_image.size() );
|
||||
//std::string::data() ensures that the referenced data block is contiguous.
|
||||
wxMemoryInputStream mis( m_zip_image.data(), m_zip_image.size() );
|
||||
|
||||
// This decoder should always be UTF8, since it was saved that way by git.
|
||||
// That is, since pretty footprints are UTF8, and they were pushed to the
|
||||
@@ -223,21 +206,17 @@ MODULE* GITHUB_PLUGIN::FootprintLoad( const wxString& aLibraryPath,
|
||||
if( zis.OpenEntry( *entry ) )
|
||||
{
|
||||
INPUTSTREAM_LINE_READER reader( &zis, aLibraryPath );
|
||||
#if 1
|
||||
|
||||
// I am a PCB_IO derivative with my own PCB_PARSER
|
||||
m_parser->SetLineReader( &reader ); // ownership not passed
|
||||
|
||||
MODULE* ret = (MODULE*) m_parser->Parse();
|
||||
#else
|
||||
PCB_PARSER parser( &reader );
|
||||
|
||||
MODULE* ret = (MODULE*) parser.Parse();
|
||||
#endif
|
||||
|
||||
// Dude, the footprint name comes from the file name in
|
||||
// a github library. Zero out the library name, we don't know it here.
|
||||
// Some caller may set the library nickname, one such instance is
|
||||
// FP_LIB_TABLE::FootprintLoad().
|
||||
// In a github library, (as well as in a "KiCad" library) the name of
|
||||
// the pretty file defines the footprint name. That filename trumps
|
||||
// any name found in the pretty file; any name in the pretty file
|
||||
// must be ignored here. Also, the library nickname is unknown in
|
||||
// this context so clear it just in case.
|
||||
ret->SetFPID( fp_name );
|
||||
|
||||
return ret;
|
||||
@@ -408,7 +387,7 @@ void GITHUB_PLUGIN::cacheLib( const wxString& aLibraryPath, const PROPERTIES* aP
|
||||
|
||||
if( !wx_pretty_fn.IsOk() ||
|
||||
!wx_pretty_fn.IsDirWritable() ||
|
||||
wx_pretty_fn.GetExt() != wxT( "pretty" )
|
||||
wx_pretty_fn.GetExt() != "pretty"
|
||||
)
|
||||
{
|
||||
wxString msg = wxString::Format(
|
||||
@@ -425,13 +404,13 @@ void GITHUB_PLUGIN::cacheLib( const wxString& aLibraryPath, const PROPERTIES* aP
|
||||
}
|
||||
|
||||
// operator==( wxString, wxChar* ) does not exist, construct wxString once here.
|
||||
const wxString kicad_mod( wxT( "kicad_mod" ) );
|
||||
const wxString kicad_mod( "kicad_mod" );
|
||||
|
||||
//D(printf("%s: this:%p m_lib_path:'%s' aLibraryPath:'%s'\n", __func__, this, TO_UTF8( m_lib_path), TO_UTF8(aLibraryPath) );)
|
||||
m_gh_cache = new GH_CACHE();
|
||||
|
||||
// INIT_LOGGER( "/tmp", "test.log" );
|
||||
remote_get_zip( aLibraryPath );
|
||||
remoteGetZip( aLibraryPath );
|
||||
// UNINIT_LOGGER();
|
||||
|
||||
m_lib_path = aLibraryPath;
|
||||
@@ -460,7 +439,7 @@ void GITHUB_PLUGIN::cacheLib( const wxString& aLibraryPath, const PROPERTIES* aP
|
||||
}
|
||||
|
||||
|
||||
bool GITHUB_PLUGIN::repoURL_zipURL( const wxString& aRepoURL, string* aZipURL )
|
||||
bool GITHUB_PLUGIN::repoURL_zipURL( const wxString& aRepoURL, std::string* aZipURL )
|
||||
{
|
||||
// e.g. "https://github.com/liftoff-sr/pretty_footprints"
|
||||
//D(printf("aRepoURL:%s\n", TO_UTF8( aRepoURL ) );)
|
||||
@@ -470,12 +449,12 @@ bool GITHUB_PLUGIN::repoURL_zipURL( const wxString& aRepoURL, string* aZipURL )
|
||||
if( repo.HasServer() && repo.HasPath() )
|
||||
{
|
||||
// scheme might be "http" or if truly github.com then "https".
|
||||
wxString zip_url = repo.GetScheme();
|
||||
|
||||
zip_url += "://";
|
||||
wxString zip_url;
|
||||
|
||||
if( repo.GetServer() == "github.com" )
|
||||
{
|
||||
//codeload.github.com only supports https
|
||||
zip_url = "https://";
|
||||
#if 0 // A proper code path would be this one, but it is not the fastest.
|
||||
zip_url += repo.GetServer();
|
||||
zip_url += repo.GetPath(); // path comes with a leading '/'
|
||||
@@ -488,8 +467,6 @@ bool GITHUB_PLUGIN::repoURL_zipURL( const wxString& aRepoURL, string* aZipURL )
|
||||
|
||||
// In order to bypass this redirect, saving time, we use the
|
||||
// redirected URL on first attempt to save one HTTP GET hit.
|
||||
// avhttp would do the redirect behind the scenes normally, but that would
|
||||
// be slower than doing this bypass.
|
||||
zip_url += "codeload.github.com";
|
||||
zip_url += repo.GetPath(); // path comes with a leading '/'
|
||||
zip_url += "/zip/master";
|
||||
@@ -498,9 +475,11 @@ bool GITHUB_PLUGIN::repoURL_zipURL( const wxString& aRepoURL, string* aZipURL )
|
||||
|
||||
else
|
||||
{
|
||||
zip_url = repo.GetScheme();
|
||||
zip_url += "://";
|
||||
|
||||
// This is the generic code path for any server which can serve
|
||||
// up zip files. The schemes tested include: http and https.
|
||||
// (I don't know what the avhttp library supports beyond that.)
|
||||
|
||||
// zip_url goal: "<scheme>://<server>[:<port>]/<path>"
|
||||
|
||||
@@ -533,9 +512,9 @@ bool GITHUB_PLUGIN::repoURL_zipURL( const wxString& aRepoURL, string* aZipURL )
|
||||
}
|
||||
|
||||
|
||||
void GITHUB_PLUGIN::remote_get_zip( const wxString& aRepoURL ) throw( IO_ERROR )
|
||||
void GITHUB_PLUGIN::remoteGetZip( const wxString& aRepoURL ) throw( IO_ERROR )
|
||||
{
|
||||
string zip_url;
|
||||
std::string zip_url;
|
||||
|
||||
if( !repoURL_zipURL( aRepoURL, &zip_url ) )
|
||||
{
|
||||
@@ -543,107 +522,48 @@ void GITHUB_PLUGIN::remote_get_zip( const wxString& aRepoURL ) throw( IO_ERROR )
|
||||
THROW_IO_ERROR( msg );
|
||||
}
|
||||
|
||||
boost::asio::io_service io;
|
||||
avhttp::http_stream h( io );
|
||||
avhttp::request_opts options;
|
||||
wxLogDebug( wxT( "Attempting to download: " ) + zip_url );
|
||||
|
||||
options.insert( "Accept", "application/zip" );
|
||||
options.insert( "User-Agent", "http://kicad-pcb.org" ); // THAT WOULD BE ME.
|
||||
h.request_options( options );
|
||||
KICAD_CURL_EASY kcurl; // this can THROW_IO_ERROR
|
||||
|
||||
kcurl.SetURL( zip_url.c_str() );
|
||||
kcurl.SetUserAgent( "http://kicad-pcb.org" );
|
||||
kcurl.SetHeader( "Accept", "application/zip" );
|
||||
kcurl.SetFollowRedirects( true );
|
||||
|
||||
try
|
||||
{
|
||||
ostringstream os;
|
||||
|
||||
h.open( zip_url ); // only one file, therefore do it synchronously.
|
||||
os << &h;
|
||||
|
||||
// Keep zip file byte image in RAM. That plus the MODULE_MAP will constitute
|
||||
// the cache. We don't cache the MODULEs per se, we parse those as needed from
|
||||
// this zip file image.
|
||||
m_zip_image = os.str();
|
||||
|
||||
// 4 lines, using SSL, top that.
|
||||
kcurl.Perform();
|
||||
m_zip_image = kcurl.GetBuffer();
|
||||
}
|
||||
catch( const boost::system::system_error& e )
|
||||
catch( const IO_ERROR& ioe )
|
||||
{
|
||||
// https "GET" has faild, report this to API caller.
|
||||
// https "GET" has failed, report this to API caller.
|
||||
// Note: kcurl.Perform() does not return an error if the file to download is not found
|
||||
static const char errorcmd[] = "http GET command failed"; // Do not translate this message
|
||||
|
||||
UTF8 fmt( _( "%s\nCannot get/download Zip archive: '%s'\nfor library path: '%s'.\nReason: '%s'" ) );
|
||||
|
||||
string msg = StrPrintf( fmt.c_str(),
|
||||
errorcmd,
|
||||
// Report both secret zip_url and Lib Path, to user. The secret
|
||||
// zip_url may go bad at some point in future if github changes
|
||||
// their server architecture. Then fix repoURL_zipURL() to reflect
|
||||
// new architecture.
|
||||
zip_url.c_str(), TO_UTF8( aRepoURL ),
|
||||
e.what() );
|
||||
|
||||
THROW_IO_ERROR( msg );
|
||||
}
|
||||
catch( const exception& exc )
|
||||
{
|
||||
UTF8 error( _( "Exception '%s' in avhttp while open()-ing URI:'%s'" ) );
|
||||
|
||||
string msg = StrPrintf( error.c_str(), exc.what(), zip_url.c_str() );
|
||||
THROW_IO_ERROR( msg );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// This GITHUB_GETLIBLIST method should not be here, but in github_getliblist.cpp !
|
||||
// However it is here just because we need to include <avhttp.hpp> to compile it.
|
||||
// and when we include avhttp in two .cpp files, the link fails because it detects duplicate
|
||||
// avhttp functions.
|
||||
// So until it is fixed, this code is here.
|
||||
bool GITHUB_GETLIBLIST::remote_get_json( std::string* aFullURLCommand, wxString* aMsgError )
|
||||
{
|
||||
boost::asio::io_service io;
|
||||
avhttp::http_stream h( io );
|
||||
avhttp::request_opts options;
|
||||
|
||||
|
||||
options.insert( "Accept", m_option_string );
|
||||
options.insert( "User-Agent", "http://kicad-pcb.org" ); // THAT WOULD BE ME.
|
||||
h.request_options( options );
|
||||
|
||||
try
|
||||
{
|
||||
std::ostringstream os;
|
||||
|
||||
h.open( *aFullURLCommand ); // only one file, therefore do it synchronously.
|
||||
os << &h;
|
||||
|
||||
// Keep downloaded text file image in RAM.
|
||||
m_image = os.str();
|
||||
|
||||
// 4 lines, using SSL, top that.
|
||||
}
|
||||
catch( boost::system::system_error& e )
|
||||
{
|
||||
// https "GET" has faild, report this to API caller.
|
||||
static const char errorcmd[] = "https GET command failed"; // Do not translate this message
|
||||
|
||||
UTF8 fmt( _( "%s\nCannot get/download data from: '%s'\nReason: '%s'" ) );
|
||||
|
||||
std::string msg = StrPrintf( fmt.c_str(),
|
||||
errorcmd,
|
||||
// Report secret list_url to user. The secret
|
||||
// list_url may go bad at some point in future if github changes
|
||||
// their server architecture. Then fix repoURL_zipURL() to reflect
|
||||
// new architecture.
|
||||
aFullURLCommand->c_str(), e.what() );
|
||||
errorcmd,
|
||||
zip_url.c_str(),
|
||||
TO_UTF8( aRepoURL ),
|
||||
TO_UTF8( ioe.errorText )
|
||||
);
|
||||
|
||||
if( aMsgError )
|
||||
{
|
||||
*aMsgError = FROM_UTF8( msg.c_str() );
|
||||
return false;
|
||||
}
|
||||
THROW_IO_ERROR( msg );
|
||||
}
|
||||
|
||||
return true;
|
||||
// If the zip archive is not existing, the received data is "Not Found" or "404: Not Found",
|
||||
// and no error is returned by kcurl.Perform().
|
||||
if( ( m_zip_image.compare( 0, 9, "Not Found", 9 ) == 0 ) ||
|
||||
( m_zip_image.compare( 0, 14, "404: Not Found", 14 ) == 0 ) )
|
||||
{
|
||||
UTF8 fmt( _( "Cannot download library '%s'.\nThe library does not exist on the server" ) );
|
||||
std::string msg = StrPrintf( fmt.c_str(), TO_UTF8( aRepoURL ) );
|
||||
|
||||
THROW_IO_ERROR( msg );
|
||||
}
|
||||
}
|
||||
|
||||
#if 0 && defined(STANDALONE)
|
||||
@@ -657,7 +577,7 @@ int main( int argc, char** argv )
|
||||
try
|
||||
{
|
||||
wxArrayString fps = gh.FootprintEnumerate(
|
||||
wxT( "https://github.com/liftoff-sr/pretty_footprints" ),
|
||||
"https://github.com/liftoff-sr/pretty_footprints",
|
||||
NULL
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user