Skip to content

Commit 36aa1d1

Browse files
committedJun 18, 2022
update README about create project and ref , and add practice codes
1 parent 648459a commit 36aa1d1

16 files changed

+1318
-2
lines changed
 

‎.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
# buildディレクトリ
2+
demo/build/
3+
14
# Prerequisites
25
*.d
36

‎README.md

+27-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ WebフレームワークDrogonお試し
44
## Drogonインストール手順
55
- Ubuntu LTS 20.04(Windowsでは面倒だったのでMac or Linuxがオススメ)<br>
66

7-
参考:https://zenn.dev/cork/articles/drogon_tutorial
8-
97
``` bash
108
git clone https://github.com/an-tao/drogon
119
cd drogon
@@ -24,3 +22,30 @@ make && sudo make install
2422
``` bash
2523
drogon_ctl -v
2624
```
25+
26+
## プロジェクト作成と実行
27+
28+
プロジェクトディレクトリ名「demo」
29+
30+
``` bash
31+
# プロジェクト作成コマンド
32+
drogon_ctl create project demo
33+
# プロジェクトディレクトリのビルドに移動
34+
cd ./dmeo/build
35+
# Makefile作成
36+
cmake
37+
# ビルド&コンパイル
38+
make
39+
# 実行
40+
sudo ./demo
41+
42+
# ↑強制的に80番ポートを使用するためsudoを使用。sudoを用いなければ80番ポートが別のプロセスで使用されていた場合にはエラーになってしまう。
43+
```
44+
45+
## 参考Webサイト
46+
- [Drogon公式ドキュメント](https://drogon.docsforge.com/)
47+
- [「Drogon」入門](https://zenn.dev/cork/articles/drogon_tutorial)
48+
- [最速のC++ Webフレームワーク「Drogon」を試してみた!](https://rightcode.co.jp/blog/information-technology/fastest-c-web-framework-drogon-quick-start)
49+
50+
## 私的感想
51+
C++のWebフレームワークと聞いてやってみたが、環境構築が面倒な割に想像より面白くなかった

‎demo/.gitignore

+561
Large diffs are not rendered by default.

‎demo/CMakeLists.txt

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
cmake_minimum_required(VERSION 3.5)
2+
project(demo CXX)
3+
4+
include(CheckIncludeFileCXX)
5+
6+
check_include_file_cxx(any HAS_ANY)
7+
check_include_file_cxx(string_view HAS_STRING_VIEW)
8+
check_include_file_cxx(coroutine HAS_COROUTINE)
9+
if (NOT "${CMAKE_CXX_STANDARD}" STREQUAL "")
10+
# Do nothing
11+
elseif (HAS_ANY AND HAS_STRING_VIEW AND HAS_COROUTINE)
12+
set(CMAKE_CXX_STANDARD 20)
13+
elseif (HAS_ANY AND HAS_STRING_VIEW)
14+
set(CMAKE_CXX_STANDARD 17)
15+
else ()
16+
set(CMAKE_CXX_STANDARD 14)
17+
endif ()
18+
19+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
20+
set(CMAKE_CXX_EXTENSIONS OFF)
21+
22+
add_executable(${PROJECT_NAME} main.cc)
23+
24+
# ##############################################################################
25+
# If you include the drogon source code locally in your project, use this method
26+
# to add drogon
27+
# add_subdirectory(drogon)
28+
# target_link_libraries(${PROJECT_NAME} PRIVATE drogon)
29+
#
30+
# and comment out the following lines
31+
find_package(Drogon CONFIG REQUIRED)
32+
target_link_libraries(${PROJECT_NAME} PRIVATE Drogon::Drogon)
33+
34+
# ##############################################################################
35+
36+
if (CMAKE_CXX_STANDARD LESS 17)
37+
# With C++14, use boost to support any, string_view and filesystem
38+
message(STATUS "use c++14")
39+
find_package(Boost 1.61.0 REQUIRED)
40+
target_link_libraries(${PROJECT_NAME} PUBLIC Boost::boost)
41+
elseif (CMAKE_CXX_STANDARD LESS 20)
42+
message(STATUS "use c++17")
43+
else ()
44+
message(STATUS "use c++20")
45+
endif ()
46+
47+
aux_source_directory(controllers CTL_SRC)
48+
aux_source_directory(filters FILTER_SRC)
49+
aux_source_directory(plugins PLUGIN_SRC)
50+
aux_source_directory(models MODEL_SRC)
51+
52+
drogon_create_views(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/views
53+
${CMAKE_CURRENT_BINARY_DIR})
54+
# use the following line to create views with namespaces.
55+
# drogon_create_views(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/views
56+
# ${CMAKE_CURRENT_BINARY_DIR} TRUE)
57+
# use the following line to create views with namespace CHANGE_ME prefixed
58+
# and path namespaces.
59+
# drogon_create_views(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/views
60+
# ${CMAKE_CURRENT_BINARY_DIR} TRUE CHANGE_ME)
61+
62+
target_include_directories(${PROJECT_NAME}
63+
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
64+
${CMAKE_CURRENT_SOURCE_DIR}/models)
65+
target_sources(${PROJECT_NAME}
66+
PRIVATE
67+
${SRC_DIR}
68+
${CTL_SRC}
69+
${FILTER_SRC}
70+
${PLUGIN_SRC}
71+
${MODEL_SRC})
72+
# ##############################################################################
73+
# uncomment the following line for dynamically loading views
74+
# set_property(TARGET ${PROJECT_NAME} PROPERTY ENABLE_EXPORTS ON)
75+
76+
# ##############################################################################
77+
78+
add_subdirectory(test)

‎demo/config.json

+311
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,311 @@
1+
/* This is a JSON format configuration file
2+
*/
3+
{
4+
/*
5+
//ssl:The global SSL settings. "key" and "cert" are the path to the SSL key and certificate. While
6+
// "conf" is an array of 1 or 2-element tuples that supplies file style options for `SSL_CONF_cmd`.
7+
"ssl": {
8+
"cert": "../../trantor/trantor/tests/server.pem",
9+
"key": "../../trantor/trantor/tests/server.pem",
10+
"conf": [
11+
//["Options", "-SessionTicket"],
12+
//["Options", "Compression"]
13+
]
14+
},
15+
"listeners": [
16+
{
17+
//address: Ip address,0.0.0.0 by default
18+
"address": "0.0.0.0",
19+
//port: Port number
20+
"port": 80,
21+
//https: If true, use https for security,false by default
22+
"https": false
23+
},
24+
{
25+
"address": "0.0.0.0",
26+
"port": 443,
27+
"https": true,
28+
//cert,key: Cert file path and key file path, empty by default,
29+
//if empty, use the global setting
30+
"cert": "",
31+
"key": "",
32+
//use_old_tls: enable the TLS1.0/1.1, false by default
33+
"use_old_tls": false,
34+
"ssl_conf": [
35+
//["MinProtocol", "TLSv1.3"]
36+
]
37+
}
38+
],
39+
"db_clients": [
40+
{
41+
//name: Name of the client,'default' by default
42+
//"name":"",
43+
//rdbms: Server type, postgresql,mysql or sqlite3, "postgresql" by default
44+
"rdbms": "postgresql",
45+
//filename: Sqlite3 db file name
46+
//"filename":"",
47+
//host: Server address,localhost by default
48+
"host": "127.0.0.1",
49+
//port: Server port, 5432 by default
50+
"port": 5432,
51+
//dbname: Database name
52+
"dbname": "test",
53+
//user: 'postgres' by default
54+
"user": "",
55+
//passwd: '' by default
56+
"passwd": "",
57+
//is_fast: false by default, if it is true, the client is faster but user can't call
58+
//any synchronous interface of it.
59+
"is_fast": false,
60+
//client_encoding: The character set used by the client. it is empty string by default which
61+
//means use the default character set.
62+
//"client_encoding": "",
63+
//number_of_connections: 1 by default, if the 'is_fast' is true, the number is the number of
64+
//connections per IO thread, otherwise it is the total number of all connections.
65+
"number_of_connections": 1,
66+
//timeout: -1.0 by default, in seconds, the timeout for executing a SQL query.
67+
//zero or negative value means no timeout.
68+
"timeout": -1.0,
69+
//"auto_batch": this feature is only available for the PostgreSQL driver(version >= 14.0), see
70+
// the wiki for more details.
71+
"auto_batch": false
72+
}
73+
],
74+
"redis_clients": [
75+
{
76+
//name: Name of the client,'default' by default
77+
//"name":"",
78+
//host: Server IP, 127.0.0.1 by default
79+
"host": "127.0.0.1",
80+
//port: Server port, 6379 by default
81+
"port": 6379,
82+
//username: '' by default which means 'default' in redis ACL
83+
"username": "",
84+
//passwd: '' by default
85+
"passwd": "",
86+
//db index: 0 by default
87+
"db": 0,
88+
//is_fast: false by default, if it is true, the client is faster but user can't call
89+
//any synchronous interface of it.
90+
"is_fast": false,
91+
//number_of_connections: 1 by default, if the 'is_fast' is true, the number is the number of
92+
//connections per IO thread, otherwise it is the total number of all connections.
93+
"number_of_connections": 1,
94+
//timeout: -1.0 by default, in seconds, the timeout for executing a command.
95+
//zero or negative value means no timeout.
96+
"timeout": -1.0
97+
}
98+
],*/
99+
"app": {
100+
//number_of_threads: The number of IO threads, 1 by default, if the value is set to 0, the number of threads
101+
//is the number of CPU cores
102+
"number_of_threads": 1,
103+
//enable_session: False by default
104+
"enable_session": false,
105+
"session_timeout": 0,
106+
//string value of SameSite attribute of the Set-Cookie HTTP respone header
107+
//valid value is either 'Null' (default), 'Lax', 'Strict' or 'None'
108+
"session_same_site" : "Null",
109+
//document_root: Root path of HTTP document, defaut path is ./
110+
"document_root": "./",
111+
//home_page: Set the HTML file of the home page, the default value is "index.html"
112+
//If there isn't any handler registered to the path "/", the home page file in the "document_root" is send to clients as a response
113+
//to the request for "/".
114+
"home_page": "index.html",
115+
//use_implicit_page: enable implicit pages if true, true by default
116+
"use_implicit_page": true,
117+
//implicit_page: Set the file which would the server access in a directory that a user accessed.
118+
//For example, by default, http://localhost/a-directory resolves to http://localhost/a-directory/index.html.
119+
"implicit_page": "index.html",
120+
//static_file_headers: Headers for static files
121+
/*"static_file_headers": [
122+
{
123+
"name": "field-name",
124+
"value": "field-value"
125+
}
126+
],*/
127+
//upload_path: The path to save the uploaded file. "uploads" by default.
128+
//If the path isn't prefixed with /, ./ or ../,
129+
//it is relative path of document_root path
130+
"upload_path": "uploads",
131+
/* file_types:
132+
* HTTP download file types,The file types supported by drogon
133+
* by default are "html", "js", "css", "xml", "xsl", "txt", "svg",
134+
* "ttf", "otf", "woff2", "woff" , "eot", "png", "jpg", "jpeg",
135+
* "gif", "bmp", "ico", "icns", etc. */
136+
"file_types": [
137+
"gif",
138+
"png",
139+
"jpg",
140+
"js",
141+
"css",
142+
"html",
143+
"ico",
144+
"swf",
145+
"xap",
146+
"apk",
147+
"cur",
148+
"xml"
149+
],
150+
// mime: A dictionary that extends the internal MIME type support. Maps extensions into new MIME types
151+
// note: This option only adds MIME to the sever. `file_types` above have to be set for the server to serve them.
152+
"mime": {
153+
// "text/markdown": "md",
154+
// "text/gemini": ["gmi", "gemini"]
155+
},
156+
//locations: An array of locations of static files for GET requests.
157+
"locations": [
158+
{
159+
//uri_prefix: The URI prefix of the location prefixed with "/", the default value is "" that disables the location.
160+
//"uri_prefix": "/.well-known/acme-challenge/",
161+
//default_content_type: The default content type of the static files without
162+
//an extension. empty string by default.
163+
"default_content_type": "text/plain",
164+
//alias: The location in file system, if it is prefixed with "/", it
165+
//presents an absolute path, otherwise it presents a relative path to
166+
//the document_root path.
167+
//The default value is "" which means use the document root path as the location base path.
168+
"alias": "",
169+
//is_case_sensitive: indicates whether the URI prefix is case sensitive.
170+
"is_case_sensitive": false,
171+
//allow_all: true by default. If it is set to false, only static files with a valid extension can be accessed.
172+
"allow_all": true,
173+
//is_recursive: true by default. If it is set to false, files in sub directories can't be accessed.
174+
"is_recursive": true,
175+
//filters: string array, the filters applied to the location.
176+
"filters": []
177+
}
178+
],
179+
//max_connections: maximum number of connections, 100000 by default
180+
"max_connections": 100000,
181+
//max_connections_per_ip: maximum number of connections per clinet, 0 by default which means no limit
182+
"max_connections_per_ip": 0,
183+
//Load_dynamic_views: False by default, when set to true, drogon
184+
//compiles and loads dynamically "CSP View Files" in directories defined
185+
//by "dynamic_views_path"
186+
"load_dynamic_views": false,
187+
//dynamic_views_path: If the path isn't prefixed with /, ./ or ../,
188+
//it is relative path of document_root path
189+
"dynamic_views_path": [
190+
"./views"
191+
],
192+
//dynamic_views_output_path: Default by an empty string which means the output path of source
193+
//files is the path where the csp files locate. If the path isn't prefixed with /, it is relative
194+
//path of the current working directory.
195+
"dynamic_views_output_path": "",
196+
//enable_unicode_escaping_in_json: true by default, enable unicode escaping in json.
197+
"enable_unicode_escaping_in_json": true,
198+
//float_precision_in_json: set precision of float number in json.
199+
"float_precision_in_json": {
200+
//precision: 0 by default, 0 means use the default precision of the jsoncpp lib.
201+
"precision": 0,
202+
//precision_type: must be "significant" or "decimal", defaults to "significant" that means
203+
//setting max number of significant digits in string, "decimal" means setting max number of
204+
//digits after "." in string
205+
"precision_type": "significant"
206+
},
207+
//log: Set log output, drogon output logs to stdout by default
208+
"log": {
209+
//log_path: Log file path,empty by default,in which case,logs are output to the stdout
210+
//"log_path": "./",
211+
//logfile_base_name: Log file base name,empty by default which means drogon names logfile as
212+
//drogon.log ...
213+
"logfile_base_name": "",
214+
//log_size_limit: 100000000 bytes by default,
215+
//When the log file size reaches "log_size_limit", the log file is switched.
216+
"log_size_limit": 100000000,
217+
//log_level: "DEBUG" by default,options:"TRACE","DEBUG","INFO","WARN"
218+
//The TRACE level is only valid when built in DEBUG mode.
219+
"log_level": "DEBUG"
220+
},
221+
//run_as_daemon: False by default
222+
"run_as_daemon": false,
223+
//handle_sig_term: True by default
224+
"handle_sig_term": true,
225+
//relaunch_on_error: False by default, if true, the program will be restart by the parent after exiting;
226+
"relaunch_on_error": false,
227+
//use_sendfile: True by default, if true, the program
228+
//uses sendfile() system-call to send static files to clients;
229+
"use_sendfile": true,
230+
//use_gzip: True by default, use gzip to compress the response body's content;
231+
"use_gzip": true,
232+
//use_brotli: False by default, use brotli to compress the response body's content;
233+
"use_brotli": false,
234+
//static_files_cache_time: 5 (seconds) by default, the time in which the static file response is cached,
235+
//0 means cache forever, the negative value means no cache
236+
"static_files_cache_time": 5,
237+
//simple_controllers_map: Used to configure mapping from path to simple controller
238+
"simple_controllers_map": [
239+
{
240+
"path": "/path/name",
241+
"controller": "controllerClassName",
242+
"http_methods": [
243+
"get",
244+
"post"
245+
],
246+
"filters": [
247+
"FilterClassName"
248+
]
249+
}
250+
],
251+
//idle_connection_timeout: Defaults to 60 seconds, the lifetime
252+
//of the connection without read or write
253+
"idle_connection_timeout": 60,
254+
//server_header_field: Set the 'Server' header field in each response sent by drogon,
255+
//empty string by default with which the 'Server' header field is set to "Server: drogon/version string\r\n"
256+
"server_header_field": "",
257+
//enable_server_header: Set true to force drogon to add a 'Server' header to each HTTP response. The default
258+
//value is true.
259+
"enable_server_header": true,
260+
//enable_date_header: Set true to force drogon to add a 'Date' header to each HTTP response. The default
261+
//value is true.
262+
"enable_date_header": true,
263+
//keepalive_requests: Set the maximum number of requests that can be served through one keep-alive connection.
264+
//After the maximum number of requests are made, the connection is closed.
265+
//The default value of 0 means no limit.
266+
"keepalive_requests": 0,
267+
//pipelining_requests: Set the maximum number of unhandled requests that can be cached in pipelining buffer.
268+
//After the maximum number of requests are made, the connection is closed.
269+
//The default value of 0 means no limit.
270+
"pipelining_requests": 0,
271+
//gzip_static: If it is set to true, when the client requests a static file, drogon first finds the compressed
272+
//file with the extension ".gz" in the same path and send the compressed file to the client.
273+
//The default value of gzip_static is true.
274+
"gzip_static": true,
275+
//br_static: If it is set to true, when the client requests a static file, drogon first finds the compressed
276+
//file with the extension ".br" in the same path and send the compressed file to the client.
277+
//The default value of br_static is true.
278+
"br_static": true,
279+
//client_max_body_size: Set the maximum body size of HTTP requests received by drogon. The default value is "1M".
280+
//One can set it to "1024", "1k", "10M", "1G", etc. Setting it to "" means no limit.
281+
"client_max_body_size": "1M",
282+
//max_memory_body_size: Set the maximum body size in memory of HTTP requests received by drogon. The default value is "64K" bytes.
283+
//If the body size of a HTTP request exceeds this limit, the body is stored to a temporary file for processing.
284+
//Setting it to "" means no limit.
285+
"client_max_memory_body_size": "64K",
286+
//client_max_websocket_message_size: Set the maximum size of messages sent by WebSocket client. The default value is "128K".
287+
//One can set it to "1024", "1k", "10M", "1G", etc. Setting it to "" means no limit.
288+
"client_max_websocket_message_size": "128K",
289+
//reuse_port: Defaults to false, users can run multiple processes listening on the same port at the same time.
290+
"reuse_port": false
291+
},
292+
//plugins: Define all plugins running in the application
293+
"plugins": [
294+
{
295+
//name: The class name of the plugin
296+
//"name": "drogon::plugin::SecureSSLRedirector",
297+
//dependencies: Plugins that the plugin depends on. It can be commented out
298+
"dependencies": [],
299+
//config: The configuration of the plugin. This json object is the parameter to initialize the plugin.
300+
//It can be commented out
301+
"config": {
302+
"ssl_redirect_exempt": [
303+
".*\\.jpg"
304+
],
305+
"secure_ssl_host": "localhost:8849"
306+
}
307+
}
308+
],
309+
//custom_config: custom configuration for users. This object can be get by the app().getCustomConfig() method.
310+
"custom_config": {}
311+
}

‎demo/controllers/ListParameters.cc

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#include "ListParameters.h"
2+
void ListParameters::asyncHandleHttpRequest(
3+
const HttpRequestPtr &req,
4+
std::function<void(const HttpResponsePtr &)> &&callback) {
5+
// write your application logic here
6+
7+
// CSPに渡すデータを格納
8+
auto para = req->getParameters();
9+
HttpViewData data;
10+
data.insert("title", "list parameters");
11+
data.insert("parameters", para);
12+
13+
// ListParaCsp.cspにデータを渡す
14+
auto res =
15+
drogon::HttpResponse::newHttpViewResponse("ListParaCsp.csp", data);
16+
callback(res);
17+
}

‎demo/controllers/ListParameters.h

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#pragma once
2+
#include <drogon/HttpSimpleController.h>
3+
using namespace drogon;
4+
class ListParameters : public drogon::HttpSimpleController<ListParameters> {
5+
public:
6+
virtual void asyncHandleHttpRequest(
7+
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_ADD("/list_para", Get);
13+
14+
PATH_LIST_END
15+
};

‎demo/controllers/demo_v1_User.cc

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#include "demo_v1_User.h"
2+
3+
using namespace demo::v1;
4+
5+
// Add definition of your processing function here
6+
void User::login(const HttpRequestPtr &req,
7+
std::function<void (const HttpResponsePtr &)> &&callback,
8+
std::string &&userId,
9+
const std::string &password)
10+
{
11+
LOG_DEBUG<<"User "<<userId<<" login";
12+
//Authentication algorithm, read database, verify identity, etc...
13+
//...
14+
Json::Value ret;
15+
ret["result"]="ok";
16+
ret["token"]=drogon::utils::getUuid();
17+
auto resp=HttpResponse::newHttpJsonResponse(ret);
18+
callback(resp);
19+
}
20+
21+
void User::getInfo(const HttpRequestPtr &req,
22+
std::function<void (const HttpResponsePtr &)> &&callback,
23+
std::string userId,
24+
const std::string &token) const
25+
{
26+
LOG_DEBUG<<"User "<<userId<<" get his information";
27+
28+
//Verify the validity of the token, etc.
29+
//Read the database or cache to get user information
30+
Json::Value ret;
31+
ret["result"]="ok";
32+
ret["user_name"]="Jack";
33+
ret["user_id"]=userId;
34+
ret["gender"]=1;
35+
auto resp=HttpResponse::newHttpJsonResponse(ret);
36+
callback(resp);
37+
}

‎demo/controllers/demo_v1_User.h

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#pragma once
2+
3+
#include <drogon/HttpController.h>
4+
5+
using namespace drogon;
6+
7+
namespace demo
8+
{
9+
namespace v1
10+
{
11+
class User : public drogon::HttpController<User>
12+
{
13+
public:
14+
METHOD_LIST_BEGIN
15+
// Getでアクセスされた場合、getInfo()メソッドの処理をする
16+
17+
METHOD_ADD(User::login,"/token?userId={1}&passwd={2}",Post);
18+
METHOD_ADD(User::getInfo,"/{1}/info?token={2}",Get);
19+
// http://localhost/demo/v1/user/text/info?token=111
20+
21+
METHOD_LIST_END
22+
// メソッドの宣言:実装は「demo_v1_User.cc」に行う
23+
void login(const HttpRequestPtr &req,
24+
std::function<void (const HttpResponsePtr &)> &&callback,
25+
std::string &&userId,
26+
const std::string &password);
27+
28+
void getInfo(const HttpRequestPtr &req,
29+
std::function<void (const HttpResponsePtr &)> &&callback,
30+
std::string userId,
31+
const std::string &token) const;
32+
};
33+
}
34+
}

‎demo/controllers/testctrl.cc

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#include "testctrl.h"
2+
3+
void testctrl::asyncHandleHttpRequest(const HttpRequestPtr& req, std::function<void (const HttpResponsePtr &)> &&callback)
4+
{
5+
// write your application logic here
6+
auto resp = HttpResponse::newHttpResponse(); // 新しいレスポンスインスタンスを生成
7+
resp->setStatusCode(k200OK); // HTTPステータスコード 200に設定
8+
resp->setContentTypeCode(CT_TEXT_HTML); // Header: Content typeをHTMLにする
9+
resp->setBody("<h1>Hello World!</h1>"); // Body:
10+
callback(resp);
11+
}

‎demo/controllers/testctrl.h

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

‎demo/main.cc

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#include <drogon/drogon.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+
}

‎demo/models/model.json

+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
{
2+
//rdbms: server type, postgresql,mysql or sqlite3
3+
"rdbms": "postgresql",
4+
//filename: sqlite3 db file name
5+
//"filename":"",
6+
//host: server address,localhost by default;
7+
"host": "127.0.0.1",
8+
//port: server port, 5432 by default;
9+
"port": 5432,
10+
//dbname: Database name;
11+
"dbname": "",
12+
//schema: valid for postgreSQL, "public" by default;
13+
"schema": "public",
14+
//user: User name
15+
"user": "",
16+
//password or passwd: Password
17+
"password": "",
18+
//client_encoding: The character set used by drogon_ctl. it is empty string by default which
19+
//means use the default character set.
20+
//"client_encoding": "",
21+
//table: An array of tables to be modelized. if the array is empty, all revealed tables are modelized.
22+
"tables": [],
23+
//convert: the value can be changed by a function call before it is stored into database or
24+
//after it is read from database
25+
"convert": {
26+
"enabled": false,
27+
"items":[{
28+
"table": "user",
29+
"column": "password",
30+
"method": {
31+
//after_db_read: name of the method which is called after reading from database, signature: void([const] std::shared_ptr [&])
32+
"after_db_read": "decrypt_password",
33+
//before_db_write: name of the method which is called before writing to database, signature: void([const] std::shared_ptr [&])
34+
"before_db_write": "encrypt_password"
35+
},
36+
"includes": [
37+
"\"file_local_search_path.h\"","<file_in_global_search_path.h>"
38+
]
39+
}]
40+
},
41+
"relationships": {
42+
"enabled": false,
43+
"items": [{
44+
"type": "has one",
45+
"original_table_name": "products",
46+
"original_table_alias": "product",
47+
"original_key": "id",
48+
"target_table_name": "skus",
49+
"target_table_alias": "SKU",
50+
"target_key": "product_id",
51+
"enable_reverse": true
52+
},
53+
{
54+
"type": "has many",
55+
"original_table_name": "products",
56+
"original_table_alias": "product",
57+
"original_key": "id",
58+
"target_table_name": "reviews",
59+
"target_table_alias": "",
60+
"target_key": "product_id",
61+
"enable_reverse": true
62+
},
63+
{
64+
"type": "many to many",
65+
"original_table_name": "products",
66+
"original_table_alias": "",
67+
"original_key": "id",
68+
"pivot_table": {
69+
"table_name": "carts_products",
70+
"original_key": "product_id",
71+
"target_key": "cart_id"
72+
},
73+
"target_table_name": "carts",
74+
"target_table_alias": "",
75+
"target_key": "id",
76+
"enable_reverse": true
77+
}
78+
]
79+
},
80+
"restful_api_controllers": {
81+
"enabled": false,
82+
// resource_uri: The URI to access the resource, the default value
83+
// is '/*' in which the asterisk represents the table name.
84+
// If this option is set to a empty string, the URI is composed of the namespaces and the class name.
85+
"resource_uri": "/*",
86+
// class_name: "Restful*Ctrl" by default, the asterisk represents the table name.
87+
// This option can contain namespaces.
88+
"class_name": "Restful*Ctrl",
89+
// filters: an array of filter names.
90+
"filters": [],
91+
// db_client: the database client used by the controller. this option must be consistent with
92+
// the configuration of the application.
93+
"db_client": {
94+
//name: Name of the client,'default' by default
95+
"name": "default",
96+
//is_fast:
97+
"is_fast": false
98+
},
99+
// directory: The directory where the controller source files are stored.
100+
"directory": "controllers",
101+
// generate_base_only: false by default. Set to true to avoid overwriting custom subclasses.
102+
"generate_base_only": false
103+
}
104+
}

‎demo/test/CMakeLists.txt

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
cmake_minimum_required(VERSION 3.5)
2+
project(demo_test CXX)
3+
4+
add_executable(${PROJECT_NAME} test_main.cc)
5+
6+
# ##############################################################################
7+
# If you include the drogon source code locally in your project, use this method
8+
# to add drogon
9+
# target_link_libraries(${PROJECT_NAME}_test PRIVATE drogon)
10+
#
11+
# and comment out the following lines
12+
target_link_libraries(${PROJECT_NAME} PRIVATE Drogon::Drogon)
13+
14+
ParseAndAddDrogonTests(${PROJECT_NAME})

‎demo/test/test_main.cc

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#define DROGON_TEST_MAIN
2+
#include <drogon/drogon_test.h>
3+
#include <drogon/drogon.h>
4+
5+
DROGON_TEST(BasicTest)
6+
{
7+
// Add your tests here
8+
}
9+
10+
int main(int argc, char** argv)
11+
{
12+
using namespace drogon;
13+
14+
std::promise<void> p1;
15+
std::future<void> f1 = p1.get_future();
16+
17+
// Start the main loop on another thread
18+
std::thread thr([&]() {
19+
// Queues the promise to be fulfilled after starting the loop
20+
app().getLoop()->queueInLoop([&p1]() { p1.set_value(); });
21+
app().run();
22+
});
23+
24+
// The future is only satisfied after the event loop started
25+
f1.get();
26+
int status = test::run(argc, argv);
27+
28+
// Ask the event loop to shutdown and wait
29+
app().getLoop()->queueInLoop([]() { app().quit(); });
30+
thr.join();
31+
return status;
32+
}

‎demo/views/ListParaCsp.csp

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<%c++
4+
// c++のコードが記述可能な範囲
5+
6+
// dataからunorder_mapとしてパラメータを取得
7+
auto para = @@.get<std::unordered_map<std::string, std::string>>("parameters");
8+
9+
// 適当に変数宣言する
10+
auto name = "Drogon Inc.";
11+
auto date = "2022.6.18";
12+
auto text = "hogehoge";
13+
%>
14+
15+
<head>
16+
<meta charset="UTF-8">
17+
<title>[[ title ]]</title>
18+
</head>
19+
20+
<body>
21+
22+
<!-- 変数展開はどちらでも良い -->
23+
<p>Hello, {% name %}</p>
24+
<p>Date: <%c++ $$ << date; %></p>
25+
<p>サンプル文字: <%c++ $$ << text; %></p>
26+
27+
<%c++ if(para.size()>0){%>
28+
<H1>Parameters</H1>
29+
<table border="1">
30+
<tr>
31+
<th>name</th>
32+
<th>value</th>
33+
</tr>
34+
<!-- イテレーションループでパラメータを展開 -->
35+
<%c++ for(auto iter:para){ %>
36+
<tr>
37+
<td>{% iter.first %}</td>
38+
<td><%c++ $$<<iter.second;%></td>
39+
</tr>
40+
<%c++ } // endfor%>
41+
</table>
42+
<%c++ }else{ %>
43+
<H1>no parameter</H1>
44+
<%c++ } // endif %>
45+
</body>
46+
</html>

0 commit comments

Comments
 (0)
Please sign in to comment.