DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
RestEndpoint.cpp
Go to the documentation of this file.
1
9
10#include "logging/Logging.hpp"
11
12#include <chrono>
13#include <future>
14#include <utility>
15#include <sstream>
16
17using namespace dunedaq::restcmd;
18using namespace Pistache;
19
20void RestEndpoint::init(size_t threads)
21{
22 auto opts = Http::Endpoint::options()
23 .threads(static_cast<int>(threads))
24 .maxRequestSize(15728640) // 15MB
25 .maxResponseSize(1048576) // 1MB
26 .flags(Pistache::Tcp::Options::ReuseAddr)
27 .flags(Pistache::Tcp::Options::ReusePort);
28
29 http_endpoint_->init(opts);
31 http_client_options_ = Http::Client::options().threads(static_cast<int>(threads));
33}
34
36{
37 http_endpoint_->setHandler(router_.handler());
38 http_endpoint_->serveThreaded();
39 port_ = http_endpoint_->getPort();
40 TLOG() << "REST server started on port " << port_;
41}
42
43// void RestEndpoint::serveTask()
44// {
45// }
46
48{
49 http_endpoint_->shutdown();
50 //server_thread_.join();
51 http_client_->shutdown();
52}
53
55{
56 using namespace Rest;
57 Routes::Post(router_, "/command", Routes::bind(&RestEndpoint::handle_route_command, this));
58}
59
60inline void extendHeader(Http::Header::Collection& headers)
61{
62 headers.add<Http::Header::AccessControlAllowOrigin>("*");
63 headers.add<Http::Header::AccessControlAllowMethods>("POST,GET");
64 headers.add<Http::Header::ContentType>(MIME(Text, Plain));
65}
66
67inline
68std::string
69getClientAddress(const Pistache::Rest::Request &request) {
70 const auto xff = request.headers().tryGetRaw("X-Forwarded-For");
71 if (!xff.isEmpty()) {
72 //TODO: Strip of after first comma (to handle chained proxies).
73 return xff.get().value();
74 }
75 return request.address().host();
76}
77
78void RestEndpoint::handle_route_command(const Rest::Request& request, Http::ResponseWriter response)
79{
81 auto addr = request.address();
82 auto headers = request.headers();
83 auto ct = headers.get<Http::Header::ContentType>();
84 if ( ct->mime() != accepted_mime_ ) {
85 auto res = response.send(Http::Code::Not_Acceptable, "Not a JSON command!\n");
86 } else {
87 auto ansport = headers.getRaw("X-Answer-Port"); // RS: FIXME reply using headers
88 auto anshost = headers.tryGetRaw("X-Answer-Host"); // RS: FIXME reply using headers
89 meta.data["ans-port"] = ansport.value();
90 meta.data["ans-host"] = ( !anshost.isEmpty() ? anshost.get().value() : addr.host() );
91 command_callback_(nlohmann::json::parse(request.body()), meta); // RS: FIXME parse errors
92 auto res = response.send(Http::Code::Accepted, "Command received\n");
93 }
94}
95
97{
99 std::ostringstream addrstr;
100 addrstr << meta.data["ans-host"].get<std::string>() << ":" << meta.data["ans-port"].get<std::string>() << "/response";
101 meta.data["cmdid"] = command.id;
102 TLOG() << "Sending POST request to " << addrstr.str();
103
104 nlohmann::json body_json;
105 dunedaq::cmdlib::cmd::to_json(body_json, meta);
106 auto response = http_client_->post(addrstr.str()).body(body_json.dump()).send();
107 response.then(
108 [&](Http::Response response) {
109 TLOG() << "Response code = " << response.code();
110 },
111 [&](std::exception_ptr exc) {
112 // handle response failure
113 try{
114 std::rethrow_exception(exc);
115 }
116 catch (const std::exception &e) {
117 TLOG() << "Exception thrown by Http::Client::post() call: \"" << e.what() << "\"; errno = " << errno;
118 }
119 }
120 );
121 http_client_responses_.push_back(std::move(response));
122}
123
std::string getClientAddress(const Pistache::Rest::Request &request)
void extendHeader(Http::Header::Collection &headers)
Pistache::Rest::Router router_
std::shared_ptr< Pistache::Http::Client > http_client_
void handle_route_command(const Pistache::Rest::Request &, Pistache::Http::ResponseWriter response)
std::shared_ptr< Pistache::Http::Endpoint > http_endpoint_
Pistache::Http::Client::Options http_client_options_
Pistache::Http::Mime::MediaType accepted_mime_
std::function< void(const cmdobj_t &, cmdlib::cmd::CommandReply)> command_callback_
void handleResponseCommand(const cmdobj_t &cmd, cmdlib::cmd::CommandReply &meta)
std::vector< Pistache::Async::Promise< Pistache::Http::Response > > http_client_responses_
#define TLOG(...)
Definition macro.hpp:22
void to_json(data_t &j, const Command &obj)
Definition Nljs.hpp:20
nlohmann::json cmdobj_t