1
0
Fork 0

Initial work for a PKG http service

This commit is contained in:
Torsten Dreyer 2015-02-16 22:58:17 +01:00
parent 5349d3367f
commit ae91b9cede
5 changed files with 278 additions and 1 deletions

View file

@ -146,7 +146,7 @@ void FGHTTPClient::init()
// always show this message
SG_LOG(SG_GENERAL, SG_ALERT, "default catalog not found, installing...");
pkg::Catalog::createFromUrl(packageRoot,
"http://fgfs.goneabitbursar.com/pkg/" FLIGHTGEAR_VERSION "/default-catalog.xml");
"http://localhost:8080/default-catalog.xml");
}
// start a refresh now

View file

@ -5,6 +5,7 @@ set(SOURCES
ScreenshotUriHandler.cxx
PropertyUriHandler.cxx
JsonUriHandler.cxx
PkgUriHandler.cxx
RunUriHandler.cxx
NavdbUriHandler.cxx
PropertyChangeWebsocket.cxx
@ -18,6 +19,7 @@ set(HEADERS
ScreenshotUriHandler.hxx
PropertyUriHandler.hxx
JsonUriHandler.hxx
PkgUriHandler.hxx
RunUriHandler.hxx
NavdbUriHandler.hxx
HTTPRequest.hxx

View file

@ -0,0 +1,227 @@
// PkgUriHandler.cxx -- service for the package system
//
// Written by Torsten Dreyer, started February 2015.
//
// Copyright (C) 2014 Torsten Dreyer
//
// 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; either version 2 of the
// License, or (at your option) any later version.
//
// 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 "PkgUriHandler.hxx"
#include <3rdparty/cjson/cJSON.h>
#include <simgear/package/Root.hxx>
#include <simgear/package/Catalog.hxx>
#include <simgear/package/Delegate.hxx>
#include <simgear/package/Install.hxx>
#include <simgear/package/Package.hxx>
#include <Main/fg_props.hxx>
using std::string;
namespace flightgear {
namespace http {
/*
url: /pkg/command/args
Examples:
/pkg/path
Input:
{
command: "command",
args: {
}
}
Output:
{
}
*/
static cJSON * StringListToJson( const string_list & l )
{
cJSON * jsonArray = cJSON_CreateArray();
for( string_list::const_iterator it = l.begin(); it != l.end(); ++it )
cJSON_AddItemToArray(jsonArray, cJSON_CreateString((*it).c_str()) );
return jsonArray;
}
static cJSON * PackageToJson( simgear::pkg::Package * p )
{
cJSON * json = cJSON_CreateObject();
if( p ) {
cJSON_AddItemToObject(json, "id", cJSON_CreateString( p->id().c_str() ));
cJSON_AddItemToObject(json, "name", cJSON_CreateString( p->name().c_str() ));
cJSON_AddItemToObject(json, "description", cJSON_CreateString( p->description().c_str() ));
cJSON_AddItemToObject(json, "installed", cJSON_CreateBool( p->isInstalled() ));
cJSON_AddItemToObject(json, "thumbnails", StringListToJson( p->thumbnailUrls() ));
cJSON_AddItemToObject(json, "variants", StringListToJson( p->variants() ));
cJSON_AddItemToObject(json, "revision", cJSON_CreateNumber( p->revision() ));
cJSON_AddItemToObject(json, "fileSize", cJSON_CreateNumber( p->fileSizeBytes() ));
cJSON_AddItemToObject(json, "author", cJSON_CreateString( p->getLocalisedProp("author").c_str() ));
cJSON_AddItemToObject(json, "ratingFdm", cJSON_CreateString( p->getLocalisedProp("rating/FDM").c_str() ));
cJSON_AddItemToObject(json, "ratingCockpit", cJSON_CreateString( p->getLocalisedProp("rating/cockpit").c_str() ));
cJSON_AddItemToObject(json, "ratingModel", cJSON_CreateString( p->getLocalisedProp("rating/model").c_str() ));
cJSON_AddItemToObject(json, "ratingSystems", cJSON_CreateString( p->getLocalisedProp("rating/systems").c_str() ));
}
return json;
}
static cJSON * PackageListToJson( const simgear::pkg::PackageList & l )
{
cJSON * jsonArray = cJSON_CreateArray();
for( simgear::pkg::PackageList::const_iterator it = l.begin(); it != l.end(); ++it ) {
cJSON_AddItemToArray(jsonArray, PackageToJson(*it) );
}
return jsonArray;
}
static cJSON * CatalogToJson( simgear::pkg::Catalog * c )
{
cJSON * json = cJSON_CreateObject();
if( c ) {
cJSON_AddItemToObject(json, "id", cJSON_CreateString( c->id().c_str() ));
cJSON_AddItemToObject(json, "installRoot", cJSON_CreateString( c->installRoot().str().c_str() ));
cJSON_AddItemToObject(json, "url", cJSON_CreateString( c->url().c_str() ));
cJSON_AddItemToObject(json, "description", cJSON_CreateString( c->description().c_str() ));
cJSON_AddItemToObject(json, "packages", PackageListToJson(c->packages()) );
cJSON_AddItemToObject(json, "needingUpdate", PackageListToJson(c->packagesNeedingUpdate()) );
cJSON_AddItemToObject(json, "installed", PackageListToJson(c->installedPackages()) );
}
return json;
}
static string PackageRootCommand( simgear::pkg::Root* packageRoot, const string & command, const string & args )
{
cJSON * json = cJSON_CreateObject();
if( command == "path" ) {
cJSON_AddItemToObject(json, "path", cJSON_CreateString( packageRoot->path().str().c_str() ));
} else if( command == "version" ) {
cJSON_AddItemToObject(json, "version", cJSON_CreateString( packageRoot->catalogVersion().c_str() ));
} else if( command == "refresh" ) {
packageRoot->refresh(true);
cJSON_AddItemToObject(json, "refresh", cJSON_CreateString( "OK" ));
} else if( command == "catalogs" ) {
cJSON * jsonArray = cJSON_CreateArray();
simgear::pkg::CatalogList catalogList = packageRoot->catalogs();
for( simgear::pkg::CatalogList::iterator it = catalogList.begin(); it != catalogList.end(); ++it ) {
cJSON_AddItemToArray(jsonArray, CatalogToJson(*it) );
}
cJSON_AddItemToObject(json, "catalogs", jsonArray );
} else if( command == "packageById" ) {
simgear::pkg::PackageRef p = packageRoot->getPackageById(args);
cJSON_AddItemToObject(json, "package", PackageToJson( p ));
} else if( command == "catalogById" ) {
simgear::pkg::CatalogRef p = packageRoot->getCatalogById(args);
cJSON_AddItemToObject(json, "catalog", CatalogToJson( p ));
} else if( command == "search" ) {
SGPropertyNode_ptr query(new SGPropertyNode);
simgear::pkg::PackageList packageList = packageRoot->packagesMatching(query);
cJSON_AddItemToObject(json, "packages", PackageListToJson(packageList) );
} else if( command == "install" ) {
simgear::pkg::PackageRef package = packageRoot->getPackageById(args);
if( NULL == package ) {
SG_LOG(SG_NETWORK,SG_WARN,"Can't install package '" << args << "', package not found" );
cJSON_Delete( json );
return string("");
}
package->existingInstall();
} else {
SG_LOG( SG_NETWORK,SG_WARN, "Unhandled pkg command : '" << command << "'" );
cJSON_Delete( json );
return string("");
}
char * jsonString = cJSON_PrintUnformatted( json );
string reply(jsonString);
free( jsonString );
cJSON_Delete( json );
return reply;
}
static string findCommand( const string & uri, string & outArgs )
{
size_t n = uri.find_first_of('/');
if( n == string::npos ) outArgs = string("");
else outArgs = uri.substr( n+1 );
return uri.substr( 0, n );
}
bool PkgUriHandler::handleRequest( const HTTPRequest & request, HTTPResponse & response, Connection * connection )
{
response.Header["Content-Type"] = "application/json; charset=UTF-8";
response.Header["Access-Control-Allow-Origin"] = "*";
response.Header["Access-Control-Allow-Methods"] = "OPTIONS, GET, POST";
response.Header["Access-Control-Allow-Headers"] = "Origin, Accept, Content-Type, X-Requested-With, X-CSRF-Token";
if( request.Method == "OPTIONS" ){
return true; // OPTIONS only needs the headers
}
simgear::pkg::Root* packageRoot = globals->packageRoot();
if( NULL == packageRoot ) {
SG_LOG( SG_NETWORK,SG_WARN, "NO PackageRoot" );
response.StatusCode = 500;
response.Content = "{}";
return true;
}
string argString;
string command = findCommand( string(request.Uri).substr(getUri().size()), argString );
SG_LOG(SG_NETWORK,SG_INFO, "Request is for command '" << command << "' with arg='" << argString << "'" );
if( request.Method == "GET" ){
} else if( request.Method == "POST" ) {
} else {
SG_LOG(SG_NETWORK,SG_INFO, "PkgUriHandler: invalid request method '" << request.Method << "'" );
response.Header["Allow"] = "OPTIONS, GET, POST";
response.StatusCode = 405;
response.Content = "{}";
return true;
}
response.Content = PackageRootCommand( packageRoot, command, argString );
if( response.Content.empty() ) {
response.StatusCode = 404;
response.Content = "{}";
}
return true;
}
} // namespace http
} // namespace flightgear

View file

@ -0,0 +1,40 @@
// PkgUriHandler.hxx -- service for the package system
//
// Written by Torsten Dreyer, started February 2015.
//
// Copyright (C) 2014 Torsten Dreyer
//
// 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; either version 2 of the
// License, or (at your option) any later version.
//
// 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.
#ifndef __FG_PKG_URI_HANDLER_HXX
#define __FG_PKG_URI_HANDLER_HXX
#include "urihandler.hxx"
#include <simgear/props/props.hxx>
namespace flightgear {
namespace http {
class PkgUriHandler : public URIHandler {
public:
PkgUriHandler( const char * uri = "/pkg/" ) : URIHandler( uri ) {}
virtual bool handleRequest( const HTTPRequest & request, HTTPResponse & response, Connection * connection );
private:
};
} // namespace http
} // namespace flightgear
#endif //#define __FG_PKG_URI_HANDLER_HXX

View file

@ -24,6 +24,7 @@
#include "ScreenshotUriHandler.hxx"
#include "PropertyUriHandler.hxx"
#include "JsonUriHandler.hxx"
#include "PkgUriHandler.hxx"
#include "RunUriHandler.hxx"
#include "NavdbUriHandler.hxx"
#include "PropertyChangeObserver.hxx"
@ -451,6 +452,13 @@ void MongooseHttpd::init()
_uriHandler.push_back(new flightgear::http::JsonUriHandler(uri));
}
//#ifdef ENABLE_PACKAGE_SYSTEM
if ((uri = n->getStringValue("pkg"))[0] != 0) {
SG_LOG(SG_NETWORK, SG_INFO, "httpd: adding pkg uri handler at " << uri);
_uriHandler.push_back(new flightgear::http::PkgUriHandler(uri));
}
//#endif
if ((uri = n->getStringValue("run"))[0] != 0) {
SG_LOG(SG_NETWORK, SG_INFO, "httpd: adding run uri handler at " << uri);
_uriHandler.push_back(new flightgear::http::RunUriHandler(uri));