Static Site

Let’s start with a simple example that introduces the usage of drogon. In this example we create a project using the command line tool drogon_ctl:

  1. drogon_ctl create project your_project_name

There are several useful folders in the project directory already:

  1. ├── build Build folder
  2. ├── CMakeLists.txt Project cmake configuration file
  3. ├── config.json Drogon application configuration file
  4. ├── controllers The folder where the controller source files are stored
  5. ├── filters The folder where the filter files are stored
  6. ├── main.cc Main program
  7. ├── models The folder of the database model file
  8. └── model.json
  9. └── views The folder where view csp files are stored

Users can put various files (such as controllers, filters, views, etc.) into the corresponding folders. For more convenience and less error, we strongly recommend that users create their own web application projects using the drogon_ctl command. See drogon_ctl for more details.

Let’s look at the main.cc file:

  1. #include <drogon/HttpAppFramework.h>
  2. int main() {
  3. //Set HTTP listener address and port
  4. drogon::app().addListener("0.0.0.0",80);
  5. //Load config file
  6. //drogon::app().loadConfigFile("../config.json");
  7. //Run HTTP framework,the method will block in the internal event loop
  8. drogon::app().run();
  9. return 0;
  10. }

Then build your project as below:

  1. cd build
  2. cmake ..
  3. make

After the compilation is complete, run the target ./your_project_name.

Now, we simply add one static file index.html to the Http root path:

  1. echo '<h1>Hello Drogon!</h1>' >>index.html

The default root path is "./", but could also be modified by config.json. See Configuration File for more details. Then you can visit this page by URL "http://localhost" or"http://localhost/index.html" (or the IP of the server where your wepapp is running).

Hello Drogon!

If the server cannot find the the page you have requested, it returns a 404 page: 404 page

Note: Make sure your server firewall has allowed the 80 port. Otherwise, you won’t see these pages.(Another way is to change your port from 80 to 1024(or above) in case you get the error message below):

  1. FATAL Permission denied (errno=13) , Bind address failed at 0.0.0.0:80 - Socket.cc:67

We could copy the directory and files of a static website to the startup directory of this running webapp, then we can access them from the browser. The file types supported by drogon by default are

  • html
  • js
  • css
  • xml
  • xsl
  • txt
  • svg
  • ttf
  • otf
  • woff2
  • woff
  • eot
  • png
  • jpg
  • jpeg
  • gif
  • bmp
  • ico
  • icns

Drogon also provides interfaces to change these file types. For details, please refer to the HttpAppFramework API.

Dynamic Site

Let’s see how to add controllers to this application, and let the controller respond with content.

One can use the drogon_ctl command line tool to generate controller source files. Let’s run it in the controllers directory:

  1. drogon_ctl create controller TestCtrl

As you can see, there are two new files, TestCtrl.h and TestCtrl.cc:

TestCtrl.h is as follows:

  1. #pragma once
  2. #include <drogon/HttpSimpleController.h>
  3. using namespace drogon;
  4. class TestCtrl:public drogon::HttpSimpleController<TestCtrl>
  5. {
  6. public:
  7. virtual void asyncHandleHttpRequest(const HttpRequestPtr &req,
  8. std::function<void (const HttpResponsePtr &)> &&callback)override;
  9. PATH_LIST_BEGIN
  10. //list path definitions here;
  11. //PATH_ADD("/path","filter1","filter2",HttpMethod1,HttpMethod2...);
  12. PATH_LIST_END
  13. };

TestCtrl.cc is as follows:

  1. #include "TestCtrl.h"
  2. void TestCtrl::asyncHandleHttpRequest(const HttpRequestPtr &req,
  3. std::function<void (const HttpResponsePtr &)> &&callback)
  4. {
  5. //write your application logic here
  6. }

Let’s edit the two files and let the controller handle the function response to a simple “Hello World!”

TestCtrl.h is as follows:

  1. #pragma once
  2. #include <drogon/HttpSimpleController.h>
  3. using namespace drogon;
  4. class TestCtrl:public drogon::HttpSimpleController<TestCtrl>
  5. {
  6. public:
  7. virtual void asyncHandleHttpRequest(const HttpRequestPtr &req,
  8. std::function<void (const HttpResponsePtr &)> &&callback)override;
  9. PATH_LIST_BEGIN
  10. //list path definitions here
  11. //example
  12. //PATH_ADD("/path","filter1","filter2",HttpMethod1,HttpMethod2...);
  13. PATH_ADD("/",Get,Post);
  14. PATH_ADD("/test",Get);
  15. PATH_LIST_END
  16. };

Use PATH_ADD to map the two paths ‘/‘ and ‘/test’ to handler functions and add optional path constraints (here, the allowed HTTP methods).

TestCtrl.cc is as follows:

  1. #include "TestCtrl.h"
  2. void TestCtrl::asyncHandleHttpRequest(const HttpRequestPtr &req,
  3. std::function<void (const HttpResponsePtr &)> &&callback)
  4. {
  5. //write your application logic here
  6. auto resp=HttpResponse::newHttpResponse();
  7. //NOTE: The enum constant below is named "k200OK" (as in 200 OK), not "k2000K".
  8. resp->setStatusCode(k200OK);
  9. resp->setContentTypeCode(CT_TEXT_HTML);
  10. resp->setBody("Hello World!");
  11. callback(resp);
  12. }

Recompile this project with CMake, then run the target ./your_project_name:

  1. cd ../build
  2. cmake ..
  3. make
  4. ./your_project_name

Type "http://localhost/" or "http://localhost/test" in the browser address bar, and you will see “Hello World!” in the browser.

Note: If your server has both static and dynamic resources, Drogon uses dynamic resources first. In this example,the response to GET http://localhost/ is Hello World! (from the TestCtrl controller file) instead of Hello Drogon! (from the static file index.html).

We see that adding a controller to an application is very simple. You only need to add the corresponding source file. Even the main file does not need to be modified. This loosely coupled design is very effective for web application development.

Note: Drogon has no restrictions on the location of the controller source files. You could also save them in “./“ (the project root directory), or you could even define a new directory in CMakeLists.txt. It is recommended to use the controllers directory for the convenience of management.

04.0 Controller Introduction