Build Status Build Status Total alerts Join the chat at Join the telegram group at Docker image

English | 简体中文 | 繁體中文


Drogon is a C++14/17-based HTTP application framework. Drogon can be used to easily build various types of web application server programs using C++. Drogon is the name of a dragon in the American TV series "Game of Thrones" that I really like.

Drogon is a cross-platform framework, It supports Linux, macOS, FreeBSD, OpenBSD, HaikuOS, and Windows. Its main features are as follows:

  • Use a non-blocking I/O network lib based on epoll (kqueue under macOS/FreeBSD) to provide high-concurrency, high-performance network IO, please visit the TFB Tests Results for more details;
  • Provide a completely asynchronous programming mode;
  • Support Http1.0/1.1 (server side and client side);
  • Based on template, a simple reflection mechanism is implemented to completely decouple the main program framework, controllers and views.
  • Support cookies and built-in sessions;
  • Support back-end rendering, the controller generates the data to the view to generate the Html page. Views are described by CSP template files, C++ codes are embedded into Html pages through CSP tags. And the drogon command-line tool automatically generates the C++ code files for compilation;
  • Support view page dynamic loading (dynamic compilation and loading at runtime);
  • Provide a convenient and flexible routing solution from the path to the controller handler;
  • Support filter chains to facilitate the execution of unified logic (such as login verification, Http Method constraint verification, etc.) before handling HTTP requests;
  • Support https (based on OpenSSL);
  • Support WebSocket (server side and client side);
  • Support JSON format request and response, very friendly to the Restful API application development;
  • Support file download and upload;
  • Support gzip, brotli compression transmission;
  • Support pipelining;
  • Provide a lightweight command line tool, drogon_ctl, to simplify the creation of various classes in Drogon and the generation of view code;
  • Support non-blocking I/O based asynchronously reading and writing database (PostgreSQL and MySQL(MariaDB) database);
  • Support asynchronously reading and writing sqlite3 database based on thread pool;
  • Support Redis with asynchronous reading and writing;
  • Support ARM Architecture;
  • Provide a convenient lightweight ORM implementation that supports for regular object-to-database bidirectional mapping;
  • Support plugins which can be installed by the configuration file at load time;
  • Support AOP with build-in joinpoints.
  • Support C++ coroutines

A very simple example

Unlike most C++ frameworks, the main program of the drogon application can be kept clean and simple. Drogon uses a few tricks to decouple controllers from the main program. The routing settings of controllers can be done through macros or configuration file.

Below is the main program of a typical drogon application:

#include <drogon/drogon.h>
using namespace drogon;
int main()
         .addListener("", 80)

It can be further simplified by using configuration file as follows:

#include <drogon/drogon.h>
using namespace drogon;
int main()

Drogon provides some interfaces for adding controller logic directly in the main() function, for example, user can register a handler like this in Drogon:

                    [](const HttpRequestPtr& req,
                       std::function<void (const HttpResponsePtr &)> &&callback,
                       const std::string &name)
                        Json::Value json;
                        auto resp=HttpResponse::newHttpJsonResponse(json);

While such interfaces look intuitive, they are not suitable for complex business logic scenarios. Assuming there are tens or even hundreds of handlers that need to be registered in the framework, isn't it a better practice to implement them separately in their respective classes? So unless your logic is very simple, we don't recommend using above interfaces. Instead, we can create an HttpSimpleController as follows:

/// The TestCtrl.h file
#pragma once
#include <drogon/HttpSimpleController.h>
using namespace drogon;
class TestCtrl:public drogon::HttpSimpleController<TestCtrl>
    void asyncHandleHttpRequest(const HttpRequestPtr& req, std::function<void (const HttpResponsePtr &)> &&callback) override;

/// The file
#include "TestCtrl.h"
void TestCtrl::asyncHandleHttpRequest(const HttpRequestPtr& req,
                                      std::function<void (const HttpResponsePtr &)> &&callback)
    //write your application logic here
    auto resp = HttpResponse::newHttpResponse();
    resp->setBody("<p>Hello, world!</p>");

Most of the above programs can be automatically generated by the command line tool drogon_ctl provided by drogon (The command is drogon_ctl create controller TestCtrl). All the user needs to do is add their own business logic. In the example, the controller returns a Hello, world! string when the client accesses the http://ip/test URL.

