Implement JSON API generation for async API calls

Move JSON helpers to util/rsjson.* for better usability
Implement JSON ostream manipulator to print compact and pretty JSON
Use lambdas for API wrappers, integrate better and avoid namespace
  pollution
Removed experimental JSON API for notify client wrapper, notifications
  can be implemented automatically with moderns async API calls
Implement and automatically expose to JSON API
  RsGxsChannels::turtleSearchRequest(
        const std::string& matchString,
        const std::function<void (const RsGxsGroupSummary&)>& multiCallback,
        std::time_t maxWait )
This commit is contained in:
Gioacchino Mazzurco 2018-08-16 23:34:29 +02:00
parent b7f5d4286f
commit 4b6f751b09
No known key found for this signature in database
GPG key ID: A1FBCA3872E87051
15 changed files with 444 additions and 177 deletions

View file

@ -18,16 +18,19 @@
#include "jsonapi.h"
#include <rapid_json/document.h>
#include <rapid_json/writer.h>
#include <rapid_json/stringbuffer.h>
#include <sstream>
#include <memory>
#include <restbed>
#include "util/rsjson.h"
#include "retroshare/rsgxschannels.h"
// Generated at compile time
#include "jsonapi-wrappers.h"
#include "jsonapi-includes.inl"
JsonApiServer::JsonApiServer(
uint16_t port, const std::function<void(int)> shutdownCallback) :
mPort(port), mShutdownCallback(shutdownCallback), notifyClientWrapper(*this)
mPort(port), mShutdownCallback(shutdownCallback)
{
registerHandler("/jsonApiServer/shutdown",
[this](const std::shared_ptr<rb::Session>)
@ -35,32 +38,16 @@ JsonApiServer::JsonApiServer(
shutdown();
});
registerHandler("/jsonApiServer/notifications",
[this](const std::shared_ptr<rb::Session> session)
{
const auto headers = std::multimap<std::string, std::string>
{
{ "Connection", "keep-alive" },
{ "Cache-Control", "no-cache" },
{ "Content-Type", "text/event-stream" },
};
session->yield(rb::OK, headers,
[this](const std::shared_ptr<rb::Session> session)
{
notifySessions.push_back(session);
} );
} );
// Generated at compile time
#include "jsonapi-register.inl"
#include "jsonapi-wrappers.inl"
}
void JsonApiServer::run()
{
std::shared_ptr<rb::Settings> settings(new rb::Settings);
settings->set_port(mPort);
settings->set_default_header("Connection", "close");
// settings->set_default_header("Connection", "close");
settings->set_default_header("Cache-Control", "no-cache");
mService.start(settings);
}
@ -80,47 +67,3 @@ void JsonApiServer::shutdown(int exitCode)
mService.stop();
mShutdownCallback(exitCode);
}
void JsonApiServer::cleanClosedNotifySessions()
{
notifySessions.erase(
std::remove_if(
notifySessions.begin(), notifySessions.end(),
[](const std::shared_ptr<rb::Session> &s)
{ return s->is_closed(); } ), notifySessions.end());
}
JsonApiServer::NotifyClientWrapper::NotifyClientWrapper(JsonApiServer& parent) :
NotifyClient(), mJsonApiServer(parent)
{
rsNotify->registerNotifyClient(static_cast<NotifyClient*>(this));
}
void JsonApiServer::NotifyClientWrapper::notifyTurtleSearchResult(
uint32_t searchId, const std::list<TurtleFileInfo>& files )
{
mJsonApiServer.cleanClosedNotifySessions();
RsGenericSerializer::SerializeContext cAns;
RsJson& jAns(cAns.mJson);
// serialize parameters and method name to JSON
{
std::string methodName("NotifyClient/notifyTurtleSearchResult");
std::list<TurtleFileInfo> filesCopy(files);
RsGenericSerializer::SerializeContext& ctx(cAns);
RsGenericSerializer::SerializeJob j(RsGenericSerializer::TO_JSON);
RS_SERIAL_PROCESS(methodName);
RS_SERIAL_PROCESS(searchId);
// RS_SERIAL_PROCESS(filesCopy);
}
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
jAns.Accept(writer);
std::string message(buffer.GetString(), buffer.GetSize());
message.insert(0, "data: "); message.append("\n\n");
for(auto session : mJsonApiServer.notifySessions)
session->yield(message);
}

View file

@ -21,7 +21,6 @@
#include <restbed>
#include "util/rsthreads.h"
#include "retroshare/rsnotify.h"
namespace rb = restbed;
@ -70,20 +69,5 @@ private:
uint16_t mPort;
rb::Service mService;
const std::function<void(int)> mShutdownCallback;
std::list<std::shared_ptr<rb::Session> > notifySessions;
void cleanClosedNotifySessions();
struct NotifyClientWrapper : NotifyClient
{
NotifyClientWrapper(JsonApiServer& parent);
void notifyTurtleSearchResult(
uint32_t searchId, const std::list<TurtleFileInfo>& files);
private:
JsonApiServer& mJsonApiServer;
};
NotifyClientWrapper notifyClientWrapper;
};