rest webservice cplus

Build your own simple RESTful Webservice (C++ Webservice Part 1)

If you ever thought about building a multi-platform system, you should know that a Web Service is an essential part of your system. Instead of duplicating common operations among the devices, like registering an user or retrieving a list of items sorted by price, for example, it’s better to move all those operations to a common Web Service and establish the communication through HTTP requests.

Recently, a class of web services has become pretty popular: The REST web service. REST stands for Representational State Ttransfer. It’s an architectural pattern where the requisitions are totally independent and don’t keep any state on server. (It’s different from a web service that keeps a “session” for the user, for example). Another remarking aspect of the REST is the use of common HTTP methods to implement “CRUD-like” systems.

Web services can be implemented in almost any programming language you wish, though somes are more adequated to this task than others, like PHP or Javascript. When we are talking about programming languages which process HTTP requests, it’s common the use of the term “CGI”, which stands for Common Gateway Interface. So here comes the C++ language: Can it be used as a CGI language? The answer is yes, THOUGH not recommended, and the reason is simple: Taks which could be easily implemented in languages like PHP would be a hell to be done in C++. But sometimes we have no choice. If that’s your case, let’s continue.

First, I’ll assume that you are using Ubuntu with Apache2 installed. For this tutorial, we are going to use the FastCGI++.

The very first step is to install mods on Apache2 to enable support for FastCGI. The mods are: mod_fastcgi and mod_fcgid (Download link: here and here). On Ubuntu, you can simply call:

sudo apt-get install libapache2-mod-fastcgi libapache2-mod-fcgid

Once installed, restart the Apache2 service by calling

sudo service apache2 restart

Now it’s necessary to download and install Boost. You can do it here. Download it from the official website, unpack it and call the following commands on terminal:

./boostrap
sudo ./b2 install

And finally, download FastCGI++ through the link.

The procedure to install it is the default one:

./configure
make
sudo make install

In order to check if everything is working, let’s compile a simple program. Create a new .cpp file named hello_world.cpp and copy/past the following content:

#include <boost/date_time/posix_time/posix_time.hpp>
#include <fstream>
#include <fastcgi++/request.hpp>
#include <fastcgi++/manager.hpp>
void error_log(const char* msg)
{
   using namespace std;
   using namespace boost;
   static ofstream error;
   if(!error.is_open())
   {
      error.open("/tmp/errlog", ios_base::out | ios_base::app);
      error.imbue(locale(error.getloc(), new posix_time::time_facet()));
   }
   error << '[' << posix_time::second_clock::local_time() << "] " << msg << endl;
}
class HelloWorld: public Fastcgipp::Request<wchar_t>
{
   bool response()
   {
      wchar_t russian[]={ 0x041f, 0x0440, 0x0438, 0x0432, 0x0435, 0x0442, 0x0020, 0x043c, 0x0438, 0x0440, 0x0000 };
      wchar_t chinese[]={ 0x4e16, 0x754c, 0x60a8, 0x597d, 0x0000 };
      wchar_t greek[]={ 0x0393, 0x03b5, 0x03b9, 0x03b1, 0x0020, 0x03c3, 0x03b1, 0x03c2, 0x0020, 0x03ba, 0x03cc, 0x03c3, 0x03bc, 0x03bf, 0x0000 };
      wchar_t japanese[]={ 0x4eca, 0x65e5, 0x306f, 0x4e16, 0x754c, 0x0000 };
      wchar_t runic[]={ 0x16ba, 0x16d6, 0x16da, 0x16df, 0x0020, 0x16b9, 0x16df, 0x16c9, 0x16da, 0x16de, 0x0000 };
      out << "Content-Type: text/html; charset=utf-8\r\n\r\n";
      out << "<html><head><meta http-equiv='Content-Type' content='text/html; charset=utf-8' />";
      out << "<title>fastcgi++: Hello World in UTF-8</title></head><body>";
      out << "English: Hello World<br />";
      out << "Russian: " << russian << "<br />";
      out << "Greek: " << greek << "<br />";
      out << "Chinese: " << chinese << "<br />";
      out << "Japanese: " << japanese << "<br />";
      out << "Runic English?: " << runic << "<br />";
      out << "</body></html>";
      err << "Hello apache error log";
      return true;
   }
};
int main()
{
   try
   {
      Fastcgipp::Manager<HelloWorld> fcgi;
      fcgi.handler();
   }
   catch(std::exception& e)
   {
      error_log(e.what());
   }
}

Now compile by calling:

g++ hello_world.cpp -lfastcgipp -lboost_date_time -lboost_system -lboost_thread -o hello_world.fcgi

After compiled, try to execute it. If an error similar to this appear:

hello_world.fcgi: error while loading shared libraries: libfastcgipp.so.2: cannot open shared object file: No such file or directory

You may need to copy the libraries inside /usr/local/lib to /usr/lib. Copy and past the following commands on terminal:

cd /usr/lib
ln -s /usr/local/lib/libboost_* .
ln -s /usr/local/lib/libfast* .

It may solve your problem.

Now create a folder on /var/www/html called “hello_world” and move the executable to there. Now if you try to access the following URL: http://localhost/hello_world/hello_world.fcgi, an error like the following is likely to happen:

You don't have permission to access /hello_world/hello_world.fcgi on this server.

In this case, go to /etc/apache2/ and edit the file apache2.conf, by substituing:

<Directory />
        Options FollowSymLinks
        AllowOverride None
        Require all granted
</Directory>

...

<Directory /var/www/>
        Options Indexes FollowSymLinks
        AllowOverride None
        Require all granted
</Directory>

to

<Directory />
        Options  Indexes FollowSymLinks Includes ExecCGI
        AllowOverride All
        Allow from all
</Directory>

...

<Directory /var/www/>
        Options Indexes FollowSymLinks Includes ExecCGI
        AllowOverride All
        Allow from all
</Directory>

Now restart the Apache2 service by calling

sudo service apache2 restart

and try to access the link again: http://localhost/hello_world/hello_world.fcgi.
A message like that must be displayed:

English: Hello World
Russian: Привет мир
Greek: Γεια σας κόσμο
Chinese: 世界您好
Japanese: 今日は世界
Runic English?: ᚺᛖᛚᛟ ᚹᛟᛉᛚᛞ

Got the message? Excellent! Now we can continue (otherwise either check the previous steps to verify if you didn’t mistake anything or reply with a comment to this tutorial).

Webservice C++: Part 2

Thank you Abner Matheus for helpful article about C++ Webservice.