29 #include <oatpp/web/server/handler/ErrorHandler.hpp>
30 #include <oatpp/web/server/interceptor/RequestInterceptor.hpp>
33 #define SWAGGER_ROOT_PATH "/api-docs"
34 #define SWAGGER_UI_PATH "/ui"
36 #include <ccut/Thread.hpp>
37 #include <oatpp-swagger/AsyncController.hpp>
38 #include <oatpp-swagger/Model.hpp>
39 #include <oatpp-swagger/Resources.hpp>
40 #include <oatpp/core/macro/component.hpp>
41 #include <oatpp/network/Server.hpp>
42 #include <oatpp/network/tcp/server/ConnectionProvider.hpp>
43 #include <oatpp/parser/json/mapping/ObjectMapper.hpp>
44 #include <oatpp/web/server/AsyncHttpConnectionHandler.hpp>
45 #include <oatpp/web/server/HttpConnectionHandler.hpp>
47 #include "../MotionController.hpp"
48 #include "ApiController.hpp"
49 #include "AsyncAliasController.hpp"
50 #include "AsyncApiController.hpp"
51 #include "AsyncAxisController.hpp"
52 #include "AsyncAxisPositionMonitorController.hpp"
53 #include "AsyncConfigController.hpp"
54 #include "AsyncGpioController.hpp"
55 #include "AsyncPositionController.hpp"
56 #include "AsyncTriggerController.hpp"
57 #include "AsyncTypesController.hpp"
58 #include "Environment.hpp"
59 #include "SmcController.hpp"
62 #include "favicon-16x16.png.cpp"
63 #include "favicon-32x32.png.cpp"
64 #include "index.html.cpp"
65 #include "oauth2-redirect.html.cpp"
66 #include "swagger-ui-bundle.js.cpp"
67 #include "swagger-ui-es-bundle-core.js.cpp"
68 #include "swagger-ui-es-bundle.js.cpp"
69 #include "swagger-ui-standalone-preset.js.cpp"
70 #include "swagger-ui.css.cpp"
71 #include "swagger-ui.js.cpp"
73 #define ENV_PORT "DEBUG_PORT"
74 #define ENV_ADDR "DEBUG_ADDR"
76 #define ENV_HOSTNAME "DEBUG_HOSTNAME"
78 namespace http = oatpp::web::protocol::http;
84 public oatpp::web::server::interceptor::RequestInterceptor
87 std::shared_ptr<OutgoingResponse> intercept(
88 const std::shared_ptr<IncomingRequest> &request)
override
90 const auto &line = request->getStartingLine();
91 OATPP_LOGV(
"req",
"%s %s", line.method.std_str().c_str(),
92 line.path.std_str().c_str());
94 if (line.method ==
"OPTIONS")
95 return OutgoingResponse::createShared(http::Status::CODE_204,
103 public oatpp::web::server::interceptor::ResponseInterceptor
106 std::shared_ptr<OutgoingResponse> intercept(
107 const std::shared_ptr<IncomingRequest> &request,
108 const std::shared_ptr<OutgoingResponse> &response)
override
110 response->putOrReplaceHeader(http::Header::SERVER,
"CERN/MRO");
114 const auto &line = request->getStartingLine();
115 const int32_t code = response->getStatus().code;
118 OATPP_LOGE(
"req",
"%s %s -> %i", line.method.std_str().c_str(),
119 line.path.std_str().c_str(), code);
123 OATPP_LOGV(
"req",
"%s %s -> %i", line.method.std_str().c_str(),
124 line.path.std_str().c_str(), code);
127 if (line.method ==
"OPTIONS")
129 response->putHeaderIfNotExists(http::Header::CORS_METHODS,
130 "GET,PUT,POST,DELETE,OPTIONS");
131 response->putHeaderIfNotExists(http::Header::CORS_MAX_AGE,
136 response->putHeaderIfNotExists(http::Header::CORS_ORIGIN,
"*");
137 response->putHeaderIfNotExists(http::Header::CORS_HEADERS,
"*");
142 class ErrorHandler :
public oatpp::web::server::handler::DefaultErrorHandler
145 using oatpp::web::server::handler::DefaultErrorHandler::handleError;
147 std::shared_ptr<http::outgoing::Response> handleError(
148 const http::Status &status,
149 const oatpp::String &message,
150 const Headers &headers)
override
152 OATPP_LOGE(
"req",
"error: %s", message.getValue(
"").c_str());
153 return DefaultErrorHandler::handleError(status, message, headers);
160 static const oatpp::network::Address &getAddress()
162 const char *addr = getenv(ENV_ADDR);
163 const char *port_str = getenv(ENV_PORT);
164 uint16_t port = (port_str) ? std::stoul(std::string(port_str)) : 8080;
166 static const oatpp::network::Address address = {
167 (addr ? addr :
"0.0.0.0"), port, oatpp::network::Address::IP_4};
175 std::shared_ptr<oatpp::network::ServerConnectionProvider>,
176 serverConnectionProvider)
178 return oatpp::network::tcp::server::ConnectionProvider::createShared(
179 ServerData::getAddress());
187 ([] {
return oatpp::web::server::HttpRouter::createShared(); }());
194 serverConnectionHandler)
196 OATPP_COMPONENT(std::shared_ptr<oatpp::web::server::HttpRouter>,
198 auto ret = oatpp::web::server::AsyncHttpConnectionHandler::createShared(
200 ret->addRequestInterceptor(std::make_shared<RequestInterceptor>());
201 ret->addResponseInterceptor(std::make_shared<ResponseInterceptor>());
202 ret->setErrorHandler(std::make_shared<ErrorHandler>());
213 return oatpp::parser::json::mapping::ObjectMapper::createShared();
219 oatpp::swagger::DocumentInfo::Builder builder;
221 builder.setTitle(
"Motion-Library")
222 .setDescription(
"Motion Library debug interface")
225 const std::string port =
std::to_string(ServerData::getAddress().port);
227 const char *hostname = getenv(ENV_HOSTNAME);
231 std::string(
"http://") + hostname + std::string(
":") + port,
232 "configured server hostname");
237 char hostname[HOST_NAME_MAX + 1];
238 if (gethostname(hostname, HOST_NAME_MAX) == 0)
241 std::string(
"http://") + hostname + std::string(
":") + port,
242 "detected server hostname");
245 builder.addServer(
"http://localhost:" + port,
"server on localhost");
246 return builder.build();
255 auto res = std::make_shared<oatpp::swagger::Resources>(
"/tmp");
256 res->cacheResource(
"favicon-16x16.png", favicon_16x16_png);
257 res->cacheResource(
"favicon-32x32.png", favicon_32x32_png);
258 res->cacheResource(
"index.html", index_html);
259 res->cacheResource(
"oauth2-redirect.html", oauth2_redirect_html);
260 res->cacheResource(
"swagger-ui-bundle.js", swagger_ui_bundle_js);
261 res->cacheResource(
"swagger-ui-bundle.js.map",
"");
262 res->cacheResource(
"swagger-ui-es-bundle-core.js",
263 swagger_ui_es_bundle_core_js);
264 res->cacheResource(
"swagger-ui-es-bundle-core.js.map",
"");
265 res->cacheResource(
"swagger-ui-es-bundle.js", swagger_ui_es_bundle_js);
266 res->cacheResource(
"swagger-ui-es-bundle.js.map",
"");
267 res->cacheResource(
"swagger-ui-standalone-preset.js",
268 swagger_ui_standalone_preset_js);
269 res->cacheResource(
"swagger-ui-standalone-preset.js.map",
"");
270 res->cacheResource(
"swagger-ui.css", swagger_ui_css);
271 res->cacheResource(
"swagger-ui.css.map",
"");
272 res->cacheResource(
"swagger-ui.js", swagger_ui_js);
273 res->cacheResource(
"swagger-ui.js.map",
"");
281 std::unique_lock<std::mutex> lock(m_mutex);
282 m_started.store(
false);
289 OATPP_COMPONENT(std::shared_ptr<oatpp::network::ConnectionHandler>,
290 serverConnectionHandler);
291 serverConnectionHandler->stop();
296 virtual void thread_func()
override;
298 std::list<SmcController::Shared> smcControllers;
299 std::shared_ptr<oatpp::swagger::AsyncController> swaggerController;
300 std::unique_ptr<oatpp::network::Server> server;
303 void ServerData::thread_func()
307 std::shared_ptr<oatpp::network::ServerConnectionProvider>,
309 OATPP_LOGI(
"motion-lib",
"Server running on port %s",
310 connectionProvider->getProperty(
"port").getData());
327 for (
auto c : m_data->smcControllers)
359 m_env = Environment::instance();
360 m_data.reset(
new ServerData);
362 OATPP_COMPONENT(std::shared_ptr<oatpp::web::server::HttpRouter>, router);
374 std::shared_ptr<oatpp::web::server::handler::ErrorHandler> errHdlr{
376 oatpp::web::server::api::Endpoints ep;
377 for (
auto controller : m_data->smcControllers)
379 controller->setErrorHandler(errHdlr);
380 router->addController(controller);
381 ep.append(controller->getEndpoints());
384 m_data->swaggerController = oatpp::swagger::AsyncController::createShared(
386 router->addController(m_data->swaggerController);
389 OATPP_COMPONENT(std::shared_ptr<oatpp::network::ConnectionHandler>,
393 OATPP_COMPONENT(std::shared_ptr<oatpp::network::ServerConnectionProvider>,
398 m_data->server.reset(
399 new oatpp::network::Server(connectionProvider, connectionHandler));
std::shared_ptr< internal::PlatformFactory > getPlatformFactory() const
for internal use and debugging purpose
std::shared_ptr< internal::DeviceStore > getDeviceStore() const
for internal use and debugging purpose
OATPP_CREATE_COMPONENT(std::shared_ptr< oatpp::network::ConnectionHandler >, serverConnectionHandler)([]
Create ConnectionHandler component which uses Router component to route requests.
OATPP_CREATE_COMPONENT(std::shared_ptr< oatpp::data::mapping::ObjectMapper >, apiObjectMapper)([]
Create ObjectMapper component to serialize/deserialize DTOs in Contoller's API.
OATPP_CREATE_COMPONENT(std::shared_ptr< oatpp::swagger::Resources >, swaggerResources)([]
Swagger-Ui Resources (<oatpp-examples>/lib/oatpp-swagger/res)
OATPP_CREATE_COMPONENT(std::shared_ptr< oatpp::web::server::HttpRouter >, httpRouter)([]
Create Router component.
OATPP_CREATE_COMPONENT(std::shared_ptr< oatpp::network::ServerConnectionProvider >, serverConnectionProvider)([]
Create ConnectionProvider component which listens on the port.
void connect(const MotionController &controller)
(re)connect the debug server
const std::string & to_string(Axis::State state)
convert State to string
main motion-lib namespace