Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pistache server URL is not reatcheable after remove and add route #1103

Closed
chorfa007 opened this issue Oct 31, 2022 · 3 comments
Closed

pistache server URL is not reatcheable after remove and add route #1103

chorfa007 opened this issue Oct 31, 2022 · 3 comments

Comments

@chorfa007
Copy link

chorfa007 commented Oct 31, 2022

Dear All,

I would like to implement a server where i add and remove routes dynamically without rebooting server.
Below the example

`#pragma once
#include <pistache/endpoint.h>
#include <pistache/http.h>
#include <pistache/router.h>

#include "rapidjson/document.h"
#include <csignal>
#include <iostream>

using namespace Pistache;
using namespace Rest;
class Server
{
public:
    enum Modes
    {
        mode_1,
        mode_2
    };    
    Server();
    virtual ~Server() = default;
    void SwitchMode();
    void StartServer(Server::Modes mode);
    void StopServer();

private:
    Router router_;
    Router empty_router_;
    std::shared_ptr<Http::Endpoint> endpoint_;
private:
    void SetupRoutes();
    void hello_fun_1_mode_1(const Rest::Request& request, Http::ResponseWriter response);
    void hello_fun_2_mode_1(const Rest::Request& request, Http::ResponseWriter response);
    void hello_fun_1_mode_2(const Rest::Request& request, Http::ResponseWriter response);
    void hello_fun_2_mode_2(const Rest::Request& request, Http::ResponseWriter response);
    Modes system_mode_ = Modes::mode_2;
};
#include "Server.hpp"

using namespace Pistache;
using namespace Rest;
Server::Server()
{
    Port port(9900);
    Pistache::Address addr(Pistache::Ipv4::any(), Pistache::Port(port));
    endpoint_ = std::make_unique<Pistache::Http::Endpoint>(addr);
    auto opts = Pistache::Http::Endpoint::options()
            .threads(2)
            .flags(Pistache::Tcp::Options::ReuseAddr);
    endpoint_->init(opts);
}

void Server::StartServer(Server::Modes mode)
{
    system_mode_ = mode;
    SetupRoutes();
    endpoint_->setHandler(router_.handler());
    endpoint_->serveThreaded();
}

void Server::StopServer()
{
    endpoint_->shutdown();
}

void Server::SetupRoutes()
{
    using namespace Pistache::Rest;
    if (system_mode_ == Modes::mode_1)
    {
        Routes::Get(router_, "/hello_fun_1_mode_1", Routes::bind(&Server::hello_fun_1_mode_1, this));
        Routes::Get(router_, "/hello_fun_2_mode_1", Routes::bind(&Server::hello_fun_2_mode_1, this));
    }
    else
    {
        Routes::Get(router_, "/hello_fun_1_mode_2", Routes::bind(&Server::hello_fun_2_mode_2, this));
        Routes::Get(router_, "/hello_fun_2_mode_2", Routes::bind(&Server::hello_fun_2_mode_2, this));
    }
}

void Server::SwitchMode()
{
    if (system_mode_ == Modes::mode_1)
    {
        std::cout<<"switch to mode_2 mode";
        Routes::Remove(router_, Pistache::Http::Method::Get, "/hello_fun_1_mode_1");
        Routes::Remove(router_, Pistache::Http::Method::Get, "/hello_fun_2_mode_1");
        system_mode_ = Modes::mode_2;
        SetupRoutes();
    }
    else
    {
        std::cout<<"switch to mode_1 mode";
        Routes::Remove(router_, Pistache::Http::Method::Get, "/hello_fun_1_mode_2");
        Routes::Remove(router_, Pistache::Http::Method::Get, "/hello_fun_1_mode_2");
        system_mode_ = Modes::mode_1;
        SetupRoutes();
    }
}

void Server::hello_fun_1_mode_1(const Rest::Request& request, Http::ResponseWriter response)
{
    response.send(Http::Code::Ok, "hello_fun_1_mode_1 !");
}
void Server::hello_fun_2_mode_1(const Rest::Request& request, Http::ResponseWriter response)
{
    response.send(Http::Code::Ok, "hello_fun_2_mode_1 !");
}
void Server::hello_fun_1_mode_2(const Rest::Request& request, Http::ResponseWriter response)
{
    response.send(Http::Code::Ok, "hello_fun_1_mode_2 !");
}
void Server::hello_fun_2_mode_2(const Rest::Request& request, Http::ResponseWriter response)
{
    response.send(Http::Code::Ok, "hello_fun_2_mode_2 !");
}`