For JSON format response, we create the controller as follows:

/// The header file
#pragma once
#include <drogon/HttpSimpleController.h>
using namespace drogon;
class JsonCtrl : public drogon::HttpSimpleController<JsonCtrl>
    void asyncHandleHttpRequest(const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> &&callback) override;
    //list path definitions here;
    PATH_ADD("/json", Get);

/// The source file
#include "JsonCtrl.h"
void JsonCtrl::asyncHandleHttpRequest(const HttpRequestPtr &req,
                                      std::function<void(const HttpResponsePtr &)> &&callback)
    Json::Value ret;
    ret["message"] = "Hello, World!";
    auto resp = HttpResponse::newHttpJsonResponse(ret);

Let's go a step further and create a demo RESTful API with the HttpController class, as shown below (Omit the source file):

/// The header file
#pragma once
#include <drogon/HttpController.h>
using namespace drogon;
namespace api
namespace v1
class User : public drogon::HttpController<User>
    //use METHOD_ADD to add your custom processing function here;
    METHOD_ADD(User::getInfo, "/{id}", Get);                  //path is /api/v1/User/{arg1}
    METHOD_ADD(User::getDetailInfo, "/{id}/detailinfo", Get);  //path is /api/v1/User/{arg1}/detailinfo
    METHOD_ADD(User::newUser, "/{name}", Post);                 //path is /api/v1/User/{arg1}
    //your declaration of processing function maybe like this:
    void getInfo(const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> &&callback, int userId) const;
    void getDetailInfo(const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> &&callback, int userId) const;
    void newUser(const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> &&callback, std::string &&userName);
        LOG_DEBUG << "User constructor!";
} // namespace v1
} // namespace api

As you can see, users can use the HttpController to map paths and parameters at the same time. This is a very convenient way to create a RESTful API application.

In addition, you can also find that all handler interfaces are in asynchronous mode, where the response is returned by a callback object. This design is for performance reasons because in asynchronous mode the drogon application can handle a large number of concurrent requests with a small number of threads.

After compiling all of the above source files, we get a very simple web application. This is a good start. For more information, please visit the wiki or DocsForge


Every contribution is welcome. Please refer to the contribution guidelines for more information.

Discussions (13)

Jose 3 days ago 0

Buenas tardes, encantado de saludarte. Soy Jose Quería escribirte porque me ha parecido interesante comentar contigo la posibilidad de que tu negocio aparezca cada mes en periódicos digitales como noticia para posicionar en los primeros lugares de internet, es decir, con artículos reales dentro del periódico que no se marcan como publicidad y que no se borran. La noticia es publicada por más de cuarenta periódicos de gran autoridad para mejorar el posicionamiento de tu web y la reputación.

¿Podrías facilitarme un teléfono para ofrecerte un mes gratuito? Gracias

LesterKak 1 week ago 0

Здравствуйте. Круто что касается заработке.

LesterKak 1 week ago 0

Здравствуйте. Круто о заработке.

notosoMysnoro 2 weeks ago 0

This is so cool. I will follow along the development! especially Mojoheadz records.

MatyMab 2 weeks ago 0

Lolita Girls Fuck Collection loli girl foto video cp pthc

XRumerTest 2 weeks ago 0

Hello. And Bye.

Neuro 1 month ago 0

I was very happy to uncover this great site. I need to to thank you for ones time for this wonderful read!! I definitely really liked every part of it and i also have you saved to fav to look at new information on your site.

XRumerTest 1 month ago 0

Hello. And Bye.

Alberto 3 months ago 0

Hola. ¿Cómo estás? Soy Alberto del Departamento de Prensa. Muchas gracias por atenderme.

He pensado que podría interesarte cómo podemos hacer que tu empresa aparezca en más de 50 periódicos digitales como noticia (No será un anuncio) por una única cuota al mes sin permanencia. Las noticias no se borrarán

Periódicos de gran autoridad mencionarán la web de tu empresa para lograr una mejor reputación y posicionamiento web.

Este servicio incluye tanto la redacción de la noticia como el análisis de las palabras clave.

Si pudieras proporcionarme un teléfono, me encantaría programar una llamada para hablar contigo, resolver cualquier duda sin compromiso y explicar cómo puedes disfrutar del mes gratuito sin permanencia.

¡Muchas gracias!

