ZeroEQ
0.7.0
ZeroEQ - Zero Event Queue
|
The http::Server implements a zeroeq::Receiver and Sender to serve ZeroBuf objects through a REST interface with JSON payload. It is the evolution of the RESTBridge. Issue 115 tracks the implementation.
namespace servus { /** Interface for serializable objects */ class Serializable { public: struct Data { std::shared_ptr< void* > ptr; size_t size; }; virtual uint128_t getTypeIdentifier() const = 0; virtual void fromBinary( const void* data, const size_t size ); virtual Data toBinary() const; virtual void fromJSON( const std::string& json ); virtual std::string toJSON() const; /** * Register a function called after the object has been updated remotely * (via a subscriber, a http server, loading from file...). * Only one callback is supported at the moment, to deregister the callback, * call this function with a 'nullptr' (or 0) parameter. * * @throw if a DeserializedCallback is already registered and the specified * callback is not 'nullptr' (or 0) */ SERVUS_API void registerDeserializedCallback( const DeserializedCallback& ); /** * Register a function to be called when the serializable object is about * to be serialized. * Only one callback is supported at the moment, to deregister the callback, * call this function with a 'nullptr' (or 0) parameter. * * @throw if a SerializedCallback is already registered and the specified * callback is not 'nullptr' (or 0) */ SERVUS_API void registerSerializeCallback( const SerializeCallback& ); }; } namespace zeroeq { namespace http { class Server : public zeroeq::Receiver { public: // throws if scheme is not empty or tcp explicit Server( const URI& uri ); Server( const URI& uri, Receiver& shared ); /** * Create a new Server when requested. * * The creation and parameters depend on the following command line * parameters: * * --zeroeq-http-server [host][:port]: Enable the server. Optional * parameters configure the web server, running by default on :4020 */ static std::unique_ptr< Server > parse( argc, argv ); static std::unique_ptr< Server > parse( argc, argv, Receiver& shared ); bool handle( servus::Serializable& object ); bool remove( const servus::Serializable& object ); bool handlePUT( servus::Serializable& object ); bool removePUT( const servus::Serializable& object ); bool handleGET( servus::Serializable& object ); bool removeGET( const servus::Serializable& object ); // + 8 overloads with PUTFunc, PUTPayloadFunc, GETFunc }; } }
void livre::Communicator::_setupRESTBridge( const int argc, char** argv ) { _httpServer = zeroeq::http::Server::parse( argc, argv ); if( !_httpServer ) return; subscribers.push_back( _httpServer ); _httpServer.handle( camera, LUT, vrParams ); _httpServer.handleGET( frame ); } class livre::ImageJPEG : public zeroeq::hbp::ImageJPEG { protected: void notifyRequested() final { config->frame(); // redraw before serving the last image }
};
void http::Server::process( zeroeq::detail::Socket& socket ) { zmq_recv, feed to message if message is complete for PUT: _subscribed[ type ].fromJSON( message.body( )) _subscribed[ type ].notifyUpdated() zmq_send( 200/404 ) for GET: _registered[ type ].notifyRequested() zmq_send( 200 + _registered[ type ].toJSON( ))
}
Resolved: Yes, when maintenance becomes a burden.
Removing the generic conversion and emiting specific code in the generator simplifies the implementation significantly. It does however remove the capability to translate to and from JSON in an indepent component which does not have access to the application-specific vocabulary. Today this is only used when the REST bridge is run as a separate process.
To not impose Zerobuf on other applications (e.g. for the visualization web services), the servus::Serializable interface defines the minimal API used by the zeroeq::Subscriber and zeroeq::http::Server, to be implemented by applications (and ZeroBuf).
Resolved: Use httpxx. Fix CMake as needed to integrate as a sub project.
Candidates:
Resolved: Delay, later either use proxy http servers or do a native integration.
The native ZeroEQ integration using a zmq socket enables seamless application integration. For an application, a http::Server behaves as a Subscriber, and they can be integrated in a shared receiver group. Unfortunately there is little prior work on SSL/TLS over zmq stream sockets. The easiest seems to be using a proxy frontend server to shield the (anyways unprotected) applications. The more involved seems to be integrate OpenSSL (or similar) with zmq: