Tworzenie aplikacji w modelu REST w języku C++ może stać się prostsze z frameworkiem Pistache. Jak go zainstalować? Czytaj dalej!

Pistache C++ REST Framework

Pistache jest całkiem nowym projektem, wydanym na świat trochę ponad rok temu przez Mathieu Stefani z Datacratic. Warto dać mu jednak już teraz szanse. Napisany jest w C++11, jego struktura wydaje się być bardzo przemyślana, a obsługa intuicyjna.

Informacje o frameworku można znaleźć na jego oficjalnej witrynie, a źródła na GitHubie. Nie ma na tą chwilę jednak paczek deb, binarek dla Windows czy innych gotowych do ściągnięcia plików. Pozostaje nam samodzielna kompilacja, która jest raczej prosta, ale opiszę ja poniżej na wypadek gdybyś miał problem z uruchomieniem i przetestowaniem tej biblioteki.

Instalacja

Należy przede wszystkim pobrać źródła frameworka z GitHub. Możesz pobrać paczkę ZIP, ale najwygodniejsze będzie sklonowanie repozytorium:

git clone https://github.com/oktal/pistache.git

Po pobraniu plików należy w katalogu projektu wykonać następujące polecenia:

mkdir build
cd build
cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release ..
make
sudo make install

Jeśli nie chcesz (lub nie możesz) wykonać polecenia make install z prawami superużytkownika możesz podczas konfiguracji podać opcjonalny parametr wskazujący ścieżkę w której chcesz zainstalować bibliotekę:

cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release DCMAKE_INSTALL_PREFIX:PATH=/home/user  ..

cmake może narzekać na brak bibliotek gtest i rapidjson. Są one opcjonalne. Jeśli używasz Debiana to ucieszy Cię pewnie fakt że są gotowe paczki dla tych narzędzi do pobrania z repozytorium. Może kiedyś pistache także trafi do repo Debiana…

Przykładowe wyjście z polecenia konfiguracji wygląda następująco:

$ cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release ..
-- The C compiler identification is GNU 4.9.2
-- The CXX compiler identification is GNU 4.9.2
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Performing Test COMPILER_SUPPORTS_CXX11
-- Performing Test COMPILER_SUPPORTS_CXX11 - Success
-- Performing Test COMPILER_SUPPORTS_CXX0X
-- Performing Test COMPILER_SUPPORTS_CXX0X - Success
CMake Warning at examples/CMakeLists.txt:16 (find_package):
  By not providing "FindRapidJSON.cmake" in CMAKE_MODULE_PATH this project
  has asked CMake to find a package configuration file provided by
  "RapidJSON", but CMake did not find one.

  Could not find a package configuration file provided by "RapidJSON" with
  any of the following names:

    RapidJSONConfig.cmake
    rapidjson-config.cmake

  Add the installation prefix of "RapidJSON" to CMAKE_PREFIX_PATH or set
  "RapidJSON_DIR" to a directory containing one of the above files.  If
  "RapidJSON" provides a separate development package or SDK, be sure it has
  been installed.


-- Could NOT find GTest (missing:  GTEST_LIBRARY GTEST_MAIN_LIBRARY) 
-- Found PythonInterp: /usr/bin/python (found version "2.7.9") 
-- Looking for include file pthread.h
-- Looking for include file pthread.h - found
-- Looking for pthread_create
-- Looking for pthread_create - not found
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE  
-- Configuring done
-- Generating done
-- Build files have been written to: /home/user/pistache/build

a z polecenia budowania tak:

$ make
Scanning dependencies of target net
[  1%] Building CXX object src/CMakeFiles/net.dir/common/tcp.cc.o
[  3%] Building CXX object src/CMakeFiles/net.dir/common/net.cc.o
[  5%] Building CXX object src/CMakeFiles/net.dir/common/description.cc.o
[  7%] Building CXX object src/CMakeFiles/net.dir/common/transport.cc.o
[  9%] Building CXX object src/CMakeFiles/net.dir/common/http_defs.cc.o
[ 11%] Building CXX object src/CMakeFiles/net.dir/common/mime.cc.o
[ 13%] Building CXX object src/CMakeFiles/net.dir/common/reactor.cc.o
[ 15%] Building CXX object src/CMakeFiles/net.dir/common/http_headers.cc.o
[ 17%] Building CXX object src/CMakeFiles/net.dir/common/http_header.cc.o
[ 19%] Building CXX object src/CMakeFiles/net.dir/common/cookie.cc.o
[ 21%] Building CXX object src/CMakeFiles/net.dir/common/timer_pool.cc.o
[ 23%] Building CXX object src/CMakeFiles/net.dir/common/http.cc.o
[ 25%] Building CXX object src/CMakeFiles/net.dir/common/stream.cc.o
[ 26%] Building CXX object src/CMakeFiles/net.dir/common/os.cc.o
[ 28%] Building CXX object src/CMakeFiles/net.dir/common/peer.cc.o
[ 30%] Building CXX object src/CMakeFiles/net.dir/server/listener.cc.o
[ 32%] Building CXX object src/CMakeFiles/net.dir/server/router.cc.o
[ 34%] Building CXX object src/CMakeFiles/net.dir/server/endpoint.cc.o
[ 36%] Building CXX object src/CMakeFiles/net.dir/client/client.cc.o
Linking CXX shared library libnet.so
[ 36%] Built target net
Scanning dependencies of target net_static
[ 38%] Building CXX object src/CMakeFiles/net_static.dir/common/tcp.cc.o
[ 40%] Building CXX object src/CMakeFiles/net_static.dir/common/net.cc.o
[ 42%] Building CXX object src/CMakeFiles/net_static.dir/common/description.cc.o
[ 44%] Building CXX object src/CMakeFiles/net_static.dir/common/transport.cc.o
[ 46%] Building CXX object src/CMakeFiles/net_static.dir/common/http_defs.cc.o
[ 48%] Building CXX object src/CMakeFiles/net_static.dir/common/mime.cc.o
[ 50%] Building CXX object src/CMakeFiles/net_static.dir/common/reactor.cc.o
[ 51%] Building CXX object src/CMakeFiles/net_static.dir/common/http_headers.cc.o
[ 53%] Building CXX object src/CMakeFiles/net_static.dir/common/http_header.cc.o
[ 55%] Building CXX object src/CMakeFiles/net_static.dir/common/cookie.cc.o
[ 57%] Building CXX object src/CMakeFiles/net_static.dir/common/timer_pool.cc.o
[ 59%] Building CXX object src/CMakeFiles/net_static.dir/common/http.cc.o
[ 61%] Building CXX object src/CMakeFiles/net_static.dir/common/stream.cc.o
[ 63%] Building CXX object src/CMakeFiles/net_static.dir/common/os.cc.o
[ 65%] Building CXX object src/CMakeFiles/net_static.dir/common/peer.cc.o
[ 67%] Building CXX object src/CMakeFiles/net_static.dir/server/listener.cc.o
[ 69%] Building CXX object src/CMakeFiles/net_static.dir/server/router.cc.o
[ 71%] Building CXX object src/CMakeFiles/net_static.dir/server/endpoint.cc.o
[ 73%] Building CXX object src/CMakeFiles/net_static.dir/client/client.cc.o
Linking CXX static library libnet_static.a
[ 73%] Built target net_static
Scanning dependencies of target custom_header
[ 75%] Building CXX object examples/CMakeFiles/custom_header.dir/custom_header.cc.o
Linking CXX executable custom_header
[ 75%] Built target custom_header
Scanning dependencies of target hello_server
[ 76%] Building CXX object examples/CMakeFiles/hello_server.dir/hello_server.cc.o
Linking CXX executable hello_server
[ 76%] Built target hello_server
Scanning dependencies of target http_client
[ 78%] Building CXX object examples/CMakeFiles/http_client.dir/http_client.cc.o
Linking CXX executable http_client
[ 78%] Built target http_client
Scanning dependencies of target http_server
[ 80%] Building CXX object examples/CMakeFiles/http_server.dir/http_server.cc.o
Linking CXX executable http_server
[ 80%] Built target http_server
Scanning dependencies of target rest_server
[ 82%] Building CXX object examples/CMakeFiles/rest_server.dir/rest_server.cc.o
Linking CXX executable rest_server
[ 82%] Built target rest_server
Scanning dependencies of target gtest
[ 84%] Building CXX object googletest-release-1.7.0/CMakeFiles/gtest.dir/src/gtest-all.cc.o
Linking CXX static library libgtest.a
[ 84%] Built target gtest
Scanning dependencies of target gtest_main
[ 86%] Building CXX object googletest-release-1.7.0/CMakeFiles/gtest_main.dir/src/gtest_main.cc.o
Linking CXX static library libgtest_main.a
[ 86%] Built target gtest_main
Scanning dependencies of target run_async_test
[ 88%] Building CXX object tests/CMakeFiles/run_async_test.dir/async_test.cc.o
Linking CXX executable run_async_test
[ 88%] Built target run_async_test
Scanning dependencies of target run_cookie_test
[ 90%] Building CXX object tests/CMakeFiles/run_cookie_test.dir/cookie_test.cc.o
Linking CXX executable run_cookie_test
[ 90%] Built target run_cookie_test
Scanning dependencies of target run_headers_test
[ 92%] Building CXX object tests/CMakeFiles/run_headers_test.dir/headers_test.cc.o
Linking CXX executable run_headers_test
[ 92%] Built target run_headers_test
Scanning dependencies of target run_mime_test
[ 94%] Building CXX object tests/CMakeFiles/run_mime_test.dir/mime_test.cc.o
Linking CXX executable run_mime_test
[ 94%] Built target run_mime_test
Scanning dependencies of target run_router_test
[ 96%] Building CXX object tests/CMakeFiles/run_router_test.dir/router_test.cc.o
Linking CXX executable run_router_test
[ 96%] Built target run_router_test
Scanning dependencies of target run_typeid_test
[ 98%] Building CXX object tests/CMakeFiles/run_typeid_test.dir/typeid_test.cc.o
Linking CXX executable run_typeid_test
[ 98%] Built target run_typeid_test
Scanning dependencies of target run_view_test
[100%] Building CXX object tests/CMakeFiles/run_view_test.dir/view_test.cc.o
Linking CXX executable run_view_test
[100%] Built target run_view_test

natomiast z polecenia instalacji tak:

$ make install
[ 36%] Built target net
[ 73%] Built target net_static
[ 75%] Built target custom_header
[ 76%] Built target hello_server
[ 78%] Built target http_client
[ 80%] Built target http_server
[ 82%] Built target rest_server
[ 84%] Built target gtest
[ 86%] Built target gtest_main
[ 88%] Built target run_async_test
[ 90%] Built target run_cookie_test
[ 92%] Built target run_headers_test
[ 94%] Built target run_mime_test
[ 96%] Built target run_router_test
[ 98%] Built target run_typeid_test
[100%] Built target run_view_test
Install the project...
-- Install configuration: "Release"
-- Installing: /usr/local/include/pistache/reactor.h
-- Installing: /usr/local/include/pistache/http_defs.h
-- Installing: /usr/local/include/pistache/stream.h
-- Installing: /usr/local/include/pistache/timer_pool.h
-- Installing: /usr/local/include/pistache/prototype.h
-- Installing: /usr/local/include/pistache/flags.h
-- Installing: /usr/local/include/pistache/endpoint.h
-- Installing: /usr/local/include/pistache/peer.h
-- Installing: /usr/local/include/pistache/http.h
-- Installing: /usr/local/include/pistache/http_headers.h
-- Installing: /usr/local/include/pistache/mime.h
-- Installing: /usr/local/include/pistache/iterator_adapter.h
-- Installing: /usr/local/include/pistache/net.h
-- Installing: /usr/local/include/pistache/common.h
-- Installing: /usr/local/include/pistache/tcp.h
-- Installing: /usr/local/include/pistache/optional.h
-- Installing: /usr/local/include/pistache/http_header.h
-- Installing: /usr/local/include/pistache/view.h
-- Installing: /usr/local/include/pistache/async.h
-- Installing: /usr/local/include/pistache/listener.h
-- Installing: /usr/local/include/pistache/mailbox.h
-- Installing: /usr/local/include/pistache/os.h
-- Installing: /usr/local/include/pistache/cookie.h
-- Installing: /usr/local/include/pistache/typeid.h
-- Installing: /usr/local/include/pistache/client.h
-- Installing: /usr/local/include/pistache/router.h
-- Installing: /usr/local/include/pistache/transport.h
-- Installing: /usr/local/include/pistache/description.h
-- Installing: /usr/local/lib/libnet_static.a
-- Installing: /usr/local/lib/libnet.so

Testowanie

Warto sprawdzić czy wszystko działa tak jak powinno. Ja przetestowałem to lekko modyfikując przykład ze strony frameworka, tworząc kontroler dla żądania przesłania wersji aplikacji DDS. Źródła są do podejrzenia na GitHubie. Z rzeczy na jakie należy zwrócić uwagę podczas kompilacji tych przykładów to by użyć flag -std=c++11 oraz -pthread. Jeśli nie wiesz jak to zrobić podpowiedź znajdziesz w pliku CMakeLists.txt.

#include <cstdlib>

#include "pistache/endpoint.h"

#define DDS_VERSION "0.1.0"

using namespace Net;

class VersionHandler : public Http::Handler {
public:

    HTTP_PROTOTYPE(VersionHandler)

    void onRequest(const Http::Request& request, Http::ResponseWriter response) {
         response.send(Http::Code::Ok, "DDS " DDS_VERSION);
    }
};

int main() {
    Http::listenAndServe<VersionHandler>("*:9080");
}

Po kompilacji otrzymujemy ważący około 600kB serwer HTTP odpowiadający na żądanie GET, do którego napisania, przy pomocy frameworka Pistache, wystarczy jedynie około 15 linii kodu!

Co dalej?

Możliwości frameworka Pistache będę poznawał i prezentował wraz z rozwojem mojej aplikacji konkursowej DDS. Jeśli także dopiero zaczynasz z nim swoją przygodę zapraszam do śledzenia kategorii DSP2017 na moim blogu!