pistacheio / pistache

A high-performance REST toolkit written in C++
https://pistacheio.github.io/pistache/
Apache License 2.0
3.16k stars 696 forks source link

Managing routes and endpoint #602

Open nicraMarcin opened 5 years ago

nicraMarcin commented 5 years ago

Hello, I'm new in C++ so I'm asking for your understanding.

1. I try to create routerService to store and manage routes and run threaded server. routerService.h

#pragma once
#include <pistache/router.h>

using namespace Pistache;

class RouterService {
public:
   static Rest::Router router;
    RouterService();
    void setupRoutes();
};

routerService.cpp

#include "mainEndpoint.h"
#include "routerService.h"

RouterService::RouterService() {
    setupRoutes();
}

void RouterService::setupRoutes() {
    Rest::Routes::Get(router, "/", Rest::Routes::bind(&MainEndpoint::doMain, this));

}

mainEndpoint.h

#pragma once

#include "pistache/router.h"
#include "pistache/endpoint.h"

using namespace Pistache;

class MainEndpoint {
public:

    void doMain(const Rest::Request &request, Http::ResponseWriter response);
};

mainEndpont.cpp

#include "user.h"
#include "serializerService.h"
#include "mainEndpoint.h"

void MainEndpoint::doMain(const Pistache::Rest::Request &request, Pistache::Http::ResponseWriter response) {

    User user("admin@admin.com");
    user.setUsername("admin");

    SerializerService serializer;

    std::string data = serializer.serialize(user);
    response.cookies()
            .add(Pistache::Http::Cookie("lang", "pl_PL"));
    response.headers()
            .add<Pistache::Http::Header::Server>("Sandbox server v0.1")
            .add<Pistache::Http::Header::ContentType>(MIME(Application, Json));
    response.send(Pistache::Http::Code::Ok, data);
}

and in main file **sandbox.cpp***

#include <pistache/net.h>
#include <mainEndpoint.h>
#include "Service/routerService.h"

...

    Pistache::Port port(8090);
    int thr = 8;

    Pistache::Address addr(Pistache::Ipv4::any(), port);
    auto opts = Http::Endpoint::options()
            .threads(8);

    RouterService routerService;

    Http::Endpoint server(addr);
    server.init(opts);
    server.setHandler(routerService.router.handler());
    server.serveThreaded();

And I cannot compile this:

====================[ Build | sandbox | Debug ]=================================
/home/marcin/Programs/clion-2019.1.3/bin/cmake/linux/bin/cmake --build /home/marcin/CLionProjects/sandbox/cmake-build-debug --target sandbox -- -j 8
[ 73%] Built target pistache
[ 76%] Building CXX object CMakeFiles/sandbox.dir/src/Service/routerService.cpp.o
In file included from /home/marcin/CLionProjects/sandbox/include/mainEndpoint.h:3,
                 from /home/marcin/CLionProjects/sandbox/src/Service/routerService.cpp:5:
/home/marcin/CLionProjects/sandbox/lib/pistache/src/../include/pistache/router.h: In instantiation of ‘Pistache::Rest::Route::Handler Pistache::Rest::Routes::bind(Result (Cls::*)(Args ...), Obj) [with Result = void; Cls = MainEndpoint; Args = {const Pistache::Rest::Request&, Pistache::Http::ResponseWriter}; Obj = RouterService*; Pistache::Rest::Route::Handler = std::function<Pistache::Rest::Route::Result(Pistache::Rest::Request, Pistache::Http::ResponseWriter)>]’:
/home/marcin/CLionProjects/sandbox/src/Service/routerService.cpp:13:82:   required from here
/home/marcin/CLionProjects/sandbox/lib/pistache/src/../include/pistache/router.h:349:49: error: pointer to member type ‘void (MainEndpoint::)(const Pistache::Rest::Request&, Pistache::Http::ResponseWriter)’ incompatible with object type ‘RouterService’
         #define CALL_MEMBER_FN(obj, pmf)  ((obj)->*(pmf))
                                           ~~~~~~^~~~~~~~~
/home/marcin/CLionProjects/sandbox/lib/pistache/src/../include/pistache/router.h:352:13: note: in expansion of macro ‘CALL_MEMBER_FN’
             CALL_MEMBER_FN(obj, func)(request, std::move(response));
             ^~~~~~~~~~~~~~
In file included from /usr/include/c++/8/regex:56,
                 from /home/marcin/CLionProjects/sandbox/lib/pistache/src/../include/pistache/router.h:9,
                 from /home/marcin/CLionProjects/sandbox/include/mainEndpoint.h:3,
                 from /home/marcin/CLionProjects/sandbox/src/Service/routerService.cpp:5:
/usr/include/c++/8/bits/std_function.h:666:7: error: ‘std::function<_Res(_ArgTypes ...)>::function(_Functor) [with _Functor = Pistache::Rest::Routes::bind(Result (Cls::*)(Args ...), Obj) [with Result = void; Cls = MainEndpoint; Args = {const Pistache::Rest::Request&, Pistache::Http::ResponseWriter}; Obj = RouterService*; Pistache::Rest::Route::Handler = std::function<Pistache::Rest::Route::Result(Pistache::Rest::Request, Pistache::Http::ResponseWriter)>]::<lambda(const Pistache::Rest::Request&, Pistache::Http::ResponseWriter)>; <template-parameter-2-2> = void; <template-parameter-2-3> = void; _Res = Pistache::Rest::Route::Result; _ArgTypes = {Pistache::Rest::Request, Pistache::Http::ResponseWriter}]’, declared using local type ‘Pistache::Rest::Routes::bind(Result (Cls::*)(Args ...), Obj) [with Result = void; Cls = MainEndpoint; Args = {const Pistache::Rest::Request&, Pistache::Http::ResponseWriter}; Obj = RouterService*; Pistache::Rest::Route::Handler = std::function<Pistache::Rest::Route::Result(Pistache::Rest::Request, Pistache::Http::ResponseWriter)>]::<lambda(const Pistache::Rest::Request&, Pistache::Http::ResponseWriter)>’, is used but never defined [-fpermissive]
       function<_Res(_ArgTypes...)>::
       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~

Where I'm making mistake?

  1. To not open another issue I'll allow myself to ask question in this topic, because it is about routing. How can I, if its possible, make routing and endpoints splitted? (similar to routes in symfony4) ? For example. I'd like to have one router service which manage all routes and have several endpoints for seperate storing route path (adminEndpoint for strore /admin, userEndpoint for store /user). In routing service points to correct endpoint: "^/admin" => &adminEndpoint (and in adminEnpoint store rest of this path "/admin/show" etc.) "^user" => &userEndpont (and in userEnpoint rest of this path)

Thanks for advance for this hints.

xinthose commented 4 years ago

I import these header files:

#include <pistache/http.h>
#include <pistache/http_header.h>
#include <pistache/router.h>
#include <pistache/endpoint.h>

and use a shared pointer for my endpoint

Pistache::Rest::Router router;
boost::shared_ptr<Pistache::Http::Endpoint> httpEndpoint;

My initialization then looks like:

Pistache::Address addr(Pistache::Ipv4::any(), Pistache::Port(8080));
httpEndpoint.reset(new Pistache::Http::Endpoint (addr));
auto opts = Pistache::Http::Endpoint::options()
    .threads(1)
    .flags(Pistache::Tcp::Options::ReuseAddr);
httpEndpoint->init(opts);
setup_routes();
httpEndpoint->setHandler(router.handler());
httpEndpoint->serve();  // blocking function

Elsewhere I setup my routes in my own pistache class:

Pistache::Rest::Routes::Get(router, "/check_status/*", Pistache::Rest::Routes::bind(&pistache::check_status, this));

void pistache::check_status (const Pistache::Rest::Request& request, Pistache::Http::ResponseWriter response)
{
    response.headers().add<Pistache::Http::Header::AccessControlAllowOrigin>("*");
        // query MySQL and create json_str with boost::property_tree::ptree pt;
        response.send(Pistache::Http::Code::Ok, json_str);

        return;
}
nicraMarcin commented 4 years ago

Thanks for hint. About my error I've made static method and now works. Rest::Routes::Get(router, "/", Rest::Routes::bind(RootEndpoint::doMain));

nicraMarcin commented 4 years ago

@xinthose Could You give me more detailed example in wich files You declare router and how you access to this pointer in other project files? btw Rest::Router has method addRoute() so isn't better to create new routes with this api instead of using Rest::Routes::XXX?