DeprexLeciva 6 months ago 0

Does your blog have a contact page? I'm having trouble locating it but, I'd like to shoot you an email. I've got some creative ideas for your blog you might be interested in hearing. Either way, great blog and I look forward to seeing it develop over time.

JosephHasia 10 months ago 0

I just want to say thank you for this great website. I found a solution here on for my issue.

Larry 1 year ago 3
  • Situation: I am trying to bind a simple example software with drogon as interface, and torch is involved as core ML function.
  • Expectation: compile pass and work as expected.
  • Result: link failure with following error
/usr/bin/c++ -D_GLIBCXX_USE_CXX11_ABI=0 CMakeFiles/CppModelServ.dir/ CMakeFiles/CppModelServ.dir/controllers/ -o CppModelServ -Wl,-rpath,/usr/local/libtorch/lib:/usr/local/cuda/lib64/stubs:/usr/local/cuda/lib64 /usr/local/lib/libdrogon.a /usr/local/libtorch/lib/ /usr/local/libtorch/lib/ /usr/local/libtorch/lib/libkineto.a /usr/local/cuda/lib64/stubs/ /usr/local/cuda/lib64/ /usr/local/cuda/lib64/ /usr/local/cuda/lib64/ /usr/local/libtorch/lib/ /usr/local/lib/libtrantor.a -ldl -lstdc++fs /usr/lib/x86_64-linux-gnu/ /usr/lib/x86_64-linux-gnu/ /usr/lib/x86_64-linux-gnu/ /usr/lib/x86_64-linux-gnu/ /usr/lib/x86_64-linux-gnu/ -lpthread -Wl,--no-as-needed,"/usr/local/libtorch/lib/" -Wl,--as-needed -Wl,--no-as-needed,"/usr/local/libtorch/lib/" -Wl,--as-needed /usr/local/libtorch/lib/ /usr/local/libtorch/lib/ /usr/local/cuda/lib64/ /usr/local/cuda/lib64/ /usr/local/cuda/lib64/ /usr/lib/x86_64-linux-gnu/ -Wl,--no-as-needed,"/usr/local/libtorch/lib/" -Wl,--as-needed /usr/local/cuda/lib64/ /usr/local/cuda/lib64/ /usr/bin/ld: CMakeFiles/CppModelServ.dir/ in function `std::enable_if<std::is_default_constructible<drogon::plugin::AccessLogger>::value, void>::type drogon::DrObject<drogon::plugin::AccessLogger>::DrAllocator::registerClass<drogon::plugin::AccessLogger>()':[_ZN6drogon8DrObjectINS_6plugin12AccessLoggerEE11DrAllocator13registerClassIS2_EENSt9enable_ifIXsrSt24is_default_constructibleIT_E5valueEvE4typeEv]+0x46): undefined reference to `drogon::DrClassMap::registerClass(std::string const&, std::function<drogon::DrObjectBase* ()> const&)' /usr/bin/ld: CMakeFiles/CppModelServ.dir/ in function `std::enable_if<std::is_default_constructible<drogon::plugin::SecureSSLRedirector>::value, void>::type drogon::DrObject<drogon::plugin::SecureSSLRedirector>::DrAllocator::registerClass<drogon::plugin::SecureSSLRedirector>()':[_ZN6drogon8DrObjectINS_6plugin19SecureSSLRedirectorEE11DrAllocator13registerClassIS2_EENSt9enable_ifIXsrSt24is_default_constructibleIT_E5valueEvE4typeEv]+0x46): undefined reference to `drogon::DrClassMap::registerClass(std::string const&, std::function<drogon::DrObjectBase* ()> const&)' /usr/bin/ld: CMakeFiles/CppModelServ.dir/ in function `std::enable_if<std::is_default_constructible<drogon::NotFound>::value, void>::type drogon::DrObject<drogon::NotFound>::DrAllocator::registerClass<drogon::NotFound>()':[_ZN6drogon8DrObjectINS_8NotFoundEE11DrAllocator13registerClassIS1_EENSt9enable_ifIXsrSt24is_default_constructibleIT_E5valueEvE4typeEv]+0x46): undefined reference to `drogon::DrClassMap::registerClass(std::string const&, std::function<drogon::DrObjectBase* ()> const&)' /usr/bin/ld: CMakeFiles/CppModelServ.dir/ in function `std::enable_if<std::is_default_constructible<drogon::LocalHostFilter>::value, void>::type drogon::DrObject<drogon::LocalHostFilter>::DrAllocator::registerClass<drogon::LocalHostFilter>()':[_ZN6drogon8DrObjectINS_15LocalHostFilterEE11DrAllocator13registerClassIS1_EENSt9enable_ifIXsrSt24is_default_constructibleIT_E5valueEvE4typeEv]+0x46): undefined reference to `drogon::DrClassMap::registerClass(std::string const&, std::function<drogon::DrObjectBase* ()> const&)' /usr/bin/ld: CMakeFiles/CppModelServ.dir/ in function `std::enable_if<std::is_default_constructible<drogon::IntranetIpFilter>::value, void>::type drogon::DrObject<drogon::IntranetIpFilter>::DrAllocator::registerClass<drogon::IntranetIpFilter>()':[_ZN6drogon8DrObjectINS_16IntranetIpFilterEE11DrAllocator13registerClassIS1_EENSt9enable_ifIXsrSt24is_default_constructibleIT_E5valueEvE4typeEv]+0x46): undefined reference to `drogon::DrClassMap::registerClass(std::string const&, std::function<drogon::DrObjectBase* ()> const&)' /usr/bin/ld: CMakeFiles/CppModelServ.dir/controllers/ in function `MmsCtrl::get(std::shared_ptr<drogon::HttpRequest> const&, std::function<void (std::shared_ptr<drogon::HttpResponse> const&)>&&, std::string) const': undefined reference to `Json::Value::Value(std::string const&)' /usr/bin/ld: undefined reference to `Json::Value::Value(std::string const&)' /usr/bin/ld: CMakeFiles/CppModelServ.dir/controllers/ in function `MmsCtrl::list(std::shared_ptr<drogon::HttpRequest> const&, std::function<void (std::shared_ptr<drogon::HttpResponse> const&)>&&) const': undefined reference to `Json::Value::Value(std::string const&)' /usr/bin/ld: undefined reference to `Json::Value::Value(std::string const&)' /usr/bin/ld: CMakeFiles/CppModelServ.dir/controllers/ in function `MmsCtrl::invoke(std::shared_ptr<drogon::HttpRequest> const&, std::function<void (std::shared_ptr<drogon::HttpResponse> const&)>&&, std::string) const': undefined reference to `drogon::utils::getUuid()' /usr/bin/ld: undefined reference to `Json::Value::Value(std::string const&)' /usr/bin/ld: CMakeFiles/CppModelServ.dir/controllers/ in function `std::enable_if<std::is_default_constructible<MmsCtrl>::value, void>::type drogon::DrObject<MmsCtrl>::DrAllocator::registerClass<MmsCtrl>()':[_ZN6drogon8DrObjectI7MmsCtrlE11DrAllocator13registerClassIS1_EENSt9enable_ifIXsrSt24is_default_constructibleIT_E5valueEvE4typeEv]+0x46): undefined reference to `drogon::DrClassMap::registerClass(std::string const&, std::function<drogon::DrObjectBase* ()> const&)' /usr/bin/ld: CMakeFiles/CppModelServ.dir/controllers/ in function `std::shared_ptr<MmsCtrl> drogon::DrClassMap::getSingleInstance<MmsCtrl>()':[_ZN6drogon10DrClassMap17getSingleInstanceI7MmsCtrlEESt10shared_ptrIT_Ev]+0x56): undefined reference to `drogon::DrClassMap::getSingleInstance(std::string const&)' collect2: error: ld returned 1 exit status make[2]: *** [CMakeFiles/CppModelServ.dir/build.make:136: CppModelServ] Error 1 make[2]: Leaving directory '/mnt/cpp-model-serv.git' make[1]: *** [CMakeFiles/Makefile2:100: CMakeFiles/CppModelServ.dir/all] Error 2 make[1]: Leaving directory '/mnt/cpp-model-serv.git' make: *** [Makefile:91: all] Error 2
enigma39 1 year ago 1

Hello, my drogon endpoints are mostly forwarding requests to other external services (after transforming query params / json body) then return a transformed response to the client. What kind of request processing design do you suggest for this (where I spend most of the time while waiting network I/O) ?

Add Discussion as Guest

Log in