Each time i call the function Routes::Remove via Server::SwitchMode(), i end with exception :
terminate called after throwing an instance of 'std::runtime_error'
what(): Requested does not exist.
Aborted (core dumped)
Below the back trace 👍
`(gdb) bt

#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
#1  0x00007ffff7aa2859 in __GI_abort () at abort.c:79
#2  0x00007ffff7d2b911 in ?? () from /lib/x86_64-linux-gnu/libstdc++.so.6
#3  0x00007ffff7d3738c in ?? () from /lib/x86_64-linux-gnu/libstdc++.so.6
#4  0x00007ffff7d373f7 in std::terminate() () from /lib/x86_64-linux-gnu/libstdc++.so.6
#5  0x00007ffff7d376a9 in __cxa_throw () from /lib/x86_64-linux-gnu/libstdc++.so.6
#6  0x00007ffff7efb22e in Pistache::Rest::SegmentTreeNode::removeRoute (this=0x555555574bb0, path=...) at ../src/server/router.cc:233
#7  0x00007ffff7f6b470 in Pistache::Rest::SegmentTreeNode::removeRoute (this=0x5555555748b0, path=...) at /usr/include/c++/9/bits/shared_ptr_base.h:1020
#8  0x00007ffff7f6c928 in Pistache::Rest::Router::removeRoute (this=<optimized out>, method=<optimized out>, resource="/hello_fun_1_mode_2") at ../src/server/router.cc:452
#9  0x00005555555591cb in Server::SwitchMode (this=0x5555555744f0) at /usr/include/c++/9/bits/char_traits.h:300
#10 0x00005555555579d9 in main (argc=<optimized out>, argv=<optimized out>) at /usr/include/c++/9/bits/unique_ptr.h:360
`

The problem is in line 233 file src/server/router.cc.
I would like to know if i' m using the correct syntax Routes::remove ? If no then i guess this can be a possible issue in the pistache server and need to be fixed.

Thanks.

@dennisjenkins75
Copy link
Collaborator

Please edit the above comment to fix the line-wrap on the stack trace.

I agree that being able to edit the routes live would be a really nice feature. If the API is there, then it should work.

The most useful thing to do would be to create a PR (pull request) that adds a (currently crashing) unit test that replicates the above. Someone else can then get your PR onto their development box and dig into the problem.

@chorfa007 chorfa007 changed the title std::remove throwing an instance of 'std::runtime_error' ( Requested does not exist) pistache server URL is not reatcheable after remove and add route Nov 2, 2022
@chorfa007
Copy link
Author

chorfa007 commented Nov 2, 2022

All,
I went deeper into my example and was able to resolve the exception, the root cause was that I deleted a route that does not exist:(
I added extra checks and i have seen that if i start the server with :

  1. URL 1 mode 1
  2. URL 2 mode 1
    Then i perform
  3. REMOVE URL 1 mode 1
  4. REMOVE URL 2 mode 1
  5. Add URL1 mode 2
  6. Add URL1 mode 2

Here i'm excepted that both URL 1 and 2 mode 2 should be reachable which is not the case, so i believe that the issue is here.
The API cannot rebuild the data structure of routes correctly after a dynamisc changes . [It is not taking into account the new route, it is look like the data structure holding routes in the library is cleared and never updataed after calling route::remove)
You can replicate the same with my pull request https://github.com//pull/1105/commits/aae7a4a1b55ee54d93eef167a3f321455af8a4da

Please note that the Router::remove API is not tested as a unit, which may explain why this issue was not detected previously.

All thanks you in advance for your assistance.

@chorfa007
Copy link
Author

To make the route mutable please use
/** * Used for mutable router. Useful if it is required to * add/remove routes at runtime. * \param[in] router Pointer to a (mutable) router. */ explicit RouterHandler(std::shared_ptr<Rest::Router> router);

iso
std::shared_ptr<Private::RouterHandler> handler() const;

Please note that the API is not thread safe, you can refer the example of arghness if need a thread safe API
#1105

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants