#pragma once #include #include #include #include #include "imagealgos.h" using namespace Pistache; extern uint8_t pgm_image[64 + img_width * img_height * sizeof(uint16_t)]; extern size_t pgm_image_size; extern std::mutex pgm_image_mtx; class HttpService { public: HttpService(Address addr) : httpEndpoint(std::make_shared(addr)) , desc("Banking API", "0.1") { } void init(size_t thr = 2) { auto opts = Http::Endpoint::options() .threads(static_cast(thr)); httpEndpoint->init(opts); createDescription(); } void start() { router.initFromDescription(desc); Rest::Swagger swagger(desc); swagger .uiPath("/doc") .uiDirectory("/home/user/swagger-ui/dist") .apiPath("/banker-api.json") .serializer(&Rest::Serializer::rapidJson) .install(router); httpEndpoint->setHandler(router.handler()); httpEndpoint->serve(); } private: void createDescription() { desc .info() .license("Apache", "http://www.apache.org/licenses/LICENSE-2.0"); auto backendErrorResponse = desc.response(Http::Code::Internal_Server_Error, "An error occured with the backend"); desc .schemes(Rest::Scheme::Http) .basePath("/v1") .produces(MIME(Application, Json)) .consumes(MIME(Application, Json)); // desc // .route(desc.get("/ready")) // .bind(&Generic::handleReady) // .response(Http::Code::Ok, "Response to the /ready call") // .hide(); auto versionPath = desc.path("/v1"); auto sensorPath = versionPath.path("/sensor"); sensorPath .route(desc.get("/image")) .bind(&HttpService::image, this) .produces(MIME(Image, Png)) .response(Http::Code::Ok, "Image from sensor"); // tmp sensorPath .route(desc.get("/image2")) .bind(&HttpService::image, this) .produces(MIME(Image, Png)) .response(Http::Code::Ok, "Image from sensor"); sensorPath .route(desc.get("/params"), "Retrive sensor parameters") .bind(&HttpService::get_sensorParams, this) .produces(MIME(Application, Plain)) .response(Http::Code::Ok, "Parameter value") .response(backendErrorResponse);; sensorPath .route(desc.get("/:param"), "Retrive sensor parameter") .bind(&HttpService::get_sensorParam, this) .produces(MIME(Application, Json)) .parameter("param", "The name of the parameter to retrieve") .response(Http::Code::Ok, "Parameter value") .response(backendErrorResponse);; sensorPath .route(desc.post("/:param"), "Set sensor parameter") .bind(&HttpService::set_sensorParam, this) .produces(MIME(Application, Plain)) .consumes(MIME(Application, Plain)) .response(Http::Code::Ok, "Setting parameter result"); auto accountsPath = versionPath.path("/accounts"); accountsPath .route(desc.get("/all")) .bind(&HttpService::retrieveAllAccounts, this) .produces(MIME(Application, Json), MIME(Application, Xml)) .response(Http::Code::Ok, "The list of all account"); accountsPath .route(desc.get("/:name"), "Retrieve an account") .bind(&HttpService::retrieveAccount, this) .produces(MIME(Application, Json)) .parameter("name", "The name of the account to retrieve") .response(Http::Code::Ok, "The requested account") .response(backendErrorResponse); accountsPath .route(desc.post("/:name"), "Create an account") .bind(&HttpService::createAccount, this) .produces(MIME(Application, Json)) .consumes(MIME(Application, Json)) .parameter("name", "The name of the account to create") .response(Http::Code::Ok, "The initial state of the account") .response(backendErrorResponse); auto accountPath = accountsPath.path("/:name"); accountPath.parameter("name", "The name of the account to operate on"); accountPath .route(desc.post("/budget"), "Add budget to the account") .bind(&HttpService::creditAccount, this) .produces(MIME(Application, Json)) .response(Http::Code::Ok, "Budget has been added to the account") .response(backendErrorResponse); } void retrieveAllAccounts(const Rest::Request&, Http::ResponseWriter response) { response.send(Http::Code::Ok, "No Account", { Http::Mime::Type::Text, Http::Mime::Subtype::Plain} ); } void retrieveAccount(const Rest::Request&, Http::ResponseWriter response) { response.send(Http::Code::Ok, "The bank is closed, come back later"); } void createAccount(const Rest::Request&, Http::ResponseWriter response) { response.send(Http::Code::Ok, "The bank is closed, come back later"); } void creditAccount(const Rest::Request&, Http::ResponseWriter response) { response.send(Http::Code::Ok, "The bank is closed, come back later"); } void image(const Rest::Request&, Http::ResponseWriter response) { // FIXME: image should be valid std::lock_guard lg(pgm_image_mtx); // char data[pgm_image_size]; // memcpy(data, pgm_image, pgm_image_size); std::cout << "send bytes: " << pgm_image_size << std::endl; auto res = response.send(Http::Code::Ok, (const char*)pgm_image, pgm_image_size, Http::Mime::MediaType { "image/pgm" }); // { Http::Mime::Type::Image, Http::Mime::Subtype::Png }); res.then([](ssize_t bytes) { std::cout << bytes << " bytes have been sent\n"; }, Async::NoExcept); } void get_sensorParam(const Rest::Request&, Http::ResponseWriter response) { response.send(Http::Code::Ok, std::to_string(123)); } void get_sensorParams(const Rest::Request&, Http::ResponseWriter response) { response.send(Http::Code::Ok, std::to_string(123)); } void set_sensorParam(const Rest::Request&, Http::ResponseWriter response) { response.send(Http::Code::Ok, std::to_string(123)); } std::shared_ptr httpEndpoint; Rest::Description desc; Rest::Router router; };