#include "CustomCtrl.h" #include "CustomHeaderFilter.h" #include "DigestAuthFilter.h" #include #include #include #include using namespace drogon; using namespace std::chrono_literals; class A : public DrObjectBase { public: void handle(const HttpRequestPtr &req, std::function &&callback, int p1, const std::string &p2, const std::string &p3, int p4) const { HttpViewData data; data.insert("title", std::string("ApiTest::get")); std::unordered_map para; para["int p1"] = std::to_string(p1); para["string p2"] = p2; para["string p3"] = p3; para["int p4"] = std::to_string(p4); data.insert("parameters", para); auto res = HttpResponse::newHttpViewResponse("ListParaView", data); callback(res); } static void staticHandle( const HttpRequestPtr &req, std::function &&callback, int p1, const std::string &p2, const std::string &p3, int p4) { HttpViewData data; data.insert("title", std::string("ApiTest::get")); std::unordered_map para; para["int p1"] = std::to_string(p1); para["string p2"] = p2; para["string p3"] = p3; para["int p4"] = std::to_string(p4); data.insert("parameters", para); auto res = HttpResponse::newHttpViewResponse("ListParaView", data); callback(res); } }; class B : public DrObjectBase { public: void operator()(const HttpRequestPtr &req, std::function &&callback, int p1, int p2) { HttpViewData data; data.insert("title", std::string("ApiTest::get")); std::unordered_map para; para["p1"] = std::to_string(p1); para["p2"] = std::to_string(p2); data.insert("parameters", para); auto res = HttpResponse::newHttpViewResponse("ListParaView", data); callback(res); } }; class C : public drogon::HttpController { public: METHOD_LIST_BEGIN ADD_METHOD_TO(C::priv, "/priv/resource", Get, "DigestAuthFilter"); METHOD_LIST_END void priv(const HttpRequestPtr &req, std::function &&callback) const { auto resp = HttpResponse::newHttpResponse(); resp->setBody("

private content, only for authenticated users

