Basics of a plugin

Developing an http service starts with deriving a class from pion::http::plugin_service and implementing the () operator. Then spending time with the two arguments: const pion::http::request_ptr& http_request_ptr and const pion::tcp::connection_ptr& tcp_conn #1. You have all you need to stand up a service. To remain uncomplicated, use the same pion::plugins namepaces.

namespace pion {        // begin namespace pion
namespace plugins {     // begin namespace plugins

In the initialization area of the class definition start with the public pion::http::plugin_service in your EchoService.hpp file

class EchoService :/*initialization area comes right after the colon*/
    public pion::http::plugin_service

and overide the virtual () operator in your EchoService.cpp file within the same namespaces.

void EchoService::operator()(const http::request_ptr& http_request_ptr, const tcp::connection_ptr& tcp_conn)
{
            std::cout<<"Method: "<<http_request_ptr->get_method()<<std::endl;
            std::cout<<"Resource: "<<http_request_ptr->get_resource()<<std::endl;
}

Writing a Response

This example assumes the REST method is a GET. You can return anything with http::response_writer_ptr you want or build the echo service that comes with pion and start it with piond. The key is instantiating a writer bound to the tcp connection, fill it in with some ‘«’ streaming and finally call writer->send()

    // Set Content-type to "text/plain" (plain ascii text)
    http::response_writer_ptr writer(http::response_writer::create(tcp_conn, *http_request_ptr,
                                                            boost::bind(&tcp::connection::finish, tcp_conn)));
    writer->get_response().set_content_type(http::types::CONTENT_TYPE_TEXT);
    

Have different content then change to your type:

  • CONTENT_TYPE_TEXT
  • CONTENT_TYPE_XML
  • CONTENT_TYPE_HTML
  • CONTENT_TYPE_MULTIPART_FORM_DATA
  • CONTENT_TYPE_URLENCODED

or to a MIME matching your content(e.g. “application/json”)

Standing It Up

An important section at the tail of EchoService.cpp after the namespaces close scope tells the pion daemon about the plugin and when you start making your own services imitating it is where you either see it stand up or face quizzical nothing

/// creates new EchoService objects
extern "C" PION_PLUGIN pion::plugins::EchoService *pion_create_EchoService(void)
{
    return new pion::plugins::EchoService();
}

/// destroys EchoService objects
extern "C" PION_PLUGIN void pion_destroy_EchoService(pion::plugins::EchoService *service_ptr)
{
    delete service_ptr;
}

Be sure you replace the word ‘Echo’ throughout the above if your service’s suffix is ‘Service’, usually mirroring the resource you want to endpoint. Get this correct and after that real meaningful errors are likely to occur as you work with your request, connection and writer and you’re in a better position to debug.

$PION_PATH/bin/piond --help
usage:   piond [OPTIONS] RESOURCE WEBSERVICE
         piond [OPTIONS] -c SERVICE_CONFIG_FILE
options: [-ssl PEM_FILE] [-i IP] [-p PORT] [-d PLUGINS_DIR] [-o OPTION=VALUE] [-v]
$PION_PATH/bin/piond -v -p 8080 -d $PION_PATH/share/pion/plugins /echo EchoService

and go to browser uri http://localhost:8080/echo to test and view the returned data/document. When you make your own on linux make sure the service’s shared library is missing the lib prefix by sym linking for example:

ln -sf ./libDescriptionLogicsService.so ./DescriptionLogicsService.so

or the daemon won’t know it.


Note #1: the links to components point to the template X class reference documentation the typedefs like pion::http::request_ptr throughout pion code alias to boost::shared_ptr<X>’s.