"); callback(resp); } }; namespace api { namespace v1 { class Test : public HttpController { public: METHOD_LIST_BEGIN METHOD_ADD(Test::get, "get/{2}/{1}", Get); // path is /api/v1/test/get/{arg2}/{arg1} METHOD_ADD(Test::list, "/{2}/info", Get); // path is /api/v1/test/{arg2}/info METHOD_LIST_END void get(const HttpRequestPtr &req, std::function &&callback, int p1, int p2) const { HttpViewData data; data.insert("title", std::string("ApiTest::get")); std::unordered_map para; para["p1"] = std::to_string(p1); para["p2"] = std::to_string(p2); data.insert("parameters", para); auto res = HttpResponse::newHttpViewResponse("ListParaView", data); callback(res); } void list(const HttpRequestPtr &req, std::function &&callback, int p1, int p2) const { HttpViewData data; data.insert("title", std::string("ApiTest::get")); std::unordered_map para; para["p1"] = std::to_string(p1); para["p2"] = std::to_string(p2); data.insert("parameters", para); auto res = HttpResponse::newHttpViewResponse("ListParaView", data); callback(res); } }; } // namespace v1 } // namespace api using namespace std::placeholders; using namespace drogon; namespace drogon { template <> string_view fromRequest(const HttpRequest &req) { return req.body(); } } // namespace drogon /// Some examples in the main function show some common functions of drogon. In /// practice, we don't need such a lengthy main function. int main() { std::cout << banner << std::endl; // app().addListener("::1", 8848); //ipv6 app().addListener("0.0.0.0", 8848); // https if (app().supportSSL()) { drogon::app() .setSSLFiles("server.pem", "server.pem") .addListener("0.0.0.0", 8849, true); } // Class function example app().registerHandler("/api/v1/handle1/{}/{}/?p3={}&p4={}", &A::handle); app().registerHandler( "/api/v1/handle11/{int p1}/{string p2}/?p3={string p3}&p4={int p4}", &A::staticHandle); // Lambda example app().registerHandler( "/api/v1/handle2/{int a}/{float b}", [](const HttpRequestPtr &req, std::function &&callback, int a, // here the `a` parameter is converted from the number 1 // parameter in the path. float b, // here the `b` parameter is converted from the number 2 // parameter in the path. string_view &&body, // here the `body` parameter is converted from // req->as(); const std::shared_ptr &jsonPtr // here the `jsonPtr` parameter is converted from // req->as>(); ) { HttpViewData data; data.insert("title", std::string("ApiTest::get")); std::unordered_map para; para["a"] = std::to_string(a); para["b"] = std::to_string(b); data.insert("parameters", para); auto res = HttpResponse::newHttpViewResponse("ListParaView", data); callback(res); LOG_DEBUG << body.data(); assert(!jsonPtr); }); // Functor example B b; app().registerHandler("/api/v1/handle3/{1}/{2}", b); // API example for std::function A tmp; std::function &&, int, const std::string &, const std::string &, int)> func = std::bind(&A::handle, &tmp, _1, _2, _3, _4, _5, _6); app().registerHandler("/api/v1/handle4/{4:p4}/{3:p3}/{1:p1}", func); app().setDocumentRoot("./"); app().enableSession(60); std::map config_credentials; std::string realm("drogonRealm"); std::string opaque("drogonOpaque"); // Load configuration app().loadConfigFile("config.example.json"); auto &json = app().getCustomConfig(); if (json.empty()) { std::cout << "empty custom config!" << std::endl; } else { if (!json["realm"].empty()) { realm = json["realm"].asString(); } if (!json["opaque"].empty()) { opaque = json["opaque"].asString(); } for (auto &&i : json["credentials"]) { config_credentials[i["user"].asString()] = i["password"].asString(); } } // Install Digest Authentication Filter using custom config credentials, // used by C HttpController (/C/priv/resource) auto auth_filter = std::make_shared(config_credentials, realm, opaque); app().registerFilter(auth_filter); // Install custom controller auto ctrlPtr = std::make_shared("Hi"); app().registerController(ctrlPtr); // Install custom filter auto filterPtr = std::make_shared("custom_header", "yes"); app().registerFilter(filterPtr); app().setIdleConnectionTimeout(30s); // AOP example app().registerBeginningAdvice( []() { LOG_DEBUG << "Event loop is running!"; }); app().registerNewConnectionAdvice([](const trantor::InetAddress &peer, const trantor::InetAddress &local) { LOG_DEBUG << "New connection: " << peer.toIpPort() << "-->" << local.toIpPort(); return true; }); app().registerPreRoutingAdvice([](const drogon::HttpRequestPtr &req, drogon::AdviceCallback &&acb, drogon::AdviceChainCallback &&accb) { LOG_DEBUG << "preRouting1"; accb(); }); app().registerPostRoutingAdvice([](const drogon::HttpRequestPtr &req, drogon::AdviceCallback &&acb, drogon::AdviceChainCallback &&accb) { LOG_DEBUG << "postRouting1"; LOG_DEBUG << "Matched path=" << req->matchedPathPatternData(); for (auto &cookie : req->cookies()) { LOG_DEBUG << "cookie: " << cookie.first << "=" << cookie.second; } accb(); }); app().registerPreHandlingAdvice([](const drogon::HttpRequestPtr &req, drogon::AdviceCallback &&acb, drogon::AdviceChainCallback &&accb) { LOG_DEBUG << "preHandling1"; accb(); }); app().registerPostHandlingAdvice([](const drogon::HttpRequestPtr &, const drogon::HttpResponsePtr &resp) { LOG_DEBUG << "postHandling1"; resp->addHeader("Access-Control-Allow-Origin", "*"); }); app().registerPreRoutingAdvice([](const drogon::HttpRequestPtr &req) { LOG_DEBUG << "preRouting observer"; }); app().registerPostRoutingAdvice([](const drogon::HttpRequestPtr &req) { LOG_DEBUG << "postRouting observer"; }); app().registerPreHandlingAdvice([](const drogon::HttpRequestPtr &req) { LOG_DEBUG << "preHanding observer"; }); app().registerSyncAdvice([](const HttpRequestPtr &req) -> HttpResponsePtr { static const HttpResponsePtr nullResp; if (req->path() == "/plaintext") { auto resp = HttpResponse::newHttpResponse(); resp->setBody("Hello, World!"); resp->setContentTypeCodeAndCustomString( CT_TEXT_PLAIN, "Content-Type: text/plain\r\n"); return resp; } return nullResp; }); // Output information of all handlers auto handlerInfo = app().getHandlersInfo(); for (auto &info : handlerInfo) { std::cout << std::get<0>(info); switch (std::get<1>(info)) { case Get: std::cout << " (GET) "; break; case Post: std::cout << " (POST) "; break; case Delete: std::cout << " (DELETE) "; break; case Put: std::cout << " (PUT) "; break; case Options: std::cout << " (OPTIONS) "; break; case Head: std::cout << " (Head) "; break; case Patch: std::cout << " (PATCH) "; break; default: break; } std::cout << std::get<2>(info) << std::endl; } auto resp = HttpResponse::newFileResponse("index.html"); resp->setExpiredTime(0); app().setCustom404Page(resp); std::cout << "Date: " << std::string{drogon::utils::getHttpFullDate( trantor::Date::now())} << std::endl; app().run(); }