mirror of
https://github.com/drogonframework/drogon.git
synced 2025-06-24 00:00:43 -04:00
Compare commits
480 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
a22956b82b | ||
|
3c5749bbc2 | ||
|
7cd1ae8940 | ||
|
c3f9192541 | ||
|
e46e05e94a | ||
|
26e7c6913c | ||
|
8d640bafb4 | ||
|
f6b5404dbb | ||
|
46b5c9044d | ||
|
ac0d4d0f89 | ||
|
5c4057331e | ||
|
95a518e7f2 | ||
|
c03a3df106 | ||
|
d6a33f93c9 | ||
|
59cd4366c7 | ||
|
c92d146374 | ||
|
3c7c66e310 | ||
|
1fb67d68be | ||
|
cbf63f8fc4 | ||
|
d68e8aa554 | ||
|
41537a6e86 | ||
|
a32dc67867 | ||
|
e155df9f66 | ||
|
f5de41f5d7 | ||
|
a3b4779540 | ||
|
686f68a12f | ||
|
152a69f1e9 | ||
|
38dd5fea31 | ||
|
3a6268f7e9 | ||
|
47f8af7ca1 | ||
|
44f796b796 | ||
|
df7e83ae74 | ||
|
99e816283d | ||
|
3e944d28d8 | ||
|
1765223755 | ||
|
71b6d57cae | ||
|
882c1d9ecd | ||
|
8541e67143 | ||
|
6d9ecb8d8d | ||
|
23c561f072 | ||
|
284d14b8ca | ||
|
ca2210331d | ||
|
3fce70b535 | ||
|
bf1fc03bff | ||
|
5225bb3295 | ||
|
ac0a1b873e | ||
|
912f1d803c | ||
|
13d7148764 | ||
|
b0c5331bc1 | ||
|
c9f5754423 | ||
|
31fb18fb46 | ||
|
f918ead0ae | ||
|
fee34095a2 | ||
|
2911a7c08a | ||
|
1b4653577f | ||
|
bbcad71458 | ||
|
beec858eba | ||
|
93d8fb425d | ||
|
73406d1225 | ||
|
6bafdf30fd | ||
|
59919f33ef | ||
|
1326205483 | ||
|
80ec7d9211 | ||
|
5b5d1906bf | ||
|
206ef0d881 | ||
|
c46f149c2c | ||
|
0546032edc | ||
|
f743cfd4d1 | ||
|
500d44faac | ||
|
e786907478 | ||
|
5d4523a3a6 | ||
|
dfacd1b454 | ||
|
85b918f9e9 | ||
|
7b8d0085b1 | ||
|
f6913f6328 | ||
|
a2f759e4cd | ||
|
ad2b7e13e1 | ||
|
b04dfd7f96 | ||
|
de5a4a5f57 | ||
|
8bdb9b2fa6 | ||
|
0a889e921d | ||
|
9a96a20c6e | ||
|
f37a1d036f | ||
|
c4c95918bf | ||
|
6726df139d | ||
|
150735848d | ||
|
155ae9ad65 | ||
|
306df8a8fb | ||
|
82c46f13f8 | ||
|
5f75222243 | ||
|
5b7cefd32c | ||
|
abbcf6023d | ||
|
b5cd748a12 | ||
|
439ddd8dbe | ||
|
e79d5170b4 | ||
|
519398c159 | ||
|
96919df488 | ||
|
294035beb9 | ||
|
46ac53adb3 | ||
|
9f2872639a | ||
|
4cbac301fb | ||
|
88d06684f2 | ||
|
da7f065a6f | ||
|
aa04d33e02 | ||
|
1a9ad1a2c9 | ||
|
22f4b4fad6 | ||
|
99d97df25f | ||
|
6aed658fab | ||
|
3d469112ca | ||
|
f63480674f | ||
|
0d178877f0 | ||
|
5f273d8744 | ||
|
3c8c273582 | ||
|
c2b8e7c624 | ||
|
56a53165b6 | ||
|
674137e89d | ||
|
ffc6e74f27 | ||
|
359b63fa77 | ||
|
baea2dce47 | ||
|
cca1c8f262 | ||
|
aeed963915 | ||
|
e640cc092d | ||
|
93c568bb95 | ||
|
af29e25b03 | ||
|
d745cfe765 | ||
|
6b36b3a4f9 | ||
|
8e4ffa71e2 | ||
|
25f874a278 | ||
|
5ecbd1f184 | ||
|
34d32a1ef0 | ||
|
1fd5c7ea5e | ||
|
2a0da80d5f | ||
|
01ad18d2d5 | ||
|
f4443dce44 | ||
|
021c89ec78 | ||
|
125dd0e69e | ||
|
38bde80aaa | ||
|
4eec56c49f | ||
|
ba9e9731d2 | ||
|
41b740f649 | ||
|
e76bf08eb2 | ||
|
c35e62ccd2 | ||
|
358de6e66f | ||
|
8026790e1a | ||
|
4e890f52d6 | ||
|
27f1a3d812 | ||
|
6370461896 | ||
|
6b20a9fa8d | ||
|
830ced8c5b | ||
|
6f6a03b14b | ||
|
f21b899e63 | ||
|
26840aa056 | ||
|
01385f4f33 | ||
|
2000a4279e | ||
|
1ec3c96cbb | ||
|
56f0102cfe | ||
|
a76c11cc34 | ||
|
e5daba6bf5 | ||
|
8586874c87 | ||
|
f215cb15a0 | ||
|
7599ae98a0 | ||
|
4323e7b6ef | ||
|
9ffe1b267b | ||
|
645c2d8aaf | ||
|
ab76e80089 | ||
|
d9afdf279a | ||
|
1efe89a719 | ||
|
fd7af8110f | ||
|
63b7f5eb13 | ||
|
94ca651cbd | ||
|
6cb8ac6f52 | ||
|
078f60ca03 | ||
|
cfa0de4389 | ||
|
112d19ff12 | ||
|
cedeeb59f4 | ||
|
4e5638fdcd | ||
|
e2e5d6d57f | ||
|
53c84305b2 | ||
|
85d7c068e4 | ||
|
5d0c70278e | ||
|
366311c196 | ||
|
5df9b48998 | ||
|
8d4c17702a | ||
|
9337571e1a | ||
|
816684e15d | ||
|
40aa034595 | ||
|
de4c811772 | ||
|
3ecb8b4917 | ||
|
f761c54aa8 | ||
|
58055ae39c | ||
|
bc4d740b0c | ||
|
f8f5283dff | ||
|
54b137d64f | ||
|
40579ae308 | ||
|
81bf767d89 | ||
|
f1426c6e9a | ||
|
17c80508c0 | ||
|
f361995035 | ||
|
3723ed5e0c | ||
|
83e08f4b27 | ||
|
3aa93e62e7 | ||
|
5c43b82dc2 | ||
|
4c44322221 | ||
|
47e700c77f | ||
|
a122725c3b | ||
|
5509091ab8 | ||
|
43b014cc24 | ||
|
4ad68db5e2 | ||
|
d3dbaed60a | ||
|
d7ae3a21b3 | ||
|
3fa480dd87 | ||
|
56f620717e | ||
|
ad99cf724d | ||
|
a91014a982 | ||
|
9b2716ec24 | ||
|
d00222883f | ||
|
0fb887cb07 | ||
|
f16017ee6e | ||
|
ec5dfdd9f7 | ||
|
8f37e526cc | ||
|
c1da9922eb | ||
|
ca92e32d55 | ||
|
cca5e5badd | ||
|
92e036874a | ||
|
cb2ae14bdf | ||
|
34a5c37974 | ||
|
3c82dcb491 | ||
|
6dbe650c74 | ||
|
74bb47c690 | ||
|
61073b4f74 | ||
|
eea916315e | ||
|
8e4474bf4c | ||
|
269399b701 | ||
|
586fd6d67a | ||
|
44b6916d7e | ||
|
7f04e63f25 | ||
|
5e245d08dc | ||
|
b9a699f866 | ||
|
3263b78ec3 | ||
|
07726dfcab | ||
|
415b34e06d | ||
|
75b106599d | ||
|
7fce0f1ff5 | ||
|
87a3132fd1 | ||
|
abf6f6cc86 | ||
|
bd66fa4f55 | ||
|
5baca75359 | ||
|
29984f26e0 | ||
|
fddbc0abb7 | ||
|
bf4ff759ad | ||
|
42bbc185e1 | ||
|
8b250f8638 | ||
|
178fb22b49 | ||
|
2caa8c4a34 | ||
|
4ec75e03e0 | ||
|
22c7567da3 | ||
|
f615d5e8df | ||
|
f14ba8de28 | ||
|
7c96c7fbf5 | ||
|
65b1715539 | ||
|
4358b71f55 | ||
|
c7912f246b | ||
|
d133b21804 | ||
|
ad2798e4aa | ||
|
abee656699 | ||
|
292d677446 | ||
|
0715a94a06 | ||
|
5df4db96a5 | ||
|
122a42cd4f | ||
|
120aaf249d | ||
|
f0a011b14d | ||
|
e25a162887 | ||
|
02742e4518 | ||
|
4f066258f2 | ||
|
ceab5f3037 | ||
|
21e207abe5 | ||
|
c63b021e7d | ||
|
2af8e47278 | ||
|
00debb056b | ||
|
af551bf2fb | ||
|
b229f74743 | ||
|
a039157587 | ||
|
97a5496fa4 | ||
|
314bab0b4c | ||
|
ab5259b290 | ||
|
d4c0e063f1 | ||
|
57ec87d38d | ||
|
b739a7fab8 | ||
|
394f9bd0d4 | ||
|
bc028776f7 | ||
|
d321bd4fc1 | ||
|
313392a9b6 | ||
|
29955becc1 | ||
|
54d96963f3 | ||
|
ae9d5f20b3 | ||
|
7d87d7e0b2 | ||
|
36d7435d1d | ||
|
479346822f | ||
|
3adf168a87 | ||
|
0b3147c157 | ||
|
007a6ffbe3 | ||
|
554939d7ee | ||
|
1618484d74 | ||
|
19f08786f0 | ||
|
80ea3c4f30 | ||
|
c5e596d942 | ||
|
28518b7bba | ||
|
1b11bfb668 | ||
|
ef93c91ec7 | ||
|
25ece89558 | ||
|
31fa010ca9 | ||
|
ab10d8cb22 | ||
|
c0d48da99f | ||
|
9dff8b296b | ||
|
990be54ea0 | ||
|
6208332de3 | ||
|
a8be56f9bb | ||
|
164972e2d3 | ||
|
37a10318ff | ||
|
29c67565a3 | ||
|
995b8e8b82 | ||
|
89588959b1 | ||
|
875bca0a86 | ||
|
4d63475203 | ||
|
cdd48686ab | ||
|
d3fe59432b | ||
|
1c8580a71b | ||
|
c913441bb4 | ||
|
302bb560b6 | ||
|
a1a0ef1af8 | ||
|
6a397efefe | ||
|
c97125b22f | ||
|
574a60f812 | ||
|
de1bd805fc | ||
|
ff1aac37de | ||
|
94c4f27d61 | ||
|
29b33a7fa0 | ||
|
c40bb2bc1f | ||
|
f582a16adb | ||
|
64b9484657 | ||
|
2465753ee9 | ||
|
bd9d290b82 | ||
|
4ef31d7c2d | ||
|
9abc9e5b6c | ||
|
5610bd2182 | ||
|
5371b967f6 | ||
|
2b75af82ee | ||
|
a1d2bd168b | ||
|
9f23560a29 | ||
|
bf36db1562 | ||
|
c9f5946eff | ||
|
82bd6bceac | ||
|
cfe1681b0f | ||
|
1bc6ee1170 | ||
|
a582a773c1 | ||
|
5373e51f92 | ||
|
474db0dd9a | ||
|
8b90403bae | ||
|
da18f21796 | ||
|
b32fa58d16 | ||
|
cf543716ce | ||
|
ee9ca895c7 | ||
|
9524a91479 | ||
|
b8f44aec2e | ||
|
e2b5a07921 | ||
|
46c00a317f | ||
|
81dd4ebd07 | ||
|
7570137138 | ||
|
a42f759248 | ||
|
3b5de8863a | ||
|
ebf87d69d7 | ||
|
664d97c185 | ||
|
346e2e6033 | ||
|
7af9853589 | ||
|
a4afc394dc | ||
|
3388c72343 | ||
|
8ab868ea22 | ||
|
bd4f3814a6 | ||
|
1bc38c7e22 | ||
|
fffb8f7e7c | ||
|
41d9d7ec58 | ||
|
3b11b80b10 | ||
|
cd55a198d2 | ||
|
3b0fd3d676 | ||
|
19d9ffcfc2 | ||
|
4f2cbd4135 | ||
|
c5a1888da3 | ||
|
f017b09947 | ||
|
e8b21502e2 | ||
|
a4ba8aff95 | ||
|
5892fa2f9f | ||
|
c9c2675ba9 | ||
|
bccf509ca0 | ||
|
86dbf9875b | ||
|
e53c81b229 | ||
|
d51bae1016 | ||
|
567e7c07ad | ||
|
8c4896dfec | ||
|
6971f84dae | ||
|
3d3daef3c5 | ||
|
740c34fce3 | ||
|
dd63a72dab | ||
|
b9bbe45642 | ||
|
b8a6188ad5 | ||
|
fc68b8c92c | ||
|
09a351d032 | ||
|
0e3ee5fad0 | ||
|
4b31f93767 | ||
|
3c785326c6 | ||
|
8ed0434ad8 | ||
|
26c8c0b527 | ||
|
92d39fb174 | ||
|
bbc31612fc | ||
|
bfb25a3765 | ||
|
88f4f090a8 | ||
|
68b2a46a29 | ||
|
e81662f29b | ||
|
29732a94ef | ||
|
e2842c9de5 | ||
|
720ce4e9ed | ||
|
9db332af65 | ||
|
6c8f8bac1f | ||
|
bc4e8faec2 | ||
|
52800006a0 | ||
|
03f34cb40b | ||
|
bba5253a0f | ||
|
080123ff96 | ||
|
6b677a3ff6 | ||
|
be3136ea26 | ||
|
719d50c0a7 | ||
|
754fd2da29 | ||
|
66e29dd9b2 | ||
|
7455355419 | ||
|
2a484536d1 | ||
|
6a55a3aa64 | ||
|
e9fafc643d | ||
|
1c44cf7e4c | ||
|
3ad9326e2a | ||
|
113d23494a | ||
|
7cf0a64ab6 | ||
|
8913abc400 | ||
|
d6b09c9e1b | ||
|
f522d2d70e | ||
|
bc18f56d57 | ||
|
7d137362bd | ||
|
6e6493299e | ||
|
faf3e0c17c | ||
|
ec8146774a | ||
|
895552dcae | ||
|
df331c8a74 | ||
|
953000e3fb | ||
|
e4ec2c36c5 | ||
|
29f2d431ab | ||
|
9e9bc7997e | ||
|
9448c19865 | ||
|
0431f38a4e | ||
|
7066b09edb | ||
|
dff4b6c5d9 | ||
|
e2eb674781 | ||
|
5a03c9aa9f | ||
|
a7f05c4214 | ||
|
0818384172 | ||
|
ac4a816a99 | ||
|
4a6f298661 | ||
|
3eb5bcd1dd | ||
|
22f810a71b | ||
|
fdcf294ef9 | ||
|
9b09abe274 | ||
|
c5effe9c51 | ||
|
8460249ab3 | ||
|
f49d71faba | ||
|
c9f98e1bf3 | ||
|
56cb305ae3 | ||
|
c7b6c8403f | ||
|
94c7add7a1 | ||
|
cdabca9de5 | ||
|
ba5187868d | ||
|
6b0e38fc8f | ||
|
30f06515fe | ||
|
b2bf247048 |
@ -1,41 +0,0 @@
|
|||||||
version: 1.6.0.{build}
|
|
||||||
configuration:
|
|
||||||
- Release
|
|
||||||
- Debug
|
|
||||||
|
|
||||||
environment:
|
|
||||||
matrix:
|
|
||||||
- GENERATOR: Visual Studio 15 2017
|
|
||||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
|
||||||
ARCH: Win32
|
|
||||||
|
|
||||||
- GENERATOR: Visual Studio 15 2017
|
|
||||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
|
||||||
ARCH: x64
|
|
||||||
|
|
||||||
init:
|
|
||||||
- cmake --version
|
|
||||||
install:
|
|
||||||
- cd C:\Tools\vcpkg
|
|
||||||
- git pull
|
|
||||||
- .\bootstrap-vcpkg.bat
|
|
||||||
- vcpkg install jsoncpp:x86-windows
|
|
||||||
- vcpkg install jsoncpp:x64-windows
|
|
||||||
- vcpkg install zlib:x86-windows
|
|
||||||
- vcpkg install zlib:x64-windows
|
|
||||||
- vcpkg install libpq:x86-windows
|
|
||||||
- vcpkg install libpq:x64-windows
|
|
||||||
- vcpkg integrate install
|
|
||||||
- cd %APPVEYOR_BUILD_FOLDER%
|
|
||||||
before_build:
|
|
||||||
- git submodule update --init
|
|
||||||
- md build
|
|
||||||
- cd build
|
|
||||||
- cmake --config "%CONFIGURATION%" -G "%GENERATOR%" -DCMAKE_TOOLCHAIN_FILE=c:/tools/vcpkg/scripts/buildsystems/vcpkg.cmake ..
|
|
||||||
build_script:
|
|
||||||
- cmake --build . --config "%CONFIGURATION%"
|
|
||||||
build:
|
|
||||||
project: build\ALL_BUILD.vcxproj
|
|
||||||
verbosity: minimal
|
|
||||||
cache:
|
|
||||||
- c:\tools\vcpkg\installed\
|
|
@ -53,7 +53,7 @@ ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
|||||||
ConstructorInitializerIndentWidth: 4
|
ConstructorInitializerIndentWidth: 4
|
||||||
ContinuationIndentWidth: 4
|
ContinuationIndentWidth: 4
|
||||||
Cpp11BracedListStyle: true
|
Cpp11BracedListStyle: true
|
||||||
DerivePointerAlignment: true
|
DerivePointerAlignment: false
|
||||||
DisableFormat: false
|
DisableFormat: false
|
||||||
FixNamespaceComments: true
|
FixNamespaceComments: true
|
||||||
ForEachMacros:
|
ForEachMacros:
|
||||||
@ -75,6 +75,7 @@ IndentCaseLabels: true
|
|||||||
IndentPPDirectives: None
|
IndentPPDirectives: None
|
||||||
IndentWidth: 4
|
IndentWidth: 4
|
||||||
IndentWrappedFunctionNames: false
|
IndentWrappedFunctionNames: false
|
||||||
|
InsertNewlineAtEOF: true
|
||||||
JavaScriptQuotes: Leave
|
JavaScriptQuotes: Leave
|
||||||
JavaScriptWrapImports: true
|
JavaScriptWrapImports: true
|
||||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||||
@ -94,7 +95,8 @@ PenaltyBreakString: 1000
|
|||||||
PenaltyBreakTemplateDeclaration: 10
|
PenaltyBreakTemplateDeclaration: 10
|
||||||
PenaltyExcessCharacter: 1000000
|
PenaltyExcessCharacter: 1000000
|
||||||
PenaltyReturnTypeOnItsOwnLine: 2000
|
PenaltyReturnTypeOnItsOwnLine: 2000
|
||||||
PointerAlignment: Left
|
PointerAlignment: Right
|
||||||
|
ReferenceAlignment: Right
|
||||||
RawStringFormats:
|
RawStringFormats:
|
||||||
- Language: Cpp
|
- Language: Cpp
|
||||||
Delimiters:
|
Delimiters:
|
||||||
@ -124,7 +126,8 @@ RawStringFormats:
|
|||||||
CanonicalDelimiter: ''
|
CanonicalDelimiter: ''
|
||||||
BasedOnStyle: google
|
BasedOnStyle: google
|
||||||
ReflowComments: true
|
ReflowComments: true
|
||||||
SortIncludes: false
|
SeparateDefinitionBlocks: Always
|
||||||
|
SortIncludes: Never
|
||||||
SortUsingDeclarations: true
|
SortUsingDeclarations: true
|
||||||
SpaceAfterCStyleCast: false
|
SpaceAfterCStyleCast: false
|
||||||
SpaceAfterTemplateKeyword: true
|
SpaceAfterTemplateKeyword: true
|
||||||
|
4
.github/FUNDING.yml
vendored
4
.github/FUNDING.yml
vendored
@ -1,6 +1,6 @@
|
|||||||
# These are supported funding model platforms
|
# These are supported funding model platforms
|
||||||
|
|
||||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
github: drogonframework
|
||||||
patreon: # Replace with a single Patreon username
|
patreon: # Replace with a single Patreon username
|
||||||
open_collective: # Replace with a single Open Collective username
|
open_collective: # Replace with a single Open Collective username
|
||||||
ko_fi: # Replace with a single Ko-fi username
|
ko_fi: # Replace with a single Ko-fi username
|
||||||
@ -9,4 +9,4 @@ community_bridge: # Replace with a single Community Bridge project-name e.g., cl
|
|||||||
liberapay: # Replace with a single Liberapay username
|
liberapay: # Replace with a single Liberapay username
|
||||||
issuehunt: # Replace with a single IssueHunt username
|
issuehunt: # Replace with a single IssueHunt username
|
||||||
otechie: # Replace with a single Otechie username
|
otechie: # Replace with a single Otechie username
|
||||||
custom: ['https://paypal.me/antao2019']
|
custom: # ['https://paypal.me/antao2019']
|
||||||
|
9
.github/ISSUE_TEMPLATE/bug_report.md
vendored
9
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -1,10 +1,17 @@
|
|||||||
---
|
---
|
||||||
name: Bug report
|
name: Bug report
|
||||||
about: Create a report to help us improve
|
about: Create a report to help us improve
|
||||||
labels:
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Notice**
|
||||||
|
If you need support or clarification regarding the usage of Drogon in your project, visit the official Drogon support channel at [gitter](https://gitter.im/drogon-web/community)
|
||||||
|
|
||||||
|
Please create a new issue only if you think you have found a bug or if have a feature request/enhancement.
|
||||||
|
|
||||||
**Describe the bug**
|
**Describe the bug**
|
||||||
A clear and concise description of what the bug is.
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
9
.github/ISSUE_TEMPLATE/feature_request.md
vendored
9
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@ -1,10 +1,17 @@
|
|||||||
---
|
---
|
||||||
name: Feature request
|
name: Feature request
|
||||||
about: Suggest an idea for this project
|
about: Suggest an idea for this project
|
||||||
labels:
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
**Notice**
|
||||||
|
If you need support or clarification regarding the usage of Drogon in your project, visit the official Drogon support channel at [gitter](https://gitter.im/drogon-web/community)
|
||||||
|
|
||||||
|
Please create a new issue only if you think you have found a bug or if have a feature request/enhancement.
|
||||||
|
|
||||||
**Is your feature request related to a problem? Please describe.**
|
**Is your feature request related to a problem? Please describe.**
|
||||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||||
|
|
||||||
|
11
.github/dependabot.yml
vendored
Normal file
11
.github/dependabot.yml
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# To get started with Dependabot version updates, you'll need to specify which
|
||||||
|
# package ecosystems to update and where the package manifests are located.
|
||||||
|
# Please see the documentation for all configuration options:
|
||||||
|
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||||
|
|
||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
- package-ecosystem: "github-actions"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "monthly"
|
323
.github/workflows/cmake.yml
vendored
323
.github/workflows/cmake.yml
vendored
@ -1,4 +1,4 @@
|
|||||||
name: Build Drogon
|
name: Build & Test
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
@ -6,195 +6,232 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||||
|
|
||||||
env:
|
env:
|
||||||
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
|
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
|
||||||
BUILD_TYPE: Release
|
BUILD_TYPE: Release
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
windows:
|
windows:
|
||||||
name: 'windows/msvc - ${{matrix.link}}'
|
name: windows/msvc - ${{ matrix.link }}
|
||||||
runs-on: windows-latest
|
runs-on: windows-2022
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
link: [ 'STATIC', 'SHARED' ]
|
link: ["STATIC", "SHARED"]
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Drogon source code
|
- name: Checkout Drogon source code
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: pip install conan
|
||||||
pip install conan
|
|
||||||
|
|
||||||
- name: Create build directory
|
- name: Create build directory
|
||||||
run: |
|
run: mkdir build
|
||||||
mkdir build
|
|
||||||
|
|
||||||
- name: Install conan packages
|
- name: Install conan packages
|
||||||
shell: pwsh
|
|
||||||
working-directory: ./build
|
working-directory: ./build
|
||||||
run: |
|
run: |
|
||||||
conan install .. -s compiler="Visual Studio" -s compiler.version=16 -sbuild_type=Debug -g cmake_paths
|
conan profile detect
|
||||||
|
conan install .. -s compiler="msvc" -sbuild_type=Debug --build=missing -s compiler.cppstd=17
|
||||||
|
|
||||||
- name: Create Build Environment & Configure Cmake
|
- name: Create Build Environment & Configure Cmake
|
||||||
shell: bash
|
shell: bash
|
||||||
working-directory: ./build
|
working-directory: ./build
|
||||||
run: |
|
run: |
|
||||||
[[ ${{ matrix.link }} == "SHARED" ]] && shared="ON" || shared="OFF"
|
[[ ${{ matrix.link }} == "SHARED" ]] && shared="ON" || shared="OFF"
|
||||||
cmake .. -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=on -DBUILD_DROGON_SHARED=$shared -DCMAKE_TOOLCHAIN_FILE="conan_paths.cmake" -DBUILD_CTL=ON -DBUILD_EXAMPLES=ON -DCMAKE_INSTALL_PREFIX=../install
|
cmake .. \
|
||||||
|
-DCMAKE_BUILD_TYPE=Debug \
|
||||||
|
-DBUILD_TESTING=on \
|
||||||
|
-DBUILD_SHARED_LIBS=$shared \
|
||||||
|
-DCMAKE_TOOLCHAIN_FILE="conan_toolchain.cmake" \
|
||||||
|
-DBUILD_CTL=ON \
|
||||||
|
-DBUILD_EXAMPLES=ON \
|
||||||
|
-DUSE_SPDLOG=ON \
|
||||||
|
-DCMAKE_INSTALL_PREFIX=../install \
|
||||||
|
-DCMAKE_POLICY_DEFAULT_CMP0091=NEW \
|
||||||
|
-DCMAKE_CXX_STANDARD=17
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
working-directory: ${{env.GITHUB_WORKSPACE}}
|
run: cmake --build build --target install --parallel
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
cd build
|
|
||||||
cmake --build . --target install --parallel
|
|
||||||
|
|
||||||
- name: Test
|
- name: Test
|
||||||
working-directory: ${{env.GITHUB_WORKSPACE}}
|
|
||||||
shell: bash
|
shell: bash
|
||||||
run: ./test.sh -w
|
run: ./test.sh -w
|
||||||
|
|
||||||
unix:
|
macos:
|
||||||
name: ${{matrix.buildname}}
|
runs-on: macos-${{ matrix.osver }}
|
||||||
runs-on: ${{matrix.os}}
|
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
osver: [13, 14, 15]
|
||||||
- os: ubuntu-20.04
|
|
||||||
buildname: 'ubuntu-20.04/gcc'
|
|
||||||
link: SHARED
|
|
||||||
triplet: x64-linux
|
|
||||||
compiler: gcc_64
|
|
||||||
- os: ubuntu-20.04
|
|
||||||
buildname: 'ubuntu-20.04/gcc'
|
|
||||||
link: STATIC
|
|
||||||
triplet: x64-linux
|
|
||||||
compiler: gcc_64
|
|
||||||
- os: ubuntu-20.04
|
|
||||||
buildname: 'ubuntu-20.04/gcc-10'
|
|
||||||
link: STATIC
|
|
||||||
triplet: x64-linux
|
|
||||||
- os: ubuntu-16.04
|
|
||||||
buildname: 'ubuntu-16.04/gcc'
|
|
||||||
link: STATIC
|
|
||||||
triplet: x64-linux
|
|
||||||
compiler: gcc_64
|
|
||||||
- os: macos-latest
|
|
||||||
buildname: 'macos/clang'
|
|
||||||
link: STATIC
|
|
||||||
triplet: x64-osx
|
|
||||||
compiler: clang_64
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Drogon source code
|
- name: Checkout Drogon source code
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: (macOS) Install dependencies
|
- name: Install dependencies
|
||||||
if: runner.os == 'macOS'
|
# Already installed: brotli, zlib, lz4, sqlite3
|
||||||
run: |
|
run: brew install ninja jsoncpp mariadb hiredis redis spdlog postgresql@14
|
||||||
brew install jsoncpp ossp-uuid brotli zlib
|
|
||||||
brew install openssl lz4 mariadb sqlite3 postgresql hiredis
|
|
||||||
brew install redis
|
|
||||||
|
|
||||||
- name: (Linux) Install dependencies
|
- name: Create Build Environment & Configure Cmake
|
||||||
if: runner.os == 'Linux'
|
# Some projects don't allow in-source building, so create a separate build directory
|
||||||
run: |
|
# We'll use this as our working directory for all subsequent commands
|
||||||
# Installing packages might fail as the github image becomes outdated
|
run: |
|
||||||
sudo apt update
|
cmake -B build -G Ninja \
|
||||||
# These aren't available or don't work well in vcpkg
|
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
|
||||||
sudo apt install libjsoncpp-dev uuid-dev openssl libssl-dev zlib1g-dev libsqlite3-dev
|
-DBUILD_TESTING=on \
|
||||||
sudo apt install libbrotli-dev
|
-DUSE_SPDLOG=ON \
|
||||||
- name: (Linux) Install gcc-10
|
-DBUILD_SHARED_LIBS=OFF
|
||||||
if: matrix.buildname == 'ubuntu-20.04/gcc-10'
|
|
||||||
run: |
|
|
||||||
sudo apt install gcc-10 g++-10
|
|
||||||
- name: (Linux) Install boost
|
|
||||||
if: matrix.os == 'ubuntu-16.04'
|
|
||||||
run: |
|
|
||||||
sudo add-apt-repository ppa:mhier/libboost-latest
|
|
||||||
sudo apt update
|
|
||||||
sudo apt install boost1.67
|
|
||||||
|
|
||||||
- name: (Linux) Install postgresql
|
- name: Build
|
||||||
if: matrix.os == 'ubuntu-20.04'
|
working-directory: ./build
|
||||||
run: |
|
# Execute the build. You can specify a specific target with "--target <NAME>"
|
||||||
sudo apt install postgresql-all
|
run: ninja && sudo ninja install
|
||||||
|
|
||||||
- name: Create build directory
|
- name: Prepare for testing
|
||||||
run: |
|
run: |
|
||||||
mkdir build
|
brew services restart postgresql@14
|
||||||
|
brew services start mariadb
|
||||||
|
brew services start redis
|
||||||
|
sleep 4
|
||||||
|
mariadb -e "SET PASSWORD FOR 'root'@'localhost' = PASSWORD('')"
|
||||||
|
mariadb -e "GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost'"
|
||||||
|
mariadb -e "FLUSH PRIVILEGES"
|
||||||
|
brew services restart mariadb
|
||||||
|
sleep 4
|
||||||
|
psql -c 'create user postgres superuser;' postgres
|
||||||
|
|
||||||
- name: Create Build Environment & Configure Cmake
|
- name: Test
|
||||||
# Some projects don't allow in-source building, so create a separate build directory
|
# Execute tests defined by the CMake configuration.
|
||||||
# We'll use this as our working directory for all subsequent commands
|
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
|
||||||
shell: bash
|
run: ./test.sh -t
|
||||||
working-directory: ./build
|
|
||||||
if: matrix.buildname != 'ubuntu-20.04/gcc-10'
|
|
||||||
run: |
|
|
||||||
[[ ${{ matrix.link }} == "SHARED" ]] && shared="ON" || shared="OFF"
|
|
||||||
cmake .. -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DBUILD_TESTING=on -DBUILD_DROGON_SHARED=$shared
|
|
||||||
|
|
||||||
- name: Create Build Environment & Configure Cmake (gcc-10)
|
ubuntu:
|
||||||
# Some projects don't allow in-source building, so create a separate build directory
|
runs-on: ubuntu-22.04
|
||||||
# We'll use this as our working directory for all subsequent commands
|
strategy:
|
||||||
shell: bash
|
fail-fast: false
|
||||||
working-directory: ./build
|
matrix:
|
||||||
if: matrix.buildname == 'ubuntu-20.04/gcc-10'
|
link: [SHARED, STATIC]
|
||||||
run: |
|
compiler:
|
||||||
[[ ${{ matrix.link }} == "SHARED" ]] && shared="ON" || shared="OFF"
|
- cxx: g++
|
||||||
cmake .. -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DBUILD_TESTING=on -DCMAKE_CXX_FLAGS="-fcoroutines" -DBUILD_DROGON_SHARED=$shared
|
ver: 9
|
||||||
env:
|
- cxx: g++
|
||||||
CC: gcc-10
|
ver: 10
|
||||||
CXX: g++-10
|
- cxx: g++
|
||||||
|
ver: 11
|
||||||
|
- cxx: g++
|
||||||
|
ver: 12
|
||||||
|
- cxx: g++
|
||||||
|
ver: 13
|
||||||
|
- cxx: clang++
|
||||||
|
ver: 11
|
||||||
|
- cxx: clang++
|
||||||
|
ver: 12
|
||||||
|
- cxx: clang++
|
||||||
|
ver: 13
|
||||||
|
- cxx: clang++
|
||||||
|
ver: 14
|
||||||
|
- cxx: clang++
|
||||||
|
ver: 15
|
||||||
|
- cxx: clang++
|
||||||
|
ver: 16
|
||||||
|
- cxx: clang++
|
||||||
|
ver: 17
|
||||||
|
include:
|
||||||
|
- link: STATIC
|
||||||
|
compiler:
|
||||||
|
cxx: g++
|
||||||
|
ver: 13
|
||||||
|
feature: coroutines
|
||||||
|
env:
|
||||||
|
CXX: ${{ matrix.compiler.cxx }}-${{ matrix.compiler.ver }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout Drogon source code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: true
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: (Linux) Build
|
- name: Install dependencies
|
||||||
working-directory: ./build
|
run: |
|
||||||
shell: bash
|
# Installing packages might fail as the github image becomes outdated
|
||||||
# Execute the build. You can specify a specific target with "--target <NAME>"
|
sudo apt update
|
||||||
run: |
|
# These aren't available or don't work well in vcpkg
|
||||||
sudo make -j $(nproc) && sudo make install
|
sudo apt-get install -y libjsoncpp-dev uuid-dev libssl-dev zlib1g-dev libsqlite3-dev
|
||||||
|
sudo apt-get install -y ninja-build libbrotli-dev
|
||||||
|
sudo apt-get install -y libspdlog-dev
|
||||||
|
|
||||||
- name: Prepare for testing (macOS)
|
- name: Install postgresql
|
||||||
if: runner.os == 'macOS'
|
run: |
|
||||||
run: |
|
sudo apt-get --purge remove postgresql postgresql-doc postgresql-common postgresql-client-common
|
||||||
cd $(brew --prefix)/Homebrew/Library/Taps/homebrew/homebrew-services
|
sudo apt-get -y install postgresql-all
|
||||||
git reset --hard 5f2fe01
|
|
||||||
cd ~
|
|
||||||
brew tap homebrew/services;
|
|
||||||
brew services restart postgresql;
|
|
||||||
brew services start mariadb;
|
|
||||||
brew services start redis;
|
|
||||||
sleep 4;
|
|
||||||
mariadb -e "SET PASSWORD FOR 'root'@'localhost' = PASSWORD('')";
|
|
||||||
mariadb -e "GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost'";
|
|
||||||
mariadb -e "FLUSH PRIVILEGES";
|
|
||||||
brew services restart mariadb;
|
|
||||||
sleep 4;
|
|
||||||
psql -c 'create user postgres superuser;' postgres;
|
|
||||||
|
|
||||||
- name: Prepare for testing (Linux)
|
- name: Install g++-13
|
||||||
if: runner.os == 'Linux'
|
if: startsWith(matrix.compiler.cxx, 'g++') && matrix.compiler.ver == 13
|
||||||
run: |
|
run: |
|
||||||
sudo systemctl start postgresql
|
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
|
||||||
sleep 1
|
sudo apt-get install g++-${{ matrix.compiler.ver }}
|
||||||
sudo -u postgres psql -c "ALTER USER postgres WITH PASSWORD '12345'" postgres
|
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-13 13
|
||||||
|
|
||||||
- name: Test
|
- name: Install Clang
|
||||||
working-directory: ${{env.GITHUB_WORKSPACE}}
|
if: startsWith(matrix.compiler.cxx, 'clang') && matrix.compiler.ver < 13
|
||||||
shell: bash
|
run: sudo apt-get install clang-${{ matrix.compiler.ver }}
|
||||||
# Execute tests defined by the CMake configuration.
|
|
||||||
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
|
|
||||||
run: ./test.sh -t
|
|
||||||
|
|
||||||
- name: Lint
|
- name: Install Clang
|
||||||
if: matrix.os == 'ubuntu-20.04'
|
if: startsWith(matrix.compiler.cxx, 'clang') && matrix.compiler.ver >= 13
|
||||||
working-directory: ${{env.GITHUB_WORKSPACE}}
|
run: |
|
||||||
shell: bash
|
wget https://apt.llvm.org/llvm.sh
|
||||||
run: ./format.sh && git diff --exit-code
|
chmod +x ./llvm.sh
|
||||||
|
sudo ./llvm.sh ${{ matrix.compiler.ver }}
|
||||||
|
|
||||||
|
- name: Export `shared`
|
||||||
|
run: |
|
||||||
|
[[ ${{ matrix.link }} == "SHARED" ]] && shared="ON" || shared="OFF"
|
||||||
|
echo "shared=$shared" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Create Build Environment & Configure Cmake
|
||||||
|
# Some projects don't allow in-source building, so create a separate build directory
|
||||||
|
# We'll use this as our working directory for all subsequent commands
|
||||||
|
if: matrix.compiler.feature != 'coroutines'
|
||||||
|
run: |
|
||||||
|
cmake -B build -G Ninja \
|
||||||
|
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
|
||||||
|
-DBUILD_TESTING=on \
|
||||||
|
-DUSE_SPDLOG=ON \
|
||||||
|
-DBUILD_SHARED_LIBS=$shared
|
||||||
|
- name: Create Build Environment & Configure Cmake (coroutines)
|
||||||
|
# Some projects don't allow in-source building, so create a separate build directory
|
||||||
|
# We'll use this as our working directory for all subsequent commands
|
||||||
|
if: matrix.compiler.feature == 'coroutines'
|
||||||
|
run: |
|
||||||
|
cmake -B build -G Ninja \
|
||||||
|
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
|
||||||
|
-DBUILD_TESTING=on \
|
||||||
|
-DUSE_SPDLOG=ON \
|
||||||
|
-DCMAKE_CXX_FLAGS="-fcoroutines" \
|
||||||
|
-DBUILD_SHARED_LIBS=$shared \
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
working-directory: ./build
|
||||||
|
# Execute the build. You can specify a specific target with "--target <NAME>"
|
||||||
|
run: ninja && sudo ninja install
|
||||||
|
|
||||||
|
- name: Prepare for testing
|
||||||
|
run: |
|
||||||
|
sudo systemctl start postgresql
|
||||||
|
sleep 1
|
||||||
|
sudo -u postgres psql -c "ALTER USER postgres WITH PASSWORD '12345'" postgres
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
# Execute tests defined by the CMake configuration.
|
||||||
|
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
|
||||||
|
run: ./test.sh -t
|
||||||
|
80
.github/workflows/codeql.yml
vendored
Normal file
80
.github/workflows/codeql.yml
vendored
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
name: "CodeQL"
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ 'master' ]
|
||||||
|
pull_request:
|
||||||
|
# The branches below must be a subset of the branches above
|
||||||
|
branches: [ 'master' ]
|
||||||
|
schedule:
|
||||||
|
- cron: '46 7 * * 5'
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||||
|
|
||||||
|
env:
|
||||||
|
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
|
||||||
|
BUILD_TYPE: Release
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
analyze:
|
||||||
|
name: Analyze
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
actions: read
|
||||||
|
contents: read
|
||||||
|
security-events: write
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
language: [ 'cpp' ]
|
||||||
|
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
||||||
|
# Use only 'java' to analyze code written in Java, Kotlin or both
|
||||||
|
# Use only 'javascript' to analyze code written in JavaScript, TypeScript or both
|
||||||
|
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
|
||||||
|
|
||||||
|
env:
|
||||||
|
SHARED: ON
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout Drogon source code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: true
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt update
|
||||||
|
sudo apt-get install -y libjsoncpp-dev uuid-dev libssl-dev zlib1g-dev libsqlite3-dev
|
||||||
|
sudo apt-get install -y ninja-build libbrotli-dev
|
||||||
|
|
||||||
|
- name: Create Build Environment & Configure Cmake
|
||||||
|
run: |
|
||||||
|
cmake -B build -G Ninja \
|
||||||
|
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
|
||||||
|
-DBUILD_TESTING=on \
|
||||||
|
-DBUILD_SHARED_LIBS=$SHARED
|
||||||
|
|
||||||
|
# Initializes the CodeQL tools for scanning.
|
||||||
|
- name: Initialize CodeQL
|
||||||
|
uses: github/codeql-action/init@v3
|
||||||
|
with:
|
||||||
|
languages: ${{ matrix.language }}
|
||||||
|
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||||
|
# By default, queries listed here will override any specified in a config file.
|
||||||
|
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||||
|
|
||||||
|
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||||
|
# queries: security-extended,security-and-quality
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
working-directory: ./build
|
||||||
|
run: ninja && sudo ninja install
|
||||||
|
|
||||||
|
- name: Perform CodeQL Analysis
|
||||||
|
uses: github/codeql-action/analyze@v3
|
||||||
|
with:
|
||||||
|
category: "/language:${{matrix.language}}"
|
15
.github/workflows/codespell.yml
vendored
Normal file
15
.github/workflows/codespell.yml
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# Look for typos in the codebase using codespell.
|
||||||
|
# https://github.com/codespell-project/codespell#readme
|
||||||
|
name: codespell
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [master]
|
||||||
|
pull_request:
|
||||||
|
branches: [master]
|
||||||
|
jobs:
|
||||||
|
codespell:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- run: sudo apt-get install -y codespell
|
||||||
|
- run: codespell --ignore-words-list="coo,folx,ot,statics,xwindows,NotIn,aNULL," --skip="*.csp"
|
41
.github/workflows/cpp.yml
vendored
Normal file
41
.github/workflows/cpp.yml
vendored
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
name: C++
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [master]
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
format:
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install dos2unix
|
||||||
|
run: sudo apt-get install -y dos2unix
|
||||||
|
|
||||||
|
- name: Install clang-format-17
|
||||||
|
run: |
|
||||||
|
wget https://apt.llvm.org/llvm.sh
|
||||||
|
chmod +x ./llvm.sh
|
||||||
|
sudo ./llvm.sh 17
|
||||||
|
sudo apt-get install -y clang-format-17
|
||||||
|
|
||||||
|
- name: Check formatting
|
||||||
|
run: ./format.sh && git diff --exit-code
|
||||||
|
env:
|
||||||
|
CLANG_FORMAT: clang-format-17
|
||||||
|
|
||||||
|
cpplint:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install cpplint
|
||||||
|
run: pip install cpplint
|
||||||
|
|
||||||
|
- name: Run lint
|
||||||
|
run: cpplint --recursive .
|
28
.github/workflows/docker-publish.yml
vendored
Normal file
28
.github/workflows/docker-publish.yml
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
name: Build and Push Docker Image
|
||||||
|
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types: [created] # 当新版本被创建时触发
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Check out code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Log in to Docker Hub
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
|
|
||||||
|
- name: Build Docker image
|
||||||
|
run: |
|
||||||
|
cd docker/ubuntu
|
||||||
|
docker build -t drogonframework/drogon:latest .
|
||||||
|
|
||||||
|
- name: Push Docker image
|
||||||
|
run: |
|
||||||
|
docker push drogonframework/drogon:latest
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -33,8 +33,8 @@
|
|||||||
|
|
||||||
build/
|
build/
|
||||||
cmake-build-debug/
|
cmake-build-debug/
|
||||||
|
cmake-build-debug-visual-studio/
|
||||||
.idea/
|
.idea/
|
||||||
lib/inc/drogon/version.h
|
|
||||||
html/
|
html/
|
||||||
latex/
|
latex/
|
||||||
.vscode
|
.vscode
|
||||||
|
2
.gitmodules
vendored
2
.gitmodules
vendored
@ -1,4 +1,4 @@
|
|||||||
[submodule "trantor"]
|
[submodule "trantor"]
|
||||||
path = trantor
|
path = trantor
|
||||||
url = https://github.com/an-tao/trantor.git
|
url = https://github.com/an-tao/trantor.git
|
||||||
|
branch = master
|
||||||
|
80
.travis.yml
80
.travis.yml
@ -1,80 +0,0 @@
|
|||||||
matrix:
|
|
||||||
include:
|
|
||||||
- os: linux
|
|
||||||
dist: xenial
|
|
||||||
- os: osx
|
|
||||||
osx_image: xcode12.2
|
|
||||||
|
|
||||||
sudo: required
|
|
||||||
|
|
||||||
language: cpp
|
|
||||||
|
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
sources:
|
|
||||||
- xenial
|
|
||||||
- sourceline: 'deb http://archive.ubuntu.com/ubuntu xenial main'
|
|
||||||
- sourceline: 'ppa:mhier/libboost-latest'
|
|
||||||
packages:
|
|
||||||
- gcc
|
|
||||||
- g++
|
|
||||||
- libjsoncpp-dev
|
|
||||||
- uuid-dev
|
|
||||||
- zlib1g-dev
|
|
||||||
- postgresql-server-dev-10
|
|
||||||
- openssl
|
|
||||||
- libssl-dev
|
|
||||||
- libsqlite3-dev
|
|
||||||
- mariadb-client
|
|
||||||
- mariadb-server
|
|
||||||
- build-essential
|
|
||||||
- cmake
|
|
||||||
- boost1.67
|
|
||||||
- libbrotli-dev
|
|
||||||
homebrew:
|
|
||||||
packages:
|
|
||||||
- jsoncpp
|
|
||||||
- ossp-uuid
|
|
||||||
- openssl
|
|
||||||
- cmake
|
|
||||||
- libtool
|
|
||||||
- lz4
|
|
||||||
- mariadb
|
|
||||||
- sqlite3
|
|
||||||
update: true
|
|
||||||
mariadb: '10.0'
|
|
||||||
|
|
||||||
before_install:
|
|
||||||
- wget https://github.com/google/googletest/archive/release-1.10.0.tar.gz
|
|
||||||
- tar xf release-1.10.0.tar.gz
|
|
||||||
- cd googletest-release-1.10.0
|
|
||||||
- cmake .
|
|
||||||
- make
|
|
||||||
- sudo make install
|
|
||||||
- cd -
|
|
||||||
|
|
||||||
before_script:
|
|
||||||
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
|
||||||
brew tap homebrew/services;
|
|
||||||
brew services restart postgresql;
|
|
||||||
brew services start mariadb;
|
|
||||||
sleep 4;
|
|
||||||
mariadb -e "CREATE USER 'root'@'localhost' IDENTIFIED BY ''";
|
|
||||||
mariadb -e "SET PASSWORD FOR 'root'@'localhost' = PASSWORD('')";
|
|
||||||
mariadb -e "GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost'";
|
|
||||||
mariadb -e "FLUSH PRIVILEGES";
|
|
||||||
brew services restart mariadb;
|
|
||||||
sleep 4;
|
|
||||||
psql -c 'create user postgres superuser;' postgres;
|
|
||||||
fi
|
|
||||||
|
|
||||||
services:
|
|
||||||
- postgresql
|
|
||||||
- mysql
|
|
||||||
|
|
||||||
script:
|
|
||||||
- ./build.sh -t
|
|
||||||
- ./test.sh -t
|
|
||||||
- sudo rm /usr/local/lib/libtrantor.a && sudo rm /usr/local/lib/libdrogon.a
|
|
||||||
- ./build.sh -tshared
|
|
||||||
- ./test.sh -t
|
|
407
CMakeLists.txt
Executable file → Normal file
407
CMakeLists.txt
Executable file → Normal file
@ -1,23 +1,19 @@
|
|||||||
cmake_minimum_required(VERSION 3.5)
|
cmake_minimum_required(VERSION 3.5...3.31)
|
||||||
|
|
||||||
project(drogon)
|
project(drogon)
|
||||||
|
|
||||||
message(STATUS "compiler: " ${CMAKE_CXX_COMPILER_ID})
|
message(STATUS "compiler: " ${CMAKE_CXX_COMPILER_ID})
|
||||||
|
|
||||||
# If your cross compile is failing, you should set
|
option(BUILD_CTL "Build drogon_ctl" ON)
|
||||||
# CMAKE_SYSTEM_NAME in your toolchain file
|
option(BUILD_EXAMPLES "Build examples" ON)
|
||||||
if (NOT CMAKE_CROSSCOMPILING)
|
|
||||||
set(BUILD_PROGRAMS ON)
|
|
||||||
else ()
|
|
||||||
set(BUILD_PROGRAMS OFF)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
option(BUILD_CTL "Build drogon_ctl" ${BUILD_PROGRAMS})
|
|
||||||
option(BUILD_EXAMPLES "Build examples" ${BUILD_PROGRAMS})
|
|
||||||
option(BUILD_ORM "Build orm" ON)
|
option(BUILD_ORM "Build orm" ON)
|
||||||
option(COZ_PROFILING "Use coz for profiling" OFF)
|
option(COZ_PROFILING "Use coz for profiling" OFF)
|
||||||
option(BUILD_DROGON_SHARED "Build drogon as a shared lib" OFF)
|
option(BUILD_SHARED_LIBS "Build drogon as a shared lib" OFF)
|
||||||
option(BUILD_DOC "Build Doxygen documentation" OFF)
|
option(BUILD_DOC "Build Doxygen documentation" OFF)
|
||||||
|
option(BUILD_BROTLI "Build Brotli" ON)
|
||||||
|
option(BUILD_YAML_CONFIG "Build yaml config" ON)
|
||||||
|
option(USE_SUBMODULE "Use trantor as a submodule" ON)
|
||||||
|
option(USE_STATIC_LIBS_ONLY "Use only static libraries as dependencies" OFF)
|
||||||
|
|
||||||
include(CMakeDependentOption)
|
include(CMakeDependentOption)
|
||||||
CMAKE_DEPENDENT_OPTION(BUILD_POSTGRESQL "Build with postgresql support" ON "BUILD_ORM" OFF)
|
CMAKE_DEPENDENT_OPTION(BUILD_POSTGRESQL "Build with postgresql support" ON "BUILD_ORM" OFF)
|
||||||
@ -25,10 +21,11 @@ CMAKE_DEPENDENT_OPTION(LIBPQ_BATCH_MODE "Use batch mode for libpq" ON "BUILD_POS
|
|||||||
CMAKE_DEPENDENT_OPTION(BUILD_MYSQL "Build with mysql support" ON "BUILD_ORM" OFF)
|
CMAKE_DEPENDENT_OPTION(BUILD_MYSQL "Build with mysql support" ON "BUILD_ORM" OFF)
|
||||||
CMAKE_DEPENDENT_OPTION(BUILD_SQLITE "Build with sqlite3 support" ON "BUILD_ORM" OFF)
|
CMAKE_DEPENDENT_OPTION(BUILD_SQLITE "Build with sqlite3 support" ON "BUILD_ORM" OFF)
|
||||||
CMAKE_DEPENDENT_OPTION(BUILD_REDIS "Build with redis support" ON "BUILD_ORM" OFF)
|
CMAKE_DEPENDENT_OPTION(BUILD_REDIS "Build with redis support" ON "BUILD_ORM" OFF)
|
||||||
|
CMAKE_DEPENDENT_OPTION(USE_SPDLOG "Allow using the spdlog logging library" OFF "USE_SUBMODULE" OFF)
|
||||||
|
|
||||||
set(DROGON_MAJOR_VERSION 1)
|
set(DROGON_MAJOR_VERSION 1)
|
||||||
set(DROGON_MINOR_VERSION 7)
|
set(DROGON_MINOR_VERSION 9)
|
||||||
set(DROGON_PATCH_VERSION 2)
|
set(DROGON_PATCH_VERSION 11)
|
||||||
set(DROGON_VERSION
|
set(DROGON_VERSION
|
||||||
${DROGON_MAJOR_VERSION}.${DROGON_MINOR_VERSION}.${DROGON_PATCH_VERSION})
|
${DROGON_MAJOR_VERSION}.${DROGON_MINOR_VERSION}.${DROGON_PATCH_VERSION})
|
||||||
set(DROGON_VERSION_STRING "${DROGON_VERSION}")
|
set(DROGON_VERSION_STRING "${DROGON_VERSION}")
|
||||||
@ -43,16 +40,21 @@ set(INSTALL_DROGON_CMAKE_DIR ${DEF_INSTALL_DROGON_CMAKE_DIR}
|
|||||||
CACHE PATH "Installation directory for cmake files")
|
CACHE PATH "Installation directory for cmake files")
|
||||||
|
|
||||||
if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
|
if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
|
||||||
# Force MSVC to use UTF-8 because that's what we use. Otherwise it uses
|
# Force MSVC to use UTF-8 because that's what we use. Otherwise it uses
|
||||||
# the default of whatever Windows sets and causes encoding issues.
|
# the default of whatever Windows sets and causes encoding issues.
|
||||||
message(STATUS "You are using MSVC. Forceing to use UTF-8")
|
message(STATUS "You are using MSVC. Forcing to use UTF-8")
|
||||||
add_compile_options("$<$<C_COMPILER_ID:MSVC>:/utf-8>")
|
add_compile_options("$<$<C_COMPILER_ID:MSVC>:/utf-8>")
|
||||||
add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/utf-8>")
|
add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/utf-8>")
|
||||||
|
if (MSVC_VERSION GREATER_EQUAL 1914)
|
||||||
|
# Tells Visual Studio 2017 (15.7+) and newer to correctly set the value of the standard __cplusplus macro,
|
||||||
|
# instead of leaving it to 199711L and settings the effective c++ version in _MSVC_LANG
|
||||||
|
# Dropping support for older versions of VS would allow to only rely on __cplusplus
|
||||||
|
add_compile_options("/Zc:__cplusplus")
|
||||||
|
endif()
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (BUILD_DROGON_SHARED)
|
add_library(${PROJECT_NAME})
|
||||||
set(BUILD_TRANTOR_SHARED TRUE)
|
if (BUILD_SHARED_LIBS)
|
||||||
set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
|
|
||||||
find_package(Threads)
|
find_package(Threads)
|
||||||
# set(BUILD_EXAMPLES FALSE)
|
# set(BUILD_EXAMPLES FALSE)
|
||||||
list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES
|
list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES
|
||||||
@ -60,13 +62,12 @@ if (BUILD_DROGON_SHARED)
|
|||||||
if ("${isSystemDir}" STREQUAL "-1")
|
if ("${isSystemDir}" STREQUAL "-1")
|
||||||
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${INSTALL_LIB_DIR}")
|
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${INSTALL_LIB_DIR}")
|
||||||
endif ("${isSystemDir}" STREQUAL "-1")
|
endif ("${isSystemDir}" STREQUAL "-1")
|
||||||
add_library(${PROJECT_NAME} SHARED)
|
|
||||||
set_target_properties(${PROJECT_NAME} PROPERTIES
|
set_target_properties(${PROJECT_NAME} PROPERTIES
|
||||||
VERSION ${DROGON_VERSION}
|
VERSION ${DROGON_VERSION}
|
||||||
SOVERSION ${DROGON_MAJOR_VERSION})
|
SOVERSION ${DROGON_MAJOR_VERSION})
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC Threads::Threads)
|
target_link_libraries(${PROJECT_NAME} PUBLIC Threads::Threads)
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC Rpcrt4 ws2_32 crypt32 Advapi32)
|
target_link_libraries(${PROJECT_NAME} PUBLIC rpcrt4 crypt32 advapi32 ws2_32)
|
||||||
if (CMAKE_CXX_COMPILER_ID MATCHES MSVC)
|
if (CMAKE_CXX_COMPILER_ID MATCHES MSVC)
|
||||||
# Ignore MSVC C4251 and C4275 warning of exporting std objects with no dll export
|
# Ignore MSVC C4251 and C4275 warning of exporting std objects with no dll export
|
||||||
# We export class to facilitate maintenance, thus if you compile
|
# We export class to facilitate maintenance, thus if you compile
|
||||||
@ -75,9 +76,20 @@ if (BUILD_DROGON_SHARED)
|
|||||||
target_compile_options(${PROJECT_NAME} PUBLIC /wd4251 /wd4275)
|
target_compile_options(${PROJECT_NAME} PUBLIC /wd4251 /wd4275)
|
||||||
endif ()
|
endif ()
|
||||||
endif ()
|
endif ()
|
||||||
else (BUILD_DROGON_SHARED)
|
endif (BUILD_SHARED_LIBS)
|
||||||
add_library(${PROJECT_NAME} STATIC)
|
|
||||||
endif (BUILD_DROGON_SHARED)
|
if(USE_STATIC_LIBS_ONLY)
|
||||||
|
set(CMAKE_FIND_LIBRARY_SUFFIXES "${CMAKE_STATIC_LIBRARY_SUFFIX}")
|
||||||
|
endif(USE_STATIC_LIBS_ONLY)
|
||||||
|
|
||||||
|
if(USE_SPDLOG)
|
||||||
|
find_package(spdlog CONFIG)
|
||||||
|
if(spdlog_FOUND)
|
||||||
|
message(STATUS "spdlog found!")
|
||||||
|
target_link_libraries(${PROJECT_NAME} PUBLIC spdlog::spdlog_header_only)
|
||||||
|
target_compile_definitions(${PROJECT_NAME} PUBLIC DROGON_SPDLOG_SUPPORT SPDLOG_FMT_EXTERNAL FMT_HEADER_ONLY)
|
||||||
|
endif(spdlog_FOUND)
|
||||||
|
endif(USE_SPDLOG)
|
||||||
|
|
||||||
if (NOT ${CMAKE_PLATFORM_NAME} STREQUAL "Windows" AND CMAKE_CXX_COMPILER_ID MATCHES GNU)
|
if (NOT ${CMAKE_PLATFORM_NAME} STREQUAL "Windows" AND CMAKE_CXX_COMPILER_ID MATCHES GNU)
|
||||||
target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra -Werror)
|
target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra -Werror)
|
||||||
@ -97,19 +109,22 @@ if (NOT "${CMAKE_CXX_STANDARD}" STREQUAL "")
|
|||||||
set(DROGON_CXX_STANDARD ${CMAKE_CXX_STANDARD})
|
set(DROGON_CXX_STANDARD ${CMAKE_CXX_STANDARD})
|
||||||
elseif (HAS_ANY AND HAS_STRING_VIEW AND HAS_COROUTINE)
|
elseif (HAS_ANY AND HAS_STRING_VIEW AND HAS_COROUTINE)
|
||||||
set(DROGON_CXX_STANDARD 20)
|
set(DROGON_CXX_STANDARD 20)
|
||||||
elseif (HAS_ANY AND HAS_STRING_VIEW)
|
|
||||||
set(DROGON_CXX_STANDARD 17)
|
|
||||||
else ()
|
else ()
|
||||||
set(DROGON_CXX_STANDARD 14)
|
set(DROGON_CXX_STANDARD 17)
|
||||||
endif ()
|
endif ()
|
||||||
|
if(USE_SUBMODULE)
|
||||||
|
target_include_directories(
|
||||||
|
${PROJECT_NAME}
|
||||||
|
PUBLIC
|
||||||
|
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/trantor>)
|
||||||
|
endif()
|
||||||
target_include_directories(
|
target_include_directories(
|
||||||
${PROJECT_NAME}
|
${PROJECT_NAME}
|
||||||
PUBLIC $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/lib/inc>
|
PUBLIC $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/lib/inc>
|
||||||
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/lib/inc>
|
||||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/orm_lib/inc>
|
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/orm_lib/inc>
|
||||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/nosql_lib/redis/inc>
|
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/nosql_lib/redis/inc>
|
||||||
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}>
|
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}>
|
||||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/trantor>
|
|
||||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/exports>
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/exports>
|
||||||
$<INSTALL_INTERFACE:${INSTALL_INCLUDE_DIR}>)
|
$<INSTALL_INTERFACE:${INSTALL_INCLUDE_DIR}>)
|
||||||
|
|
||||||
@ -119,85 +134,88 @@ if (WIN32)
|
|||||||
PRIVATE $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/third_party/mman-win32>)
|
PRIVATE $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/third_party/mman-win32>)
|
||||||
endif (WIN32)
|
endif (WIN32)
|
||||||
|
|
||||||
|
if(USE_SUBMODULE)
|
||||||
add_subdirectory(trantor)
|
add_subdirectory(trantor)
|
||||||
|
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC trantor)
|
target_link_libraries(${PROJECT_NAME} PUBLIC trantor)
|
||||||
|
else()
|
||||||
|
find_package(Trantor CONFIG REQUIRED)
|
||||||
|
target_link_libraries(${PROJECT_NAME} PUBLIC Trantor::Trantor)
|
||||||
|
endif()
|
||||||
|
|
||||||
if (NOT WIN32)
|
if(${CMAKE_SYSTEM_NAME} STREQUAL "Haiku")
|
||||||
if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD")
|
target_link_libraries(${PROJECT_NAME} PRIVATE network)
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE dl)
|
elseif (NOT WIN32 AND NOT ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD")
|
||||||
endif (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD")
|
target_link_libraries(${PROJECT_NAME} PRIVATE dl)
|
||||||
else (NOT WIN32)
|
elseif (WIN32)
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE shlwapi)
|
target_link_libraries(${PROJECT_NAME} PRIVATE shlwapi ws2_32 iphlpapi)
|
||||||
endif (NOT WIN32)
|
endif ()
|
||||||
|
|
||||||
list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake_modules/)
|
list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake_modules/)
|
||||||
|
|
||||||
find_package(Filesystem COMPONENTS Final)
|
find_package(Filesystem COMPONENTS Final)
|
||||||
if(CXX_FILESYSTEM_HAVE_FS)
|
if(CXX_FILESYSTEM_HAVE_FS)
|
||||||
message(STATUS "Found std::filesystem")
|
message(STATUS "Found std::filesystem")
|
||||||
|
else ()
|
||||||
|
message(FATAL_ERROR "Not found std::filesystem, please use a newer compiler")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Check for C++ filesystem support
|
if (DROGON_CXX_STANDARD EQUAL 17)
|
||||||
set(NEED_BOOST_FS 0)
|
|
||||||
if (DROGON_CXX_STANDARD EQUAL 14)
|
|
||||||
# With C++14, use Boost to support any and string_view
|
|
||||||
message(STATUS "use c++14")
|
|
||||||
find_package(Boost 1.61.0 REQUIRED)
|
|
||||||
message(STATUS "Using Boost filesystem, string_view and any")
|
|
||||||
message(STATUS "Boost include dir: " ${Boost_INCLUDE_DIR})
|
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC Boost::boost)
|
|
||||||
list(APPEND INCLUDE_DIRS_FOR_DYNAMIC_VIEW ${Boost_INCLUDE_DIR})
|
|
||||||
set(NEED_BOOST_FS 1)
|
|
||||||
elseif (DROGON_CXX_STANDARD EQUAL 17)
|
|
||||||
# With C++17, use Boost if std::filesystem::path is missing
|
|
||||||
message(STATUS "use c++17")
|
message(STATUS "use c++17")
|
||||||
|
|
||||||
# Check for partial implementation of c++17 (Windows/OSX only?)
|
# Check for partial implementation of c++17 (Windows/OSX only?)
|
||||||
if (CXX_FILESYSTEM_HAVE_FS)
|
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
|
||||||
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
|
try_compile(check_filesystem_path ${CMAKE_BINARY_DIR}/cmaketest
|
||||||
try_compile(check_filesystem_path ${CMAKE_BINARY_DIR}/cmaketest
|
${PROJECT_SOURCE_DIR}/cmake/tests/check_has_std_filesystem_path.cc
|
||||||
${PROJECT_SOURCE_DIR}/cmake/tests/check_has_std_filesystem_path.cc
|
CXX_STANDARD 17)
|
||||||
CXX_STANDARD 17)
|
set(CMAKE_TRY_COMPILE_TARGET_TYPE)
|
||||||
set(CMAKE_TRY_COMPILE_TARGET_TYPE)
|
if (NOT check_filesystem_path)
|
||||||
if (NOT check_filesystem_path)
|
message(FATAL_ERROR "The std::filesystem seems to be a partial implementation,"
|
||||||
message(STATUS "The std::filesystem seems to be a partial implementation"
|
" please use a newer compiler")
|
||||||
" Falling back to boost::filesystem")
|
|
||||||
set(NEED_BOOST_FS 1)
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
set(NEED_BOOST_FS 1)
|
|
||||||
endif()
|
endif()
|
||||||
else ()
|
else ()
|
||||||
message(STATUS "use c++20")
|
message(STATUS "use c++20")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
# Workaround: 2021-08-09 Android NDK does not provide proper std::filesystem
|
|
||||||
# support. Force boost::filesystem instead.
|
|
||||||
if (${CMAKE_SYSTEM_NAME} STREQUAL "Android")
|
|
||||||
message(STATUS "WORKAROUND: Forcing boost::filesystem on Android")
|
|
||||||
set(NEED_BOOST_FS 1)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if(NEED_BOOST_FS)
|
option(HAS_STD_FILESYSTEM_PATH "use std::filesystem" ON)
|
||||||
find_package(Boost 1.49.0 COMPONENTS filesystem system REQUIRED)
|
# HACK: Needed to be compiled on Yocto Linux
|
||||||
message(STATUS "Using Boost filesytem::path")
|
if(TARGET std::filesystem)
|
||||||
message(STATUS "Boost include dir: " ${Boost_INCLUDE_DIR})
|
get_property(CAN_LINK_FS TARGET std::filesystem PROPERTY INTERFACE_LINK_LIBRARIES SET)
|
||||||
include_directories(${BOOST_INCLUDE_DIRS})
|
if ( CAN_LINK_FS )
|
||||||
message(STATUS "Boost libraries: " ${Boost_LIBRARIES})
|
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC Boost::filesystem Boost::system)
|
|
||||||
list(APPEND INCLUDE_DIRS_FOR_DYNAMIC_VIEW ${Boost_INCLUDE_DIR})
|
|
||||||
option(HAS_STD_FILESYSTEM_PATH "use boost::filesystem" OFF)
|
|
||||||
else()
|
|
||||||
option(HAS_STD_FILESYSTEM_PATH "use std::filesystem" ON)
|
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC std::filesystem)
|
target_link_libraries(${PROJECT_NAME} PUBLIC std::filesystem)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
# jsoncpp
|
# jsoncpp
|
||||||
find_package(Jsoncpp REQUIRED)
|
find_package(Jsoncpp REQUIRED)
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC Jsoncpp_lib)
|
target_link_libraries(${PROJECT_NAME} PUBLIC Jsoncpp_lib)
|
||||||
list(APPEND INCLUDE_DIRS_FOR_DYNAMIC_VIEW ${JSONCPP_INCLUDE_DIRS})
|
list(APPEND INCLUDE_DIRS_FOR_DYNAMIC_VIEW ${JSONCPP_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
# yamlcpp
|
||||||
|
if(BUILD_YAML_CONFIG)
|
||||||
|
find_package(yaml-cpp QUIET)
|
||||||
|
if(yaml-cpp_FOUND)
|
||||||
|
if (NOT YAML_CPP_LIBRARIES)
|
||||||
|
find_library(YAML_CPP_LINK_LIBRARY "yaml-cpp")
|
||||||
|
if(NOT YAML_CPP_LINK_LIBRARY)
|
||||||
|
message(STATUS "yaml-cpp not used")
|
||||||
|
else()
|
||||||
|
message(STATUS "yaml-cpp found ")
|
||||||
|
target_link_libraries(${PROJECT_NAME} PUBLIC ${YAML_CPP_LINK_LIBRARY})
|
||||||
|
target_compile_definitions(${PROJECT_NAME} PUBLIC HAS_YAML_CPP)
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
message(STATUS "yaml-cpp found ")
|
||||||
|
target_link_libraries(${PROJECT_NAME} PUBLIC ${YAML_CPP_LIBRARIES})
|
||||||
|
target_compile_definitions(${PROJECT_NAME} PUBLIC HAS_YAML_CPP)
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
message(STATUS "yaml-cpp not used")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
message(STATUS "yaml-cpp not used")
|
||||||
|
endif(BUILD_YAML_CONFIG)
|
||||||
|
|
||||||
if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD"
|
if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD"
|
||||||
AND NOT ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD"
|
AND NOT ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD"
|
||||||
AND NOT WIN32)
|
AND NOT WIN32)
|
||||||
@ -206,73 +224,97 @@ if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD"
|
|||||||
|
|
||||||
try_compile(normal_uuid ${CMAKE_BINARY_DIR}/cmaketest
|
try_compile(normal_uuid ${CMAKE_BINARY_DIR}/cmaketest
|
||||||
${PROJECT_SOURCE_DIR}/cmake/tests/normal_uuid_lib_test.cc
|
${PROJECT_SOURCE_DIR}/cmake/tests/normal_uuid_lib_test.cc
|
||||||
LINK_LIBRARIES UUID_lib)
|
LINK_LIBRARIES UUID_lib
|
||||||
|
OUTPUT_VARIABLE NORMAL_UUID_COMPILE_OUTPUT)
|
||||||
try_compile(ossp_uuid ${CMAKE_BINARY_DIR}/cmaketest
|
try_compile(ossp_uuid ${CMAKE_BINARY_DIR}/cmaketest
|
||||||
${PROJECT_SOURCE_DIR}/cmake/tests/ossp_uuid_lib_test.cc
|
${PROJECT_SOURCE_DIR}/cmake/tests/ossp_uuid_lib_test.cc
|
||||||
LINK_LIBRARIES UUID_lib)
|
LINK_LIBRARIES UUID_lib
|
||||||
|
OUTPUT_VARIABLE OSSP_UUID_COMPILE_OUTPUT)
|
||||||
if (normal_uuid)
|
if (normal_uuid)
|
||||||
add_definitions(-DUSE_OSSP_UUID=0)
|
add_definitions(-DUSE_OSSP_UUID=0)
|
||||||
elseif (ossp_uuid)
|
elseif (ossp_uuid)
|
||||||
add_definitions(-DUSE_OSSP_UUID=1)
|
add_definitions(-DUSE_OSSP_UUID=1)
|
||||||
else ()
|
else ()
|
||||||
message(FATAL_ERROR "uuid lib error")
|
message(FATAL_ERROR "uuid lib error:\n${NORMAL_UUID_COMPILE_OUTPUT}\n${OSSP_UUID_COMPILE_OUTPUT}")
|
||||||
endif ()
|
endif ()
|
||||||
endif (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD"
|
endif (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD"
|
||||||
AND NOT ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD"
|
AND NOT ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD"
|
||||||
AND NOT WIN32)
|
AND NOT WIN32)
|
||||||
|
|
||||||
find_package(Brotli)
|
if (BUILD_BROTLI)
|
||||||
if (Brotli_FOUND)
|
find_package(Brotli)
|
||||||
message(STATUS "Brotli found")
|
if (Brotli_FOUND)
|
||||||
add_definitions(-DUSE_BROTLI)
|
message(STATUS "Brotli found")
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE Brotli_lib)
|
add_definitions(-DUSE_BROTLI)
|
||||||
endif (Brotli_FOUND)
|
target_link_libraries(${PROJECT_NAME} PRIVATE Brotli_lib)
|
||||||
|
endif (Brotli_FOUND)
|
||||||
|
endif (BUILD_BROTLI)
|
||||||
|
|
||||||
set(DROGON_SOURCES
|
set(DROGON_SOURCES
|
||||||
lib/src/AOPAdvice.cc
|
lib/src/AOPAdvice.cc
|
||||||
|
lib/src/AccessLogger.cc
|
||||||
lib/src/CacheFile.cc
|
lib/src/CacheFile.cc
|
||||||
|
lib/src/ConfigAdapterManager.cc
|
||||||
lib/src/ConfigLoader.cc
|
lib/src/ConfigLoader.cc
|
||||||
lib/src/Cookie.cc
|
lib/src/Cookie.cc
|
||||||
lib/src/DrClassMap.cc
|
lib/src/DrClassMap.cc
|
||||||
lib/src/DrTemplateBase.cc
|
lib/src/DrTemplateBase.cc
|
||||||
lib/src/FiltersFunction.cc
|
lib/src/MiddlewaresFunction.cc
|
||||||
|
lib/src/FixedWindowRateLimiter.cc
|
||||||
|
lib/src/GlobalFilters.cc
|
||||||
|
lib/src/Histogram.cc
|
||||||
|
lib/src/Hodor.cc
|
||||||
lib/src/HttpAppFrameworkImpl.cc
|
lib/src/HttpAppFrameworkImpl.cc
|
||||||
lib/src/HttpBinder.cc
|
lib/src/HttpBinder.cc
|
||||||
lib/src/HttpClientImpl.cc
|
lib/src/HttpClientImpl.cc
|
||||||
|
lib/src/HttpConnectionLimit.cc
|
||||||
|
lib/src/HttpControllerBinder.cc
|
||||||
lib/src/HttpControllersRouter.cc
|
lib/src/HttpControllersRouter.cc
|
||||||
lib/src/HttpFileImpl.cc
|
lib/src/HttpFileImpl.cc
|
||||||
lib/src/HttpFileUploadRequest.cc
|
lib/src/HttpFileUploadRequest.cc
|
||||||
lib/src/HttpRequestImpl.cc
|
lib/src/HttpRequestImpl.cc
|
||||||
lib/src/HttpRequestParser.cc
|
lib/src/HttpRequestParser.cc
|
||||||
|
lib/src/RequestStream.cc
|
||||||
lib/src/HttpResponseImpl.cc
|
lib/src/HttpResponseImpl.cc
|
||||||
lib/src/HttpResponseParser.cc
|
lib/src/HttpResponseParser.cc
|
||||||
lib/src/HttpServer.cc
|
lib/src/HttpServer.cc
|
||||||
lib/src/HttpSimpleControllersRouter.cc
|
|
||||||
lib/src/HttpUtils.cc
|
lib/src/HttpUtils.cc
|
||||||
lib/src/HttpViewData.cc
|
lib/src/HttpViewData.cc
|
||||||
lib/src/IntranetIpFilter.cc
|
lib/src/IntranetIpFilter.cc
|
||||||
|
lib/src/JsonConfigAdapter.cc
|
||||||
lib/src/ListenerManager.cc
|
lib/src/ListenerManager.cc
|
||||||
lib/src/LocalHostFilter.cc
|
lib/src/LocalHostFilter.cc
|
||||||
lib/src/MultiPart.cc
|
lib/src/MultiPart.cc
|
||||||
|
lib/src/MultipartStreamParser.cc
|
||||||
lib/src/NotFound.cc
|
lib/src/NotFound.cc
|
||||||
lib/src/PluginsManager.cc
|
lib/src/PluginsManager.cc
|
||||||
|
lib/src/PromExporter.cc
|
||||||
|
lib/src/RangeParser.cc
|
||||||
|
lib/src/RateLimiter.cc
|
||||||
|
lib/src/RealIpResolver.cc
|
||||||
lib/src/SecureSSLRedirector.cc
|
lib/src/SecureSSLRedirector.cc
|
||||||
lib/src/AccessLogger.cc
|
lib/src/Redirector.cc
|
||||||
lib/src/SessionManager.cc
|
lib/src/SessionManager.cc
|
||||||
|
lib/src/SlashRemover.cc
|
||||||
|
lib/src/SlidingWindowRateLimiter.cc
|
||||||
lib/src/StaticFileRouter.cc
|
lib/src/StaticFileRouter.cc
|
||||||
lib/src/TaskTimeoutFlag.cc
|
lib/src/TaskTimeoutFlag.cc
|
||||||
|
lib/src/TokenBucketRateLimiter.cc
|
||||||
lib/src/Utilities.cc
|
lib/src/Utilities.cc
|
||||||
lib/src/WebSocketClientImpl.cc
|
lib/src/WebSocketClientImpl.cc
|
||||||
lib/src/WebSocketConnectionImpl.cc
|
lib/src/WebSocketConnectionImpl.cc
|
||||||
lib/src/WebsocketControllersRouter.cc)
|
lib/src/YamlConfigAdapter.cc
|
||||||
|
lib/src/drogon_test.cc)
|
||||||
set(private_headers
|
set(private_headers
|
||||||
lib/src/AOPAdvice.h
|
lib/src/AOPAdvice.h
|
||||||
lib/src/CacheFile.h
|
lib/src/CacheFile.h
|
||||||
lib/src/ConfigLoader.h
|
lib/src/ConfigLoader.h
|
||||||
lib/src/filesystem.h
|
lib/src/ControllerBinderBase.h
|
||||||
lib/src/FiltersFunction.h
|
lib/src/MiddlewaresFunction.h
|
||||||
lib/src/HttpAppFrameworkImpl.h
|
lib/src/HttpAppFrameworkImpl.h
|
||||||
lib/src/HttpClientImpl.h
|
lib/src/HttpClientImpl.h
|
||||||
|
lib/src/HttpConnectionLimit.h
|
||||||
|
lib/src/HttpControllerBinder.h
|
||||||
lib/src/HttpControllersRouter.h
|
lib/src/HttpControllersRouter.h
|
||||||
lib/src/HttpFileImpl.h
|
lib/src/HttpFileImpl.h
|
||||||
lib/src/HttpFileUploadRequest.h
|
lib/src/HttpFileUploadRequest.h
|
||||||
@ -282,7 +324,6 @@ set(private_headers
|
|||||||
lib/src/HttpResponseImpl.h
|
lib/src/HttpResponseImpl.h
|
||||||
lib/src/HttpResponseParser.h
|
lib/src/HttpResponseParser.h
|
||||||
lib/src/HttpServer.h
|
lib/src/HttpServer.h
|
||||||
lib/src/HttpSimpleControllersRouter.h
|
|
||||||
lib/src/HttpUtils.h
|
lib/src/HttpUtils.h
|
||||||
lib/src/impl_forwards.h
|
lib/src/impl_forwards.h
|
||||||
lib/src/ListenerManager.h
|
lib/src/ListenerManager.h
|
||||||
@ -293,23 +334,30 @@ set(private_headers
|
|||||||
lib/src/TaskTimeoutFlag.h
|
lib/src/TaskTimeoutFlag.h
|
||||||
lib/src/WebSocketClientImpl.h
|
lib/src/WebSocketClientImpl.h
|
||||||
lib/src/WebSocketConnectionImpl.h
|
lib/src/WebSocketConnectionImpl.h
|
||||||
lib/src/WebsocketControllersRouter.h)
|
lib/src/FixedWindowRateLimiter.h
|
||||||
|
lib/src/SlidingWindowRateLimiter.h
|
||||||
|
lib/src/TokenBucketRateLimiter.h
|
||||||
|
lib/src/ConfigAdapterManager.h
|
||||||
|
lib/src/JsonConfigAdapter.h
|
||||||
|
lib/src/YamlConfigAdapter.h
|
||||||
|
lib/src/ConfigAdapter.h
|
||||||
|
lib/src/MultipartStreamParser.h)
|
||||||
|
|
||||||
if (NOT WIN32)
|
if (NOT WIN32 AND NOT CMAKE_SYSTEM_NAME STREQUAL "iOS")
|
||||||
set(DROGON_SOURCES
|
set(DROGON_SOURCES
|
||||||
${DROGON_SOURCES}
|
${DROGON_SOURCES}
|
||||||
lib/src/SharedLibManager.cc)
|
lib/src/SharedLibManager.cc)
|
||||||
set(private_headers
|
set(private_headers
|
||||||
${private_headers}
|
${private_headers}
|
||||||
lib/src/SharedLibManager.h)
|
lib/src/SharedLibManager.h)
|
||||||
else (NOT WIN32)
|
elseif(WIN32)
|
||||||
set(DROGON_SOURCES
|
set(DROGON_SOURCES
|
||||||
${DROGON_SOURCES}
|
${DROGON_SOURCES}
|
||||||
third_party/mman-win32/mman.c)
|
third_party/mman-win32/mman.c)
|
||||||
set(private_headers
|
set(private_headers
|
||||||
${private_headers}
|
${private_headers}
|
||||||
third_party/mman-win32/mman.h)
|
third_party/mman-win32/mman.h)
|
||||||
endif (NOT WIN32)
|
endif()
|
||||||
|
|
||||||
if (BUILD_POSTGRESQL)
|
if (BUILD_POSTGRESQL)
|
||||||
# find postgres
|
# find postgres
|
||||||
@ -320,10 +368,12 @@ if (BUILD_POSTGRESQL)
|
|||||||
target_link_libraries(${PROJECT_NAME} PRIVATE pg_lib)
|
target_link_libraries(${PROJECT_NAME} PRIVATE pg_lib)
|
||||||
set(DROGON_SOURCES
|
set(DROGON_SOURCES
|
||||||
${DROGON_SOURCES}
|
${DROGON_SOURCES}
|
||||||
orm_lib/src/postgresql_impl/PostgreSQLResultImpl.cc)
|
orm_lib/src/postgresql_impl/PostgreSQLResultImpl.cc
|
||||||
|
orm_lib/src/postgresql_impl/PgListener.cc)
|
||||||
set(private_headers
|
set(private_headers
|
||||||
${private_headers}
|
${private_headers}
|
||||||
orm_lib/src/postgresql_impl/PostgreSQLResultImpl.h)
|
orm_lib/src/postgresql_impl/PostgreSQLResultImpl.h
|
||||||
|
orm_lib/src/postgresql_impl/PgListener.h)
|
||||||
if (LIBPQ_BATCH_MODE)
|
if (LIBPQ_BATCH_MODE)
|
||||||
try_compile(libpq_supports_batch ${CMAKE_BINARY_DIR}/cmaketest
|
try_compile(libpq_supports_batch ${CMAKE_BINARY_DIR}/cmaketest
|
||||||
${PROJECT_SOURCE_DIR}/cmake/tests/test_libpq_batch_mode.cc
|
${PROJECT_SOURCE_DIR}/cmake/tests/test_libpq_batch_mode.cc
|
||||||
@ -349,11 +399,28 @@ if (BUILD_POSTGRESQL)
|
|||||||
endif (BUILD_POSTGRESQL)
|
endif (BUILD_POSTGRESQL)
|
||||||
|
|
||||||
if (BUILD_MYSQL)
|
if (BUILD_MYSQL)
|
||||||
# Find mysql, only mariadb client liberary is supported
|
# Find mysql, only mariadb client library is supported
|
||||||
find_package(MySQL)
|
find_package(MySQL QUIET)
|
||||||
|
find_package(unofficial-libmariadb QUIET)
|
||||||
if (MySQL_FOUND)
|
if (MySQL_FOUND)
|
||||||
message(STATUS "Ok! We find the mariadb!")
|
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE MySQL_lib)
|
target_link_libraries(${PROJECT_NAME} PRIVATE MySQL_lib)
|
||||||
|
set(DROGON_FOUND_MYSQL TRUE)
|
||||||
|
set(MYSQL_LIB_NAME MySQL_lib)
|
||||||
|
elseif (unofficial-libmariadb_FOUND)
|
||||||
|
target_link_libraries(${PROJECT_NAME} PRIVATE unofficial::libmariadb)
|
||||||
|
set(DROGON_FOUND_MYSQL TRUE)
|
||||||
|
set(MYSQL_LIB_NAME unofficial::libmariadb)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (DROGON_FOUND_MYSQL)
|
||||||
|
message(STATUS "Ok! We find mariadb!")
|
||||||
|
include(CheckLibraryExists)
|
||||||
|
check_library_exists(${MYSQL_LIB_NAME} mysql_optionsv "" HAS_MYSQL_OPTIONSV)
|
||||||
|
if (HAS_MYSQL_OPTIONSV)
|
||||||
|
message(STATUS "Mariadb support mysql_optionsv")
|
||||||
|
add_definitions(-DHAS_MYSQL_OPTIONSV)
|
||||||
|
endif(HAS_MYSQL_OPTIONSV)
|
||||||
|
|
||||||
set(DROGON_SOURCES
|
set(DROGON_SOURCES
|
||||||
${DROGON_SOURCES}
|
${DROGON_SOURCES}
|
||||||
orm_lib/src/mysql_impl/MysqlConnection.cc
|
orm_lib/src/mysql_impl/MysqlConnection.cc
|
||||||
@ -362,14 +429,25 @@ if (BUILD_MYSQL)
|
|||||||
${private_headers}
|
${private_headers}
|
||||||
orm_lib/src/mysql_impl/MysqlConnection.h
|
orm_lib/src/mysql_impl/MysqlConnection.h
|
||||||
orm_lib/src/mysql_impl/MysqlResultImpl.h)
|
orm_lib/src/mysql_impl/MysqlResultImpl.h)
|
||||||
endif (MySQL_FOUND)
|
else (DROGON_FOUND_MYSQL)
|
||||||
|
message(STATUS "MySql was not found.")
|
||||||
|
endif (DROGON_FOUND_MYSQL)
|
||||||
endif (BUILD_MYSQL)
|
endif (BUILD_MYSQL)
|
||||||
|
|
||||||
if (BUILD_SQLITE)
|
if (BUILD_SQLITE)
|
||||||
# Find sqlite3.
|
# Find sqlite3.
|
||||||
find_package(SQLite3)
|
find_package(SQLite3 QUIET)
|
||||||
|
find_package(unofficial-sqlite3 QUIET)
|
||||||
if (SQLite3_FOUND)
|
if (SQLite3_FOUND)
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE SQLite3_lib)
|
target_link_libraries(${PROJECT_NAME} PRIVATE SQLite3_lib)
|
||||||
|
set(DROGON_FOUND_SQLite3 TRUE)
|
||||||
|
elseif (unofficial-sqlite3_FOUND)
|
||||||
|
target_link_libraries(${PROJECT_NAME} PRIVATE unofficial::sqlite3::sqlite3)
|
||||||
|
set(DROGON_FOUND_SQLite3 TRUE)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (DROGON_FOUND_SQLite3)
|
||||||
|
message(STATUS "Ok! We find sqlite3!")
|
||||||
set(DROGON_SOURCES
|
set(DROGON_SOURCES
|
||||||
${DROGON_SOURCES}
|
${DROGON_SOURCES}
|
||||||
orm_lib/src/sqlite3_impl/Sqlite3Connection.cc
|
orm_lib/src/sqlite3_impl/Sqlite3Connection.cc
|
||||||
@ -378,7 +456,9 @@ if (BUILD_SQLITE)
|
|||||||
${private_headers}
|
${private_headers}
|
||||||
orm_lib/src/sqlite3_impl/Sqlite3Connection.h
|
orm_lib/src/sqlite3_impl/Sqlite3Connection.h
|
||||||
orm_lib/src/sqlite3_impl/Sqlite3ResultImpl.h)
|
orm_lib/src/sqlite3_impl/Sqlite3ResultImpl.h)
|
||||||
endif (SQLite3_FOUND)
|
else (DROGON_FOUND_SQLite3)
|
||||||
|
message(STATUS "sqlite3 was not found.")
|
||||||
|
endif (DROGON_FOUND_SQLite3)
|
||||||
endif (BUILD_SQLITE)
|
endif (BUILD_SQLITE)
|
||||||
|
|
||||||
if (BUILD_REDIS)
|
if (BUILD_REDIS)
|
||||||
@ -393,13 +473,17 @@ if (BUILD_REDIS)
|
|||||||
nosql_lib/redis/src/RedisClientManager.cc
|
nosql_lib/redis/src/RedisClientManager.cc
|
||||||
nosql_lib/redis/src/RedisConnection.cc
|
nosql_lib/redis/src/RedisConnection.cc
|
||||||
nosql_lib/redis/src/RedisResult.cc
|
nosql_lib/redis/src/RedisResult.cc
|
||||||
nosql_lib/redis/src/RedisTransactionImpl.cc)
|
nosql_lib/redis/src/RedisTransactionImpl.cc
|
||||||
|
nosql_lib/redis/src/SubscribeContext.cc
|
||||||
|
nosql_lib/redis/src/RedisSubscriberImpl.cc)
|
||||||
set(private_headers
|
set(private_headers
|
||||||
${private_headers}
|
${private_headers}
|
||||||
nosql_lib/redis/src/RedisClientImpl.h
|
nosql_lib/redis/src/RedisClientImpl.h
|
||||||
nosql_lib/redis/src/RedisClientLockFree.h
|
nosql_lib/redis/src/RedisClientLockFree.h
|
||||||
nosql_lib/redis/src/RedisConnection.h
|
nosql_lib/redis/src/RedisConnection.h
|
||||||
nosql_lib/redis/src/RedisTransactionImpl.h)
|
nosql_lib/redis/src/RedisTransactionImpl.h
|
||||||
|
nosql_lib/redis/src/SubscribeContext.h
|
||||||
|
nosql_lib/redis/src/RedisSubscriberImpl.h)
|
||||||
|
|
||||||
endif (Hiredis_FOUND)
|
endif (Hiredis_FOUND)
|
||||||
endif (BUILD_REDIS)
|
endif (BUILD_REDIS)
|
||||||
@ -422,26 +506,12 @@ endif (BUILD_TESTING)
|
|||||||
find_package(ZLIB REQUIRED)
|
find_package(ZLIB REQUIRED)
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE ZLIB::ZLIB)
|
target_link_libraries(${PROJECT_NAME} PRIVATE ZLIB::ZLIB)
|
||||||
|
|
||||||
find_package(OpenSSL)
|
|
||||||
if (OpenSSL_FOUND)
|
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE OpenSSL::SSL OpenSSL::Crypto)
|
|
||||||
else (OpenSSL_FOUND)
|
|
||||||
set(DROGON_SOURCES
|
|
||||||
${DROGON_SOURCES}
|
|
||||||
lib/src/ssl_funcs/Md5.cc
|
|
||||||
lib/src/ssl_funcs/Sha1.cc)
|
|
||||||
set(private_headers
|
|
||||||
${private_headers}
|
|
||||||
lib/src/ssl_funcs/Md5.h
|
|
||||||
lib/src/ssl_funcs/Sha1.h)
|
|
||||||
endif (OpenSSL_FOUND)
|
|
||||||
|
|
||||||
execute_process(COMMAND "git" rev-parse HEAD
|
execute_process(COMMAND "git" rev-parse HEAD
|
||||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||||
OUTPUT_VARIABLE GIT_SHA1
|
OUTPUT_VARIABLE GIT_SHA1
|
||||||
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
|
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
configure_file("${PROJECT_SOURCE_DIR}/cmake/templates/version.h.in"
|
configure_file("${PROJECT_SOURCE_DIR}/cmake/templates/version.h.in"
|
||||||
"${PROJECT_SOURCE_DIR}/lib/inc/drogon/version.h" @ONLY)
|
"${CMAKE_CURRENT_BINARY_DIR}/lib/inc/drogon/version.h" @ONLY)
|
||||||
|
|
||||||
if (DROGON_CXX_STANDARD EQUAL 20)
|
if (DROGON_CXX_STANDARD EQUAL 20)
|
||||||
option(USE_COROUTINE "Enable C++20 coroutine support" ON)
|
option(USE_COROUTINE "Enable C++20 coroutine support" ON)
|
||||||
@ -475,6 +545,7 @@ set(DROGON_SOURCES
|
|||||||
orm_lib/src/DbClientImpl.cc
|
orm_lib/src/DbClientImpl.cc
|
||||||
orm_lib/src/DbClientLockFree.cc
|
orm_lib/src/DbClientLockFree.cc
|
||||||
orm_lib/src/DbConnection.cc
|
orm_lib/src/DbConnection.cc
|
||||||
|
orm_lib/src/DbListener.cc
|
||||||
orm_lib/src/Exception.cc
|
orm_lib/src/Exception.cc
|
||||||
orm_lib/src/Field.cc
|
orm_lib/src/Field.cc
|
||||||
orm_lib/src/Result.cc
|
orm_lib/src/Result.cc
|
||||||
@ -495,7 +566,9 @@ set(DROGON_HEADERS
|
|||||||
lib/inc/drogon/HttpClient.h
|
lib/inc/drogon/HttpClient.h
|
||||||
lib/inc/drogon/HttpController.h
|
lib/inc/drogon/HttpController.h
|
||||||
lib/inc/drogon/HttpFilter.h
|
lib/inc/drogon/HttpFilter.h
|
||||||
|
lib/inc/drogon/HttpMiddleware.h
|
||||||
lib/inc/drogon/HttpRequest.h
|
lib/inc/drogon/HttpRequest.h
|
||||||
|
lib/inc/drogon/RequestStream.h
|
||||||
lib/inc/drogon/HttpResponse.h
|
lib/inc/drogon/HttpResponse.h
|
||||||
lib/inc/drogon/HttpSimpleController.h
|
lib/inc/drogon/HttpSimpleController.h
|
||||||
lib/inc/drogon/HttpTypes.h
|
lib/inc/drogon/HttpTypes.h
|
||||||
@ -511,10 +584,11 @@ set(DROGON_HEADERS
|
|||||||
lib/inc/drogon/WebSocketConnection.h
|
lib/inc/drogon/WebSocketConnection.h
|
||||||
lib/inc/drogon/WebSocketController.h
|
lib/inc/drogon/WebSocketController.h
|
||||||
lib/inc/drogon/drogon.h
|
lib/inc/drogon/drogon.h
|
||||||
lib/inc/drogon/version.h
|
${CMAKE_CURRENT_BINARY_DIR}/lib/inc/drogon/version.h
|
||||||
lib/inc/drogon/drogon_callbacks.h
|
lib/inc/drogon/drogon_callbacks.h
|
||||||
lib/inc/drogon/PubSubService.h
|
lib/inc/drogon/PubSubService.h
|
||||||
lib/inc/drogon/drogon_test.h
|
lib/inc/drogon/drogon_test.h
|
||||||
|
lib/inc/drogon/RateLimiter.h
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/exports/drogon/exports.h)
|
${CMAKE_CURRENT_BINARY_DIR}/exports/drogon/exports.h)
|
||||||
set(private_headers
|
set(private_headers
|
||||||
${private_headers}
|
${private_headers}
|
||||||
@ -523,15 +597,15 @@ set(private_headers
|
|||||||
orm_lib/src/DbConnection.h
|
orm_lib/src/DbConnection.h
|
||||||
orm_lib/src/ResultImpl.h
|
orm_lib/src/ResultImpl.h
|
||||||
orm_lib/src/TransactionImpl.h)
|
orm_lib/src/TransactionImpl.h)
|
||||||
if (pg_FOUND OR MySQL_FOUND OR SQLite3_FOUND)
|
if (pg_FOUND OR DROGON_FOUND_MYSQL OR DROGON_FOUND_SQLite3)
|
||||||
set(DROGON_SOURCES
|
set(DROGON_SOURCES
|
||||||
${DROGON_SOURCES}
|
${DROGON_SOURCES}
|
||||||
orm_lib/src/DbClientManager.cc)
|
orm_lib/src/DbClientManager.cc)
|
||||||
else (pg_FOUND OR MySQL_FOUND OR SQLite3_FOUND)
|
else (pg_FOUND OR DROGON_FOUND_MYSQL OR DROGON_FOUND_SQLite3)
|
||||||
set(DROGON_SOURCES
|
set(DROGON_SOURCES
|
||||||
${DROGON_SOURCES}
|
${DROGON_SOURCES}
|
||||||
lib/src/DbClientManagerSkipped.cc)
|
lib/src/DbClientManagerSkipped.cc)
|
||||||
endif (pg_FOUND OR MySQL_FOUND OR SQLite3_FOUND)
|
endif (pg_FOUND OR DROGON_FOUND_MYSQL OR DROGON_FOUND_SQLite3)
|
||||||
|
|
||||||
set_target_properties(${PROJECT_NAME}
|
set_target_properties(${PROJECT_NAME}
|
||||||
PROPERTIES CXX_STANDARD ${DROGON_CXX_STANDARD})
|
PROPERTIES CXX_STANDARD ${DROGON_CXX_STANDARD})
|
||||||
@ -539,27 +613,27 @@ set_target_properties(${PROJECT_NAME} PROPERTIES CXX_STANDARD_REQUIRED ON)
|
|||||||
set_target_properties(${PROJECT_NAME} PROPERTIES CXX_EXTENSIONS OFF)
|
set_target_properties(${PROJECT_NAME} PROPERTIES CXX_EXTENSIONS OFF)
|
||||||
set_target_properties(${PROJECT_NAME} PROPERTIES EXPORT_NAME Drogon)
|
set_target_properties(${PROJECT_NAME} PROPERTIES EXPORT_NAME Drogon)
|
||||||
|
|
||||||
if (pg_FOUND OR MySQL_FOUND OR SQLite3_FOUND)
|
if (pg_FOUND OR DROGON_FOUND_MYSQL OR DROGON_FOUND_SQLite3)
|
||||||
if (pg_FOUND)
|
if (pg_FOUND)
|
||||||
option(USE_POSTGRESQL "Enable PostgreSQL" ON)
|
option(USE_POSTGRESQL "Enable PostgreSQL" ON)
|
||||||
else (pg_FOUND)
|
else (pg_FOUND)
|
||||||
option(USE_POSTGRESQL "Disable PostgreSQL" OFF)
|
option(USE_POSTGRESQL "Disable PostgreSQL" OFF)
|
||||||
endif (pg_FOUND)
|
endif (pg_FOUND)
|
||||||
|
|
||||||
if (MySQL_FOUND)
|
if (DROGON_FOUND_MYSQL)
|
||||||
option(USE_MYSQL "Enable Mysql" ON)
|
option(USE_MYSQL "Enable Mysql" ON)
|
||||||
else (MySQL_FOUND)
|
else (DROGON_FOUND_MYSQL)
|
||||||
option(USE_MYSQL "Disable Mysql" OFF)
|
option(USE_MYSQL "Disable Mysql" OFF)
|
||||||
endif (MySQL_FOUND)
|
endif (DROGON_FOUND_MYSQL)
|
||||||
|
|
||||||
if (SQLite3_FOUND)
|
if (DROGON_FOUND_SQLite3)
|
||||||
option(USE_SQLITE3 "Enable Sqlite3" ON)
|
option(USE_SQLITE3 "Enable Sqlite3" ON)
|
||||||
else (SQLite3_FOUND)
|
else (DROGON_FOUND_SQLite3)
|
||||||
option(USE_SQLITE3 "Disable Sqlite3" OFF)
|
option(USE_SQLITE3 "Disable Sqlite3" OFF)
|
||||||
endif (SQLite3_FOUND)
|
endif (DROGON_FOUND_SQLite3)
|
||||||
endif (pg_FOUND OR MySQL_FOUND OR SQLite3_FOUND)
|
endif (pg_FOUND OR DROGON_FOUND_MYSQL OR DROGON_FOUND_SQLite3)
|
||||||
|
|
||||||
set(COMPILER_COMMAND ${CMAKE_CXX_COMPILER})
|
get_filename_component(COMPILER_COMMAND ${CMAKE_CXX_COMPILER} NAME)
|
||||||
set(COMPILER_ID ${CMAKE_CXX_COMPILER_ID})
|
set(COMPILER_ID ${CMAKE_CXX_COMPILER_ID})
|
||||||
|
|
||||||
if (CMAKE_BUILD_TYPE)
|
if (CMAKE_BUILD_TYPE)
|
||||||
@ -595,12 +669,12 @@ if (BUILD_TESTING)
|
|||||||
if (pg_FOUND)
|
if (pg_FOUND)
|
||||||
add_subdirectory(${PROJECT_SOURCE_DIR}/orm_lib/src/postgresql_impl/test)
|
add_subdirectory(${PROJECT_SOURCE_DIR}/orm_lib/src/postgresql_impl/test)
|
||||||
endif (pg_FOUND)
|
endif (pg_FOUND)
|
||||||
if (MySQL_FOUND)
|
if (DROGON_FOUND_MYSQL)
|
||||||
add_subdirectory(${PROJECT_SOURCE_DIR}/orm_lib/src/mysql_impl/test)
|
add_subdirectory(${PROJECT_SOURCE_DIR}/orm_lib/src/mysql_impl/test)
|
||||||
endif (MySQL_FOUND)
|
endif (DROGON_FOUND_MYSQL)
|
||||||
if (SQLite3_FOUND)
|
if (DROGON_FOUND_SQLite3)
|
||||||
add_subdirectory(${PROJECT_SOURCE_DIR}/orm_lib/src/sqlite3_impl/test)
|
add_subdirectory(${PROJECT_SOURCE_DIR}/orm_lib/src/sqlite3_impl/test)
|
||||||
endif (SQLite3_FOUND)
|
endif (DROGON_FOUND_SQLite3)
|
||||||
add_subdirectory(${PROJECT_SOURCE_DIR}/orm_lib/tests)
|
add_subdirectory(${PROJECT_SOURCE_DIR}/orm_lib/tests)
|
||||||
endif (BUILD_TESTING)
|
endif (BUILD_TESTING)
|
||||||
|
|
||||||
@ -616,8 +690,11 @@ install(FILES ${DROGON_HEADERS} DESTINATION ${INSTALL_INCLUDE_DIR}/drogon)
|
|||||||
|
|
||||||
set(ORM_HEADERS
|
set(ORM_HEADERS
|
||||||
orm_lib/inc/drogon/orm/ArrayParser.h
|
orm_lib/inc/drogon/orm/ArrayParser.h
|
||||||
|
orm_lib/inc/drogon/orm/BaseBuilder.h
|
||||||
orm_lib/inc/drogon/orm/Criteria.h
|
orm_lib/inc/drogon/orm/Criteria.h
|
||||||
orm_lib/inc/drogon/orm/DbClient.h
|
orm_lib/inc/drogon/orm/DbClient.h
|
||||||
|
orm_lib/inc/drogon/orm/DbConfig.h
|
||||||
|
orm_lib/inc/drogon/orm/DbListener.h
|
||||||
orm_lib/inc/drogon/orm/DbTypes.h
|
orm_lib/inc/drogon/orm/DbTypes.h
|
||||||
orm_lib/inc/drogon/orm/Exception.h
|
orm_lib/inc/drogon/orm/Exception.h
|
||||||
orm_lib/inc/drogon/orm/Field.h
|
orm_lib/inc/drogon/orm/Field.h
|
||||||
@ -635,25 +712,43 @@ install(FILES ${ORM_HEADERS} DESTINATION ${INSTALL_INCLUDE_DIR}/drogon/orm)
|
|||||||
set(NOSQL_HEADERS
|
set(NOSQL_HEADERS
|
||||||
nosql_lib/redis/inc/drogon/nosql/RedisClient.h
|
nosql_lib/redis/inc/drogon/nosql/RedisClient.h
|
||||||
nosql_lib/redis/inc/drogon/nosql/RedisResult.h
|
nosql_lib/redis/inc/drogon/nosql/RedisResult.h
|
||||||
|
nosql_lib/redis/inc/drogon/nosql/RedisSubscriber.h
|
||||||
nosql_lib/redis/inc/drogon/nosql/RedisException.h)
|
nosql_lib/redis/inc/drogon/nosql/RedisException.h)
|
||||||
install(FILES ${NOSQL_HEADERS} DESTINATION ${INSTALL_INCLUDE_DIR}/drogon/nosql)
|
install(FILES ${NOSQL_HEADERS} DESTINATION ${INSTALL_INCLUDE_DIR}/drogon/nosql)
|
||||||
|
|
||||||
set(DROGON_UTIL_HEADERS
|
set(DROGON_UTIL_HEADERS
|
||||||
lib/inc/drogon/utils/FunctionTraits.h
|
|
||||||
lib/inc/drogon/utils/Utilities.h
|
|
||||||
lib/inc/drogon/utils/any.h
|
|
||||||
lib/inc/drogon/utils/string_view.h
|
|
||||||
lib/inc/drogon/utils/optional.h
|
|
||||||
lib/inc/drogon/utils/coroutine.h
|
lib/inc/drogon/utils/coroutine.h
|
||||||
|
lib/inc/drogon/utils/FunctionTraits.h
|
||||||
lib/inc/drogon/utils/HttpConstraint.h
|
lib/inc/drogon/utils/HttpConstraint.h
|
||||||
lib/inc/drogon/utils/OStringStream.h)
|
lib/inc/drogon/utils/OStringStream.h
|
||||||
|
lib/inc/drogon/utils/Utilities.h
|
||||||
|
lib/inc/drogon/utils/monitoring.h)
|
||||||
install(FILES ${DROGON_UTIL_HEADERS}
|
install(FILES ${DROGON_UTIL_HEADERS}
|
||||||
DESTINATION ${INSTALL_INCLUDE_DIR}/drogon/utils)
|
DESTINATION ${INSTALL_INCLUDE_DIR}/drogon/utils)
|
||||||
|
|
||||||
|
set(DROGON_MONITORING_HEADERS
|
||||||
|
lib/inc/drogon/utils/monitoring/Counter.h
|
||||||
|
lib/inc/drogon/utils/monitoring/Metric.h
|
||||||
|
lib/inc/drogon/utils/monitoring/Registry.h
|
||||||
|
lib/inc/drogon/utils/monitoring/Collector.h
|
||||||
|
lib/inc/drogon/utils/monitoring/Sample.h
|
||||||
|
lib/inc/drogon/utils/monitoring/Gauge.h
|
||||||
|
lib/inc/drogon/utils/monitoring/Histogram.h)
|
||||||
|
|
||||||
|
install(FILES ${DROGON_MONITORING_HEADERS}
|
||||||
|
DESTINATION ${INSTALL_INCLUDE_DIR}/drogon/utils/monitoring)
|
||||||
|
|
||||||
set(DROGON_PLUGIN_HEADERS
|
set(DROGON_PLUGIN_HEADERS
|
||||||
lib/inc/drogon/plugins/Plugin.h
|
lib/inc/drogon/plugins/Plugin.h
|
||||||
|
lib/inc/drogon/plugins/Redirector.h
|
||||||
lib/inc/drogon/plugins/SecureSSLRedirector.h
|
lib/inc/drogon/plugins/SecureSSLRedirector.h
|
||||||
lib/inc/drogon/plugins/AccessLogger.h)
|
lib/inc/drogon/plugins/AccessLogger.h
|
||||||
|
lib/inc/drogon/plugins/RealIpResolver.h
|
||||||
|
lib/inc/drogon/plugins/Hodor.h
|
||||||
|
lib/inc/drogon/plugins/SlashRemover.h
|
||||||
|
lib/inc/drogon/plugins/GlobalFilters.h
|
||||||
|
lib/inc/drogon/plugins/PromExporter.h)
|
||||||
|
|
||||||
install(FILES ${DROGON_PLUGIN_HEADERS}
|
install(FILES ${DROGON_PLUGIN_HEADERS}
|
||||||
DESTINATION ${INSTALL_INCLUDE_DIR}/drogon/plugins)
|
DESTINATION ${INSTALL_INCLUDE_DIR}/drogon/plugins)
|
||||||
|
|
||||||
@ -664,7 +759,8 @@ target_sources(${PROJECT_NAME} PRIVATE
|
|||||||
${ORM_HEADERS}
|
${ORM_HEADERS}
|
||||||
${DROGON_UTIL_HEADERS}
|
${DROGON_UTIL_HEADERS}
|
||||||
${DROGON_PLUGIN_HEADERS}
|
${DROGON_PLUGIN_HEADERS}
|
||||||
${NOSQL_HEADERS})
|
${NOSQL_HEADERS}
|
||||||
|
${DROGON_MONITORING_HEADERS})
|
||||||
|
|
||||||
source_group("Public API"
|
source_group("Public API"
|
||||||
FILES
|
FILES
|
||||||
@ -672,7 +768,8 @@ source_group("Public API"
|
|||||||
${ORM_HEADERS}
|
${ORM_HEADERS}
|
||||||
${DROGON_UTIL_HEADERS}
|
${DROGON_UTIL_HEADERS}
|
||||||
${DROGON_PLUGIN_HEADERS}
|
${DROGON_PLUGIN_HEADERS}
|
||||||
${NOSQL_HEADERS})
|
${NOSQL_HEADERS}
|
||||||
|
${DROGON_MONITORING_HEADERS})
|
||||||
source_group("Private Headers"
|
source_group("Private Headers"
|
||||||
FILES
|
FILES
|
||||||
${private_headers})
|
${private_headers})
|
||||||
|
@ -9,7 +9,7 @@ contribute in an overall positive way.
|
|||||||
1. Fork, then clone the repository: `git clone
|
1. Fork, then clone the repository: `git clone
|
||||||
git@github.com:your-username/drogon.git`
|
git@github.com:your-username/drogon.git`
|
||||||
1. Follow the [official installation steps on
|
1. Follow the [official installation steps on
|
||||||
DocsForge](https://drogon.docsforge.com/master/installation/). It’s best to
|
Github](https://drogonframework.github.io/drogon-docs/#/ENG-02-Installation). It’s best to
|
||||||
make sure to have the `drogon_ctl` executable in your shell’s `PATH`
|
make sure to have the `drogon_ctl` executable in your shell’s `PATH`
|
||||||
environment variable in case you use a terminal.
|
environment variable in case you use a terminal.
|
||||||
|
|
||||||
|
36
CPPLINT.cfg
Normal file
36
CPPLINT.cfg
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
# Stop searching for additional config files.
|
||||||
|
set noparent
|
||||||
|
|
||||||
|
exclude_files=trantor
|
||||||
|
exclude_files=build
|
||||||
|
|
||||||
|
# Use non-const reference rather than a pointer.
|
||||||
|
filter=-runtime/references
|
||||||
|
|
||||||
|
# CHECK macros are from Drogon, not Google Test.
|
||||||
|
filter=-readability/check
|
||||||
|
|
||||||
|
# Don't warn about the use of C++11 or C++17 features.
|
||||||
|
filter=-build/c++11
|
||||||
|
filter=-build/c++17
|
||||||
|
|
||||||
|
filter=-build/include_subdir
|
||||||
|
|
||||||
|
# We prioritize clang-format for now.
|
||||||
|
filter=-whitespace
|
||||||
|
|
||||||
|
# We don't require a username in TODO comments.
|
||||||
|
filter=-readability/todo
|
||||||
|
|
||||||
|
# TODO: Fix these.
|
||||||
|
filter=-legal/copyright
|
||||||
|
filter=-build/namespaces
|
||||||
|
filter=-build/include
|
||||||
|
filter=-build/include_what_you_use
|
||||||
|
filter=-runtime/explicit
|
||||||
|
filter=-runtime/string
|
||||||
|
filter=-runtime/int
|
||||||
|
filter=-readability/casting
|
||||||
|
filter=-readability/braces
|
||||||
|
filter=-readability/fn_size
|
||||||
|
filter=-runtime/threadsafe_fn
|
1020
ChangeLog.md
1020
ChangeLog.md
File diff suppressed because it is too large
Load Diff
2
LICENSE
2
LICENSE
@ -1,6 +1,6 @@
|
|||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2019-2021 An Tao
|
Copyright (c) 2019-2023 An Tao
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
54
README.md
54
README.md
@ -1,17 +1,16 @@
|
|||||||

|

|
||||||
|
|
||||||
[](https://travis-ci.com/an-tao/drogon)
|
[](https://github.com/drogonframework/drogon/actions)
|
||||||

|
[](https://conan.io/center/recipes/drogon)
|
||||||
[](https://lgtm.com/projects/g/an-tao/drogon/alerts/)
|
|
||||||
[](https://gitter.im/drogon-web/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
|
||||||
[](https://t.me/joinchat/_mMNGv0748ZkMDAx)
|
[](https://t.me/joinchat/_mMNGv0748ZkMDAx)
|
||||||
|
[](https://discord.gg/3DvHY6Ewuj)
|
||||||
[](https://cloud.docker.com/u/drogonframework/repository/docker/drogonframework/drogon)
|
[](https://cloud.docker.com/u/drogonframework/repository/docker/drogonframework/drogon)
|
||||||
|
|
||||||
English | [简体中文](./README.zh-CN.md) | [繁體中文](./README.zh-TW.md)
|
English | [简体中文](./README.zh-CN.md) | [繁體中文](./README.zh-TW.md)
|
||||||
### Overview
|
### Overview
|
||||||
**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 C++17/20 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 from the American TV series *Game of Thrones*, which I really enjoy.
|
||||||
|
|
||||||
Drogon is a cross-platform framework, It supports Linux, macOS, FreeBSD, OpenBSD, and Windows. Its main features are as follows:
|
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](https://www.techempower.com/benchmarks/#section=data-r19&hw=ph&test=composite) for more details;
|
* 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](https://www.techempower.com/benchmarks/#section=data-r19&hw=ph&test=composite) for more details;
|
||||||
* Provide a completely asynchronous programming mode;
|
* Provide a completely asynchronous programming mode;
|
||||||
@ -35,7 +34,7 @@ Drogon is a cross-platform framework, It supports Linux, macOS, FreeBSD, OpenBSD
|
|||||||
* Support ARM Architecture;
|
* Support ARM Architecture;
|
||||||
* Provide a convenient lightweight ORM implementation that supports for regular object-to-database bidirectional mapping;
|
* 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 plugins which can be installed by the configuration file at load time;
|
||||||
* Support AOP with build-in joinpoints.
|
* Support AOP with built-in joinpoints.
|
||||||
* Support C++ coroutines
|
* Support C++ coroutines
|
||||||
|
|
||||||
## A very simple example
|
## A very simple example
|
||||||
@ -96,7 +95,7 @@ using namespace drogon;
|
|||||||
class TestCtrl:public drogon::HttpSimpleController<TestCtrl>
|
class TestCtrl:public drogon::HttpSimpleController<TestCtrl>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void asyncHandleHttpRequest(const HttpRequestPtr& req, std::function<void (const HttpResponsePtr &)> &&callback) override;
|
void asyncHandleHttpRequest(const HttpRequestPtr& req, std::function<void (const HttpResponsePtr &)> &&callback) override;
|
||||||
PATH_LIST_BEGIN
|
PATH_LIST_BEGIN
|
||||||
PATH_ADD("/test",Get);
|
PATH_ADD("/test",Get);
|
||||||
PATH_LIST_END
|
PATH_LIST_END
|
||||||
@ -127,7 +126,7 @@ using namespace drogon;
|
|||||||
class JsonCtrl : public drogon::HttpSimpleController<JsonCtrl>
|
class JsonCtrl : public drogon::HttpSimpleController<JsonCtrl>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void asyncHandleHttpRequest(const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> &&callback) override;
|
void asyncHandleHttpRequest(const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> &&callback) override;
|
||||||
PATH_LIST_BEGIN
|
PATH_LIST_BEGIN
|
||||||
//list path definitions here;
|
//list path definitions here;
|
||||||
PATH_ADD("/json", Get);
|
PATH_ADD("/json", Get);
|
||||||
@ -184,7 +183,40 @@ As you can see, users can use the `HttpController` to map paths and parameters a
|
|||||||
|
|
||||||
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.
|
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](https://github.com/an-tao/drogon/wiki/ENG-01-Overview) or [DocsForge](https://drogon.docsforge.com/master/overview/)**
|
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 [documentation](https://drogonframework.github.io/drogon-docs/#/) on GitHub**.
|
||||||
|
|
||||||
|
## Cross-compilation
|
||||||
|
|
||||||
|
Drogon supports cross-compilation, you should define the `CMAKE_SYSTEM_NAME` in toolchain file, for example:
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
set(CMAKE_SYSTEM_NAME Linux)
|
||||||
|
set(CMAKE_SYSTEM_PROCESSOR arm)
|
||||||
|
```
|
||||||
|
|
||||||
|
You can disable building options for examples and drogon_ctl by settings `BUILD_EXAMPLES` and `BUILD_CTL` to `OFF` in the toolchain file.
|
||||||
|
|
||||||
|
## Building options
|
||||||
|
|
||||||
|
Drogon provides some building options, you can enable or disable them by setting the corresponding variables to `ON` or `OFF` in the cmake command line, cmake file etc...
|
||||||
|
|
||||||
|
| Option name | Description | Default value |
|
||||||
|
| :--- | :--- | :--- |
|
||||||
|
| BUILD_CTL | Build drogon_ctl | ON |
|
||||||
|
| BUILD_EXAMPLES | Build examples | ON |
|
||||||
|
| BUILD_ORM | Build orm | ON |
|
||||||
|
| COZ_PROFILING | Use coz for profiling | OFF |
|
||||||
|
| BUILD_SHARED_LIBS | Build drogon as a shared lib | OFF |
|
||||||
|
| BUILD_DOC | Build Doxygen documentation | OFF |
|
||||||
|
| BUILD_BROTLI | Build Brotli | ON |
|
||||||
|
| BUILD_YAML_CONFIG | Build yaml config | ON |
|
||||||
|
| USE_SUBMODULE | Use trantor as a submodule | ON |
|
||||||
|
|
||||||
|
|
||||||
## Contributions
|
## Contributions
|
||||||
|
|
||||||
|
This project exists thanks to all the people who contribute code.
|
||||||
|
|
||||||
|
<a href="https://github.com/drogonframework/drogon/graphs/contributors"><img src="https://contributors-svg.opencollective.com/drogon/contributors.svg?width=890&button=false" alt="Code contributors" /></a>
|
||||||
|
|
||||||
Every contribution is welcome. Please refer to the [contribution guidelines](CONTRIBUTING.md) for more information.
|
Every contribution is welcome. Please refer to the [contribution guidelines](CONTRIBUTING.md) for more information.
|
||||||
|
@ -1,18 +1,17 @@
|
|||||||

|

|
||||||
|
|
||||||
[](https://travis-ci.com/an-tao/drogon)
|
[](https://github.com/drogonframework/drogon/actions)
|
||||||

|
[](https://conan.io/center/recipes/drogon)
|
||||||
[](https://lgtm.com/projects/g/an-tao/drogon/alerts/)
|
|
||||||
[](https://gitter.im/drogon-web/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
|
||||||
[](https://t.me/joinchat/_mMNGv0748ZkMDAx)
|
[](https://t.me/joinchat/_mMNGv0748ZkMDAx)
|
||||||
|
[](https://discord.gg/3DvHY6Ewuj)
|
||||||
[](https://cloud.docker.com/u/drogonframework/repository/docker/drogonframework/drogon)
|
[](https://cloud.docker.com/u/drogonframework/repository/docker/drogonframework/drogon)
|
||||||
|
|
||||||
[English](./README.md) | 简体中文 | [繁體中文](./README.zh-TW.md)
|
[English](./README.md) | 简体中文 | [繁體中文](./README.zh-TW.md)
|
||||||
|
|
||||||
**Drogon**是一个基于C++14/17的Http应用框架,使用Drogon可以方便的使用C++构建各种类型的Web应用服务端程序。
|
**Drogon**是一个基于C++17/20的Http应用框架,使用Drogon可以方便的使用C++构建各种类型的Web应用服务端程序。
|
||||||
本版本库是github上[Drogon工程](https://github.com/an-tao/drogon)的镜像库。**Drogon**是作者非常喜欢的美剧《权力的游戏》中的一条龙的名字(汉译作卓耿),和龙有关但并不是dragon的误写,为了不至于引起不必要的误会这里说明一下。
|
本版本库是github上[Drogon工程](https://github.com/an-tao/drogon)的镜像库。**Drogon**是作者非常喜欢的美剧《权力的游戏》中的一条龙的名字(汉译作卓耿),和龙有关但并不是dragon的误写,为了不至于引起不必要的误会这里说明一下。
|
||||||
|
|
||||||
Drogon是一个跨平台框架,它支持Linux,也支持macOS、FreeBSD,OpenBSD,和Windows。它的主要特点如下:
|
Drogon是一个跨平台框架,它支持Linux,也支持macOS、FreeBSD,OpenBSD,HaikuOS,和Windows。它的主要特点如下:
|
||||||
|
|
||||||
* 网络层使用基于epoll(macOS/FreeBSD下是kqueue)的非阻塞IO框架,提供高并发、高性能的网络IO。详细请见[TFB Tests Results](https://www.techempower.com/benchmarks/#section=data-r19&hw=ph&test=composite);
|
* 网络层使用基于epoll(macOS/FreeBSD下是kqueue)的非阻塞IO框架,提供高并发、高性能的网络IO。详细请见[TFB Tests Results](https://www.techempower.com/benchmarks/#section=data-r19&hw=ph&test=composite);
|
||||||
* 全异步编程模式;
|
* 全异步编程模式;
|
||||||
@ -99,7 +98,7 @@ using namespace drogon;
|
|||||||
class TestCtrl:public drogon::HttpSimpleController<TestCtrl>
|
class TestCtrl:public drogon::HttpSimpleController<TestCtrl>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void asyncHandleHttpRequest(const HttpRequestPtr& req, std::function<void (const HttpResponsePtr &)> &&callback) override;
|
void asyncHandleHttpRequest(const HttpRequestPtr& req, std::function<void (const HttpResponsePtr &)> &&callback) override;
|
||||||
PATH_LIST_BEGIN
|
PATH_LIST_BEGIN
|
||||||
PATH_ADD("/test",Get);
|
PATH_ADD("/test",Get);
|
||||||
PATH_LIST_END
|
PATH_LIST_END
|
||||||
@ -130,7 +129,7 @@ using namespace drogon;
|
|||||||
class JsonCtrl : public drogon::HttpSimpleController<JsonCtrl>
|
class JsonCtrl : public drogon::HttpSimpleController<JsonCtrl>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void asyncHandleHttpRequest(const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> &&callback) override;
|
void asyncHandleHttpRequest(const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> &&callback) override;
|
||||||
PATH_LIST_BEGIN
|
PATH_LIST_BEGIN
|
||||||
//list path definitions here;
|
//list path definitions here;
|
||||||
PATH_ADD("/json", Get);
|
PATH_ADD("/json", Get);
|
||||||
@ -187,12 +186,20 @@ class User : public drogon::HttpController<User>
|
|||||||
|
|
||||||
另外,你可以发现前面所有的处理函数接口都是异步的,处理器的响应是通过回调对象返回的。这种设计是出于对高性能的考虑,因为在异步模式下,可以使用少量的线程(比如和处理器核心数相等的线程)处理大量的并发请求。
|
另外,你可以发现前面所有的处理函数接口都是异步的,处理器的响应是通过回调对象返回的。这种设计是出于对高性能的考虑,因为在异步模式下,可以使用少量的线程(比如和处理器核心数相等的线程)处理大量的并发请求。
|
||||||
|
|
||||||
编译上述的所有源文件后,我们得到了一个非常简单的web应用程序,这是一个不错的开始。**请访问[wiki](https://github.com/an-tao/drogon/wiki/CHN-01-概述)或者[doxiz](https://doxiz.com/drogon/master/overview/)以获取更多的信息**
|
编译上述的所有源文件后,我们得到了一个非常简单的web应用程序,这是一个不错的开始。**请访问GitHub上的[文档](https://drogonframework.github.io/drogon-docs/#/CHN/CHN-01-%E6%A6%82%E8%BF%B0)**
|
||||||
|
|
||||||
## 贡献方式
|
## 贡献方式
|
||||||
|
|
||||||
欢迎您的贡献。 请阅读[贡献指南](CONTRIBUTING.md)以获取更多的信息。
|
欢迎您的贡献。 请阅读[贡献指南](CONTRIBUTING.md)以获取更多的信息。
|
||||||
|
|
||||||
|
<a href="https://github.com/drogonframework/drogon/graphs/contributors"><img src="https://contributors-svg.opencollective.com/drogon/contributors.svg?width=890&button=false" alt="Code contributors" /></a>
|
||||||
|
|
||||||
## QQ交流群:1137909452
|
## QQ交流群:1137909452
|
||||||
|
|
||||||
欢迎交流探讨。
|
欢迎交流探讨。
|
||||||
|
|
||||||
|
## 微信公众号:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
会不定期推送一些Drogon的使用技巧和更新信息,欢迎关注。
|
100
README.zh-TW.md
100
README.zh-TW.md
@ -1,49 +1,49 @@
|
|||||||

|

|
||||||
|
|
||||||
[](https://travis-ci.com/an-tao/drogon)
|
[](https://github.com/drogonframework/drogon/actions)
|
||||||

|
[](https://conan.io/center/recipes/drogon)
|
||||||
[](https://lgtm.com/projects/g/an-tao/drogon/alerts/)
|
|
||||||
[](https://gitter.im/drogon-web/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
|
||||||
[](https://t.me/joinchat/_mMNGv0748ZkMDAx)
|
[](https://t.me/joinchat/_mMNGv0748ZkMDAx)
|
||||||
|
[](https://discord.gg/3DvHY6Ewuj)
|
||||||
[](https://cloud.docker.com/u/drogonframework/repository/docker/drogonframework/drogon)
|
[](https://cloud.docker.com/u/drogonframework/repository/docker/drogonframework/drogon)
|
||||||
|
|
||||||
[English](./README.md) | [简体中文](./README.zh-CN.md) | 繁體中文
|
[English](./README.md) | [简体中文](./README.zh-CN.md) | 繁體中文
|
||||||
|
|
||||||
**Drogon**是一個基於C++14/17的Http應用框架,使用Drogon可以方便的使用C++構建各種類型的Web App伺服器程式。
|
**Drogon** 是一個基於 C++17/20 的 HTTP 應用程式框架,使用 Drogon 可以方便地用 C++ 建立各種類型的 Web App 伺服器端程式。
|
||||||
本版本庫是github上[Drogon](https://github.com/an-tao/drogon)的鏡像庫。 **Drogon**是作者非常喜歡的美劇《冰與火之歌:權力遊戲》中的一條龍的名字(漢譯作卓耿),和龍有關但並不是dragon的誤寫,為了不至於引起不必要的誤會這裡說明一下。
|
|
||||||
|
|
||||||
Drogon是一個跨平台框架,它支援Linux,也支援macOS、FreeBSD/OpenBSD和Windows。它的主要特點如下:
|
這個版本庫是 GitHub 上 [Drogon](https://github.com/an-tao/drogon) 的鏡像庫。**Drogon** 是作者非常喜歡的美劇《冰與火之歌:權力遊戲》中的一條龍的名字(中文譯作卓耿),和龍有關但並不是 dragon 的誤寫,為了避免不必要的誤會在此說明。
|
||||||
|
|
||||||
* 網路層使用基於epoll(macOS/FreeBSD下是kqueue)的非阻塞IO框架,提供高並發、高性能的網路IO。詳細請見[TFB Tests Results](https://www.techempower.com/benchmarks/#section=data-r19&hw=ph&test=composite);
|
Drogon 是一個跨平台框架,支援 Linux、macOS、FreeBSD/OpenBSD、HaikuOS 和 Windows。主要特點如下:
|
||||||
* 全異步程式設計;
|
|
||||||
* 支援Http1.0/1.1(server端和client端);
|
* 網路層使用基於 epoll(macOS/FreeBSD 下是 kqueue)的非阻塞 IO 框架,提供高並行、高效能的網路 IO。詳細請見 [TFB Tests Results](https://www.techempower.com/benchmarks/#section=data-r19&hw=ph&test=composite);
|
||||||
* 基於模板(template)實現了簡單的反射機制,使主程式框架、控制器(controller)和視圖(view)完全去耦;
|
* 完全非同步的程式撰寫邏輯;
|
||||||
* 支援cookies和內建的session;
|
* 支援 HTTP 1.0/1.1(伺服器端和用戶端);
|
||||||
* 支援後端渲染,把控制器生成的數據交給視圖生成Html頁面,視圖由CSP模板文件描述,通過CSP標籤把C++程式碼嵌入到Html頁面,由drogon的指令列工具在編譯階段自動生成C++程式碼並編譯;
|
* 基於樣板(template)實作的簡單反射機制,使主程式框架、控制器(controller)和視圖(view)完全解耦;
|
||||||
* 支援運行期的視圖頁面動態加載(動態編譯和載入so文件);
|
* 支援 cookies 和內建的 session;
|
||||||
* 非常方便靈活的路徑(path)到控制器處理函數(handler)的映射方案;
|
* 支援後端算繪,將控制器產生的資料交給視圖產生 HTML 頁面,視圖由 CSP 樣板檔案描述,透過 CSP 標籤將 C++ 程式碼嵌入 HTML 頁面,由 drogon 的命令列工具在編譯階段自動產生 C++ 程式碼並編譯;
|
||||||
* 支援過濾器(filter)鏈,方便在控制器之前執行統一的邏輯(如登錄驗證、Http Method約束驗證等);
|
* 支援執行期的視圖頁面動態載入(動態編譯和載入 so 檔案);
|
||||||
* 支援https(基於OpenSSL);
|
* 非常方便靈活的路徑(path)到控制器處理函式(handler)的對應方案;
|
||||||
* 支援websocket(server端和client端);
|
* 支援過濾器(filter)鏈,方便在控制器之前執行統一的邏輯(如登入驗證、HTTP Method 限制驗證等);
|
||||||
* 支援Json格式的請求和回應, 方便開發Restful API;
|
* 支援 HTTPS(基於 OpenSSL);
|
||||||
* 支援文件下載和上傳,支援sendfile系統呼叫;
|
* 支援 WebSocket(伺服器端和用戶端);
|
||||||
* 支援gzip/brotli壓縮傳輸;
|
* 支援 JSON 格式的請求和回應,方便開發 RESTful API;
|
||||||
* 支援pipelining;
|
* 支援檔案下載和上傳,支援 `sendfile` 系統呼叫;
|
||||||
* 提供一個輕量的指令列工具drogon_ctl,幫助簡化各種類的創造和視圖程式碼的生成過程;
|
* 支援 Gzip/Brotli 壓縮傳輸;
|
||||||
* 非同步的讀寫資料庫,目前支援PostgreSQL和MySQL(MariaDB)資料庫;
|
* 支援 pipelining;
|
||||||
* 支援異步讀寫Redis;
|
* 提供輕量的命令列工具 `drogon_ctl`,幫助簡化各種類別的建立和視圖程式碼的產生過程;
|
||||||
* 基於執行序池實現sqlite3資料庫的異步讀寫,提供與上文資料庫相同的接口;
|
* 非同步的讀寫資料庫,目前支援 PostgreSQL 和 MySQL(MariaDB)資料庫;
|
||||||
* 支援ARM架構;
|
* 支援非同步讀寫 Redis;
|
||||||
* 方便的輕量級ORM實現,一般物件到資料庫的雙向映射;
|
* 基於執行緒池實作 sqlite3 資料庫的非同步讀寫,提供與上述資料庫相同的介面;
|
||||||
* 支援外掛,可通過設定文件在載入時動態載入;
|
* 支援 ARM 架構;
|
||||||
* 支援內建插入點的AOP
|
* 方便的輕量級 ORM 實現,一般物件到資料庫的雙向對應;
|
||||||
* 支援C++ coroutine
|
* 支援外掛,可透過設定檔案在載入時動態載入;
|
||||||
|
* 支援內建插入點的 AOP;
|
||||||
|
* 支援 C++ coroutine。
|
||||||
|
|
||||||
## 一個非常簡單的例子
|
## 一個非常簡單的例子
|
||||||
|
|
||||||
不像大多數C++框架那樣,drogon的主程式可以非常簡單。 Drogon使用了一些小技巧使主程式和控制器去耦. 控制器的路由設定可以在控制器類別中定義或者設定文件中完成.
|
不像大多數 C++ 框架,drogon 的主程式可以非常簡單。Drogon 使用了一些小技巧使主程式和控制器解耦。控制器的路由設定可以在控制器類別中定義或在設定檔案中完成。
|
||||||
|
|
||||||
下面是一個典型的主程式的樣子:
|
下面是一個典型主程式的樣子:
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
#include <drogon/drogon.h>
|
#include <drogon/drogon.h>
|
||||||
@ -59,7 +59,7 @@ int main()
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
如果使用設定文件,可以進一步簡化成這樣:
|
如果使用設定檔案,可以進一步簡化成:
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
#include <drogon/drogon.h>
|
#include <drogon/drogon.h>
|
||||||
@ -70,7 +70,7 @@ int main()
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
當然,Drogon也提供了一些函數,使使用者可以在main()函數中直接添加控制器邏輯,比如,使用者可以註冊一個lambda處理器到drogon框架中,如下所示:
|
當然,Drogon 也提供了一些函式,讓使用者可以在 `main()` 函式中直接加入控制器邏輯,例如,使用者可以註冊一個 lambda 處理常式到 drogon 框架中,如下所示:
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
app().registerHandler("/test?username={name}",
|
app().registerHandler("/test?username={name}",
|
||||||
@ -87,9 +87,7 @@ app().registerHandler("/test?username={name}",
|
|||||||
{Get,"LoginFilter"});
|
{Get,"LoginFilter"});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
這看起來很方便,但不適用於複雜的場景,試想如果有數十個或數百個處理函式要註冊進框架,`main()` 函式將變得難以閱讀。顯然,讓每個包含處理函式的類別在自己的定義中完成註冊是更好的選擇。所以,除非你的應用邏輯非常簡單,我們不建議使用上述介面,更好的做法是建立一個 HttpSimpleController 類別,如下:
|
||||||
這看起來是很方便,但是這並不適用於復雜的場景,試想假如有數十個或者數百個處理函數要註冊進框架,main()函數將膨脹到不可讀的程度。顯然,讓每個包含處理函數的類在自己的定義中完成註冊是更好的選擇。所以,除非你的應用邏輯非常簡單,我們不推薦使用上述接口,更好的實踐是,我們可以創造一個HttpSimpleController類別,如下:
|
|
||||||
|
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
/// The TestCtrl.h file
|
/// The TestCtrl.h file
|
||||||
@ -99,7 +97,7 @@ using namespace drogon;
|
|||||||
class TestCtrl:public drogon::HttpSimpleController<TestCtrl>
|
class TestCtrl:public drogon::HttpSimpleController<TestCtrl>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void asyncHandleHttpRequest(const HttpRequestPtr& req, std::function<void (const HttpResponsePtr &)> &&callback) override;
|
void asyncHandleHttpRequest(const HttpRequestPtr& req, std::function<void (const HttpResponsePtr &)> &&callback) override;
|
||||||
PATH_LIST_BEGIN
|
PATH_LIST_BEGIN
|
||||||
PATH_ADD("/test",Get);
|
PATH_ADD("/test",Get);
|
||||||
PATH_LIST_END
|
PATH_LIST_END
|
||||||
@ -118,9 +116,9 @@ void TestCtrl::asyncHandleHttpRequest(const HttpRequestPtr& req,
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
**上面程式的大部分程式碼都可以由`drogon_ctl`指令創造**(這個指令是`drogon_ctl create controller TestCtr`)。使用者所需做的就是添加自己的業務邏輯。在這個例子中,當客戶端訪問URL`http://ip/test`時,控制器簡單的回傳了一個`Hello, world!`頁面。
|
**上述程式的大部分程式碼都可以由 `drogon_ctl` 指令產生**(使用指令 `drogon_ctl create controller TestCtr`)。使用者只需要加入自己的業務邏輯。在這個範例中,當用戶端存取 URL `http://ip/test` 時,控制器簡單地回傳一個 `Hello, world!` 頁面。
|
||||||
|
|
||||||
對於JSON格式的回應,我們可以像下面這樣創造控制器:
|
對於 JSON 格式的回應,我們可以這樣建立控制器:
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
/// The header file
|
/// The header file
|
||||||
@ -130,7 +128,7 @@ using namespace drogon;
|
|||||||
class JsonCtrl : public drogon::HttpSimpleController<JsonCtrl>
|
class JsonCtrl : public drogon::HttpSimpleController<JsonCtrl>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void asyncHandleHttpRequest(const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> &&callback) override;
|
void asyncHandleHttpRequest(const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> &&callback) override;
|
||||||
PATH_LIST_BEGIN
|
PATH_LIST_BEGIN
|
||||||
//list path definitions here;
|
//list path definitions here;
|
||||||
PATH_ADD("/json", Get);
|
PATH_ADD("/json", Get);
|
||||||
@ -149,7 +147,7 @@ void JsonCtrl::asyncHandleHttpRequest(const HttpRequestPtr &req,
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
讓我們更進一步,通過HttpController類別創造一個RESTful API的例子,如下所示(忽略了實做文件):
|
讓我們更進一步,透過 HttpController 類別建立一個 RESTful API 的範例,如下所示(省略實作檔案):
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
/// The header file
|
/// The header file
|
||||||
@ -183,16 +181,18 @@ class User : public drogon::HttpController<User>
|
|||||||
} // namespace api
|
} // namespace api
|
||||||
```
|
```
|
||||||
|
|
||||||
如你所見,通過`HttpController`類別,使用者可以同時映射路徑和路徑參數,這對RESTful API應用來說非常方便。
|
如你所見,透過 `HttpController` 類別,使用者可以同時對應路徑和路徑參數,這對 RESTful API 應用來說非常方便。
|
||||||
|
|
||||||
另外,你可以發現前面所有的處理函數接口都是異步的,處理器的回應是通過回調對象回傳的。這種設計是出於對高性能的考慮,因為在異步模式下,可以使用少量的執行序(比如和處理器核心數相等的執行序)處理大量的並發請求。
|
另外,你可以發現前面所有的處理函式介面都是非同步的,處理器的回應是透過回呼物件回傳的。這種設計是考慮到效能,因為在非同步模式下,可以使用少量的執行緒(例如和處理器核心數相等的執行緒)處理大量的並行請求。
|
||||||
|
|
||||||
編譯上述的所有源文件後,我們得到了一個非常簡單的web應用程式,這是一個不錯的開始。 **請瀏覽[wiki](https://github.com/an-tao/drogon/wiki/CHN-01-概述)或者[doxiz](https://doxiz.com/drogon/master/overview/)以獲取更多的信息**
|
編譯上述所有原始檔案後,我們得到了一個非常簡單的網頁應用程式,這是一個不錯的開始。**請瀏覽 GitHub 上的[文件](https://drogonframework.github.io/drogon-docs/#/CHN/CHN-01-%E6%A6%82%E8%BF%B0)**
|
||||||
|
|
||||||
## 貢獻方式
|
## 貢獻方式
|
||||||
|
|
||||||
歡迎您的貢獻。請閱讀[貢獻指南](CONTRIBUTING.md)以獲取更多的信息。
|
歡迎您的貢獻。請閱讀[貢獻指南](CONTRIBUTING.md)以取得更多資訊。
|
||||||
|
|
||||||
## QQ交流群:1137909452
|
<a href="https://github.com/drogonframework/drogon/graphs/contributors"><img src="https://contributors-svg.opencollective.com/drogon/contributors.svg?width=890&button=false" alt="Code contributors" /></a>
|
||||||
|
|
||||||
歡迎交流探討。
|
## QQ 交流群:1137909452
|
||||||
|
|
||||||
|
歡迎交流討論。
|
@ -1 +0,0 @@
|
|||||||
theme: jekyll-theme-cayman
|
|
10
build.sh
10
build.sh
@ -30,7 +30,7 @@ function build_drogon() {
|
|||||||
if [ $1 -eq 1 ]; then
|
if [ $1 -eq 1 ]; then
|
||||||
cmake .. -DBUILD_TESTING=YES $cmake_gen
|
cmake .. -DBUILD_TESTING=YES $cmake_gen
|
||||||
elif [ $1 -eq 2 ]; then
|
elif [ $1 -eq 2 ]; then
|
||||||
cmake .. -DBUILD_TESTING=YES -DBUILD_DROGON_SHARED=ON -DCMAKE_CXX_VISIBILITY_PRESET=hidden -DCMAKE_VISIBILITY_INLINES_HIDDEN=1 $cmake_gen
|
cmake .. -DBUILD_TESTING=YES -DBUILD_SHARED_LIBS=ON -DCMAKE_CXX_VISIBILITY_PRESET=hidden -DCMAKE_VISIBILITY_INLINES_HIDDEN=1 $cmake_gen
|
||||||
else
|
else
|
||||||
cmake .. -DCMAKE_BUILD_TYPE=release $cmake_gen
|
cmake .. -DCMAKE_BUILD_TYPE=release $cmake_gen
|
||||||
fi
|
fi
|
||||||
@ -48,7 +48,7 @@ function build_drogon() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Installing ..."
|
echo "Installing ..."
|
||||||
sudo $make_program install
|
$make_program install
|
||||||
|
|
||||||
#Go back to the current directory
|
#Go back to the current directory
|
||||||
cd $current_dir
|
cd $current_dir
|
||||||
@ -92,10 +92,10 @@ else
|
|||||||
make_flags="$make_flags -j$parallel"
|
make_flags="$make_flags -j$parallel"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$1" = "-t" ]; then
|
if [ "X$1" = "X-t" ]; then
|
||||||
build_drogon 1
|
build_drogon 1
|
||||||
elif [ "$1" = "-tshared" ]; then
|
elif [ "X$1" = "X-tshared" ]; then
|
||||||
build_drogon 2
|
build_drogon 2
|
||||||
else
|
else
|
||||||
build_drogon 0
|
build_drogon 0
|
||||||
fi
|
fi
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# ##############################################################################
|
# ##############################################################################
|
||||||
# function drogon_create_views(target source_path output_path
|
# function drogon_create_views(target source_path output_path
|
||||||
# [use_path_as_namespace])
|
# [TRUE to use_path_as_namespace] [prefixed namespace])
|
||||||
# ##############################################################################
|
# ##############################################################################
|
||||||
function(drogon_create_views arg)
|
function(drogon_create_views arg)
|
||||||
if(ARGC LESS 3)
|
if(ARGC LESS 3)
|
||||||
@ -27,15 +27,27 @@ function(drogon_create_views arg)
|
|||||||
""
|
""
|
||||||
outputFile
|
outputFile
|
||||||
${f2})
|
${f2})
|
||||||
|
set(p2ns "")
|
||||||
|
if("${ARGV3}" STREQUAL "TRUE")
|
||||||
|
set(p2ns "--path-to-namespace")
|
||||||
|
endif()
|
||||||
|
if ( (ARGC EQUAL 5) AND ( NOT "${ARGV4}" STREQUAL "") )
|
||||||
|
string(REPLACE "::" "_" nSpace ${ARGV4})
|
||||||
|
set(outputFile "${nSpace}_${outputFile}")
|
||||||
|
set(ns -n ${ARGV4})
|
||||||
|
else()
|
||||||
|
set(ns "")
|
||||||
|
endif()
|
||||||
add_custom_command(OUTPUT ${ARGV2}/${outputFile}.h ${ARGV2}/${outputFile}.cc
|
add_custom_command(OUTPUT ${ARGV2}/${outputFile}.h ${ARGV2}/${outputFile}.cc
|
||||||
COMMAND drogon_ctl
|
COMMAND drogon_ctl
|
||||||
ARGS
|
ARGS
|
||||||
create
|
create
|
||||||
view
|
view
|
||||||
${inFile}
|
${inFile}
|
||||||
--path-to-namespace
|
${p2ns}
|
||||||
-o
|
-o
|
||||||
${ARGV2}
|
${ARGV2}
|
||||||
|
${ns}
|
||||||
DEPENDS ${cspFile}
|
DEPENDS ${cspFile}
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
VERBATIM)
|
VERBATIM)
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
# ParseAndAddDrogonTests(${PROJECT_NAME}) #
|
# ParseAndAddDrogonTests(${PROJECT_NAME}) #
|
||||||
#==================================================================================================#
|
#==================================================================================================#
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.5)
|
cmake_minimum_required(VERSION 3.5...3.31)
|
||||||
|
|
||||||
# This removes the contents between
|
# This removes the contents between
|
||||||
# - block comments (i.e. /* ... */)
|
# - block comments (i.e. /* ... */)
|
||||||
|
@ -27,10 +27,6 @@ endif()
|
|||||||
if(@MySQL_FOUND@)
|
if(@MySQL_FOUND@)
|
||||||
find_dependency(MySQL)
|
find_dependency(MySQL)
|
||||||
endif()
|
endif()
|
||||||
if(@Boost_FOUND@)
|
|
||||||
find_dependency(Boost)
|
|
||||||
find_package(Boost COMPONENTS filesystem system)
|
|
||||||
endif()
|
|
||||||
if(@Brotli_FOUND@)
|
if(@Brotli_FOUND@)
|
||||||
find_dependency(Brotli)
|
find_dependency(Brotli)
|
||||||
endif()
|
endif()
|
||||||
@ -40,7 +36,10 @@ endif()
|
|||||||
if(@Hiredis_FOUND@)
|
if(@Hiredis_FOUND@)
|
||||||
find_dependency(Hiredis)
|
find_dependency(Hiredis)
|
||||||
endif()
|
endif()
|
||||||
if(@BUILD_DROGON_SHARED@)
|
if(@yaml-cpp_FOUND@)
|
||||||
|
find_dependency(yaml-cpp)
|
||||||
|
endif()
|
||||||
|
if(@BUILD_SHARED_LIBS@)
|
||||||
find_dependency(Threads)
|
find_dependency(Threads)
|
||||||
endif()
|
endif()
|
||||||
if(@HAS_STD_FILESYSTEM_PATH@)
|
if(@HAS_STD_FILESYSTEM_PATH@)
|
||||||
@ -48,6 +47,7 @@ find_dependency(Filesystem)
|
|||||||
find_package(Filesystem COMPONENTS Final REQUIRED)
|
find_package(Filesystem COMPONENTS Final REQUIRED)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
# Our library dependencies (contains definitions for IMPORTED targets)
|
# Our library dependencies (contains definitions for IMPORTED targets)
|
||||||
|
|
||||||
get_filename_component(DROGON_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
|
get_filename_component(DROGON_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
#define MAJOR @DROGON_MAJOR_VERSION@
|
#define MAJOR @DROGON_MAJOR_VERSION@
|
||||||
#define MINOR @DROGON_MINOR_VERSION@
|
#define MINOR @DROGON_MINOR_VERSION@
|
||||||
#define PATCH @DROGON_PATCH_VERSION@
|
#define PATCH @DROGON_PATCH_VERSION@
|
||||||
#define DROGON_VERSION "@DROGON_VERSION_STRING@"
|
#define DROGON_VERSION "@DROGON_VERSION_STRING@"
|
||||||
#define DROGON_VERSION_SHA1 "@GIT_SHA1@"
|
#define DROGON_VERSION_SHA1 "@GIT_SHA1@"
|
||||||
|
@ -2,11 +2,8 @@
|
|||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
PQisInBatchMode(NULL);
|
PQenterPipelineMode(NULL);
|
||||||
PQbatchIsAborted(NULL);
|
PQexitPipelineMode(NULL);
|
||||||
PQqueriesInBatch(NULL);
|
PQpipelineSync(NULL);
|
||||||
PQbeginBatchMode(NULL);
|
PQpipelineStatus(NULL);
|
||||||
PQendBatchMode(NULL);
|
|
||||||
PQsendEndBatch(NULL);
|
|
||||||
PQgetNextQuery(NULL);
|
|
||||||
}
|
}
|
||||||
|
@ -23,9 +23,9 @@ include(FindPackageHandleStandardArgs)
|
|||||||
|
|
||||||
find_path(BROTLI_INCLUDE_DIR "brotli/decode.h")
|
find_path(BROTLI_INCLUDE_DIR "brotli/decode.h")
|
||||||
|
|
||||||
find_library(BROTLICOMMON_LIBRARY NAMES brotlicommon)
|
find_library(BROTLICOMMON_LIBRARY NAMES brotlicommon brotlicommon-static)
|
||||||
find_library(BROTLIDEC_LIBRARY NAMES brotlidec)
|
find_library(BROTLIDEC_LIBRARY NAMES brotlidec brotlidec-static)
|
||||||
find_library(BROTLIENC_LIBRARY NAMES brotlienc)
|
find_library(BROTLIENC_LIBRARY NAMES brotlienc brotlienc-static)
|
||||||
|
|
||||||
find_package_handle_standard_args(Brotli
|
find_package_handle_standard_args(Brotli
|
||||||
REQUIRED_VARS
|
REQUIRED_VARS
|
||||||
|
@ -102,8 +102,14 @@ if(TARGET std::filesystem)
|
|||||||
return()
|
return()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.10)
|
# Ignore filesystem check if version too low
|
||||||
|
if(CMAKE_VERSION VERSION_LESS 3.10)
|
||||||
|
set(CXX_FILESYSTEM_HAVE_FS FALSE CACHE BOOL "TRUE if we have the C++ filesystem headers")
|
||||||
|
set(Filesystem_FOUND FALSE CACHE BOOL "TRUE if we can run a program using std::filesystem" FORCE)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.10)
|
||||||
include(CMakePushCheckState)
|
include(CMakePushCheckState)
|
||||||
include(CheckIncludeFileCXX)
|
include(CheckIncludeFileCXX)
|
||||||
|
|
||||||
@ -126,6 +132,7 @@ cmake_push_check_state()
|
|||||||
set(CMAKE_REQUIRED_QUIET ${Filesystem_FIND_QUIETLY})
|
set(CMAKE_REQUIRED_QUIET ${Filesystem_FIND_QUIETLY})
|
||||||
|
|
||||||
# All of our tests required C++17 or later
|
# All of our tests required C++17 or later
|
||||||
|
set(BACKUP_CXX_STANDARD "${CMAKE_CXX_STANDARD}")
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
|
||||||
# Normalize and check the component list we were given
|
# Normalize and check the component list we were given
|
||||||
@ -194,16 +201,21 @@ set(_found FALSE)
|
|||||||
if(CXX_FILESYSTEM_HAVE_FS)
|
if(CXX_FILESYSTEM_HAVE_FS)
|
||||||
# We have some filesystem library available. Do link checks
|
# We have some filesystem library available. Do link checks
|
||||||
string(CONFIGURE [[
|
string(CONFIGURE [[
|
||||||
#include <cstdlib>
|
#include <cstdio>
|
||||||
#include <@CXX_FILESYSTEM_HEADER@>
|
#include <@CXX_FILESYSTEM_HEADER@>
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
auto cwd = @CXX_FILESYSTEM_NAMESPACE@::current_path();
|
auto cwd = @CXX_FILESYSTEM_NAMESPACE@::current_path();
|
||||||
printf("%s", cwd.c_str());
|
printf("%s", cwd.generic_string().c_str());
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
]] code @ONLY)
|
]] code @ONLY)
|
||||||
|
|
||||||
|
# HACK: Needed to compile correctly on Yocto Linux
|
||||||
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang"
|
||||||
|
OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
|
||||||
|
set(CMAKE_REQUIRED_FLAGS ${prev_req_flags} -std=c++17)
|
||||||
|
endif ()
|
||||||
# Check a simple filesystem program without any linker flags
|
# Check a simple filesystem program without any linker flags
|
||||||
_cmcm_check_cxx_source("${code}" CXX_FILESYSTEM_NO_LINK_NEEDED)
|
_cmcm_check_cxx_source("${code}" CXX_FILESYSTEM_NO_LINK_NEEDED)
|
||||||
|
|
||||||
@ -246,3 +258,4 @@ if(Filesystem_FIND_REQUIRED AND NOT Filesystem_FOUND)
|
|||||||
message(FATAL_ERROR "Cannot run simple program using std::filesystem")
|
message(FATAL_ERROR "Cannot run simple program using std::filesystem")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD "${BACKUP_CXX_STANDARD}")
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
if (HIREDIS_INCLUDE_DIRS AND HIREDIS_LIBRARIES)
|
if (HIREDIS_INCLUDE_DIRS AND HIREDIS_LIBRARIES)
|
||||||
set(HIREDIS_FIND_QUIETLY TRUE)
|
set(HIREDIS_FIND_QUIETLY TRUE)
|
||||||
|
set(Hiredis_FOUND TRUE)
|
||||||
else ()
|
else ()
|
||||||
find_path(
|
find_path(
|
||||||
HIREDIS_INCLUDE_DIR
|
HIREDIS_INCLUDE_DIR
|
||||||
|
@ -44,13 +44,16 @@ if(Jsoncpp_FOUND)
|
|||||||
message(FATAL_ERROR "Error: jsoncpp lib is too old.....stop")
|
message(FATAL_ERROR "Error: jsoncpp lib is too old.....stop")
|
||||||
endif()
|
endif()
|
||||||
if(NOT WIN32)
|
if(NOT WIN32)
|
||||||
exec_program(
|
execute_process(
|
||||||
cat
|
COMMAND cat ${JSONCPP_INCLUDE_DIRS}/json/version.h
|
||||||
ARGS
|
COMMAND grep JSONCPP_VERSION_STRING
|
||||||
"${JSONCPP_INCLUDE_DIRS}/json/version.h |grep JSONCPP_VERSION_STRING|sed s'/.*define/define/'|awk '{printf $3}'|sed s'/\"//g'"
|
COMMAND sed -e "s/.*define/define/"
|
||||||
OUTPUT_VARIABLE
|
COMMAND awk "{ printf \$3 }"
|
||||||
jsoncpp_ver)
|
COMMAND sed -e "s/\"//g"
|
||||||
message(STATUS "jsoncpp verson:" ${jsoncpp_ver})
|
OUTPUT_VARIABLE jsoncpp_ver)
|
||||||
|
if(NOT Jsoncpp_FIND_QUIETLY)
|
||||||
|
message(STATUS "jsoncpp version:" ${jsoncpp_ver})
|
||||||
|
endif()
|
||||||
if(jsoncpp_ver LESS 1.7)
|
if(jsoncpp_ver LESS 1.7)
|
||||||
message(
|
message(
|
||||||
FATAL_ERROR
|
FATAL_ERROR
|
||||||
@ -58,7 +61,9 @@ if(Jsoncpp_FOUND)
|
|||||||
)
|
)
|
||||||
endif(jsoncpp_ver LESS 1.7)
|
endif(jsoncpp_ver LESS 1.7)
|
||||||
endif()
|
endif()
|
||||||
add_library(Jsoncpp_lib INTERFACE IMPORTED)
|
if (NOT TARGET Jsoncpp_lib)
|
||||||
|
add_library(Jsoncpp_lib INTERFACE IMPORTED)
|
||||||
|
endif()
|
||||||
set_target_properties(Jsoncpp_lib
|
set_target_properties(Jsoncpp_lib
|
||||||
PROPERTIES INTERFACE_INCLUDE_DIRECTORIES
|
PROPERTIES INTERFACE_INCLUDE_DIRECTORIES
|
||||||
"${JSONCPP_INCLUDE_DIRS}"
|
"${JSONCPP_INCLUDE_DIRS}"
|
||||||
|
@ -27,6 +27,26 @@
|
|||||||
# ##############################################################################
|
# ##############################################################################
|
||||||
|
|
||||||
# -------------- FIND MYSQL_INCLUDE_DIRS ------------------
|
# -------------- FIND MYSQL_INCLUDE_DIRS ------------------
|
||||||
|
find_path(MARIADB_INCLUDE_DIRS
|
||||||
|
NAMES mysql.h
|
||||||
|
PATH_SUFFIXES mariadb
|
||||||
|
PATHS /usr/include/mysql
|
||||||
|
/usr/local/include/mysql
|
||||||
|
/usr/include/mariadb
|
||||||
|
/usr/local/include/mariadb
|
||||||
|
/opt/mysql/mysql/include
|
||||||
|
/opt/mysql/mysql/include/mysql
|
||||||
|
/opt/mysql/include
|
||||||
|
/opt/local/include/mysql5
|
||||||
|
/usr/local/mysql/include
|
||||||
|
/usr/local/mysql/include/mysql
|
||||||
|
/usr/local/mariadb/include
|
||||||
|
/usr/local/mariadb/include/mariadb
|
||||||
|
/opt/rh/rh-mariadb105/root/usr/include
|
||||||
|
/opt/rh/rh-mariadb105/root/usr/include/mysql
|
||||||
|
$ENV{ProgramFiles}/MySQL/*/include
|
||||||
|
$ENV{SystemDrive}/MySQL/*/include)
|
||||||
|
|
||||||
find_path(MYSQL_INCLUDE_DIRS
|
find_path(MYSQL_INCLUDE_DIRS
|
||||||
NAMES mysql.h
|
NAMES mysql.h
|
||||||
PATH_SUFFIXES mysql
|
PATH_SUFFIXES mysql
|
||||||
@ -47,7 +67,9 @@ find_path(MYSQL_INCLUDE_DIRS
|
|||||||
$ENV{ProgramFiles}/MySQL/*/include
|
$ENV{ProgramFiles}/MySQL/*/include
|
||||||
$ENV{SystemDrive}/MySQL/*/include)
|
$ENV{SystemDrive}/MySQL/*/include)
|
||||||
|
|
||||||
if(EXISTS "${MYSQL_INCLUDE_DIRS}/mysql.h")
|
if(EXISTS "${MARIADB_INCLUDE_DIRS}/mysql.h")
|
||||||
|
set(MYSQL_INCLUDE_DIRS ${MARIADB_INCLUDE_DIRS})
|
||||||
|
elseif(EXISTS "${MYSQL_INCLUDE_DIRS}/mysql.h")
|
||||||
|
|
||||||
elseif(EXISTS "${MYSQL_INCLUDE_DIRS}/mysql/mysql.h")
|
elseif(EXISTS "${MYSQL_INCLUDE_DIRS}/mysql/mysql.h")
|
||||||
set(MYSQL_INCLUDE_DIRS ${MYSQL_INCLUDE_DIRS}/mysql)
|
set(MYSQL_INCLUDE_DIRS ${MYSQL_INCLUDE_DIRS}/mysql)
|
||||||
@ -77,7 +99,7 @@ if(WIN32)
|
|||||||
$ENV{SystemDrive}/MySQL/*/lib/${libsuffixDist})
|
$ENV{SystemDrive}/MySQL/*/lib/${libsuffixDist})
|
||||||
else(WIN32)
|
else(WIN32)
|
||||||
find_library(MYSQL_LIBRARIES
|
find_library(MYSQL_LIBRARIES
|
||||||
NAMES mysqlclient_r mariadbclient
|
NAMES mysqlclient_r mariadbclient mariadb
|
||||||
PATHS /usr/lib/mysql
|
PATHS /usr/lib/mysql
|
||||||
/usr/lib/mariadb
|
/usr/lib/mariadb
|
||||||
/usr/local/lib/mysql
|
/usr/local/lib/mysql
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
if(UUID_LIBRARIES AND UUID_INCLUDE_DIRS)
|
if(UUID_LIBRARIES AND UUID_INCLUDE_DIRS)
|
||||||
# in cache already
|
# in cache already
|
||||||
set(UUID_FOUND TRUE)
|
set(UUID_FOUND TRUE)
|
||||||
else(UUID_LIBRARIES AND UUID_INCLUDE_DIRS)
|
else()
|
||||||
find_path(
|
find_path(
|
||||||
UUID_INCLUDE_DIR
|
UUID_INCLUDE_DIR
|
||||||
NAMES uuid.h
|
NAMES uuid.h
|
||||||
@ -76,34 +76,34 @@ else(UUID_LIBRARIES AND UUID_INCLUDE_DIRS)
|
|||||||
/opt/lib
|
/opt/lib
|
||||||
/usr/freeware/lib64)
|
/usr/freeware/lib64)
|
||||||
|
|
||||||
if(NOT UUID_LIBRARY AND BSD)
|
if(NOT UUID_LIBRARY AND (BSD OR APPLE))
|
||||||
set(UUID_LIBRARY "")
|
set(UUID_LIBRARY "")
|
||||||
endif(NOT UUID_LIBRARY AND BSD)
|
endif()
|
||||||
|
|
||||||
set(UUID_INCLUDE_DIRS ${UUID_INCLUDE_DIR})
|
set(UUID_INCLUDE_DIRS ${UUID_INCLUDE_DIR})
|
||||||
set(UUID_LIBRARIES ${UUID_LIBRARY})
|
set(UUID_LIBRARIES ${UUID_LIBRARY})
|
||||||
|
|
||||||
if(UUID_INCLUDE_DIRS)
|
if(UUID_INCLUDE_DIRS)
|
||||||
if(BSD OR UUID_LIBRARIES)
|
if((BSD OR APPLE) OR UUID_LIBRARIES)
|
||||||
set(UUID_FOUND TRUE)
|
set(UUID_FOUND TRUE)
|
||||||
endif(BSD OR UUID_LIBRARIES)
|
endif()
|
||||||
endif(UUID_INCLUDE_DIRS)
|
endif()
|
||||||
|
|
||||||
if(UUID_FOUND)
|
if(UUID_FOUND)
|
||||||
if(NOT UUID_FIND_QUIETLY)
|
if(NOT UUID_FIND_QUIETLY)
|
||||||
message(STATUS "Found UUID: ${UUID_LIBRARIES}")
|
message(STATUS "Found UUID: ${UUID_LIBRARIES}")
|
||||||
endif(NOT UUID_FIND_QUIETLY)
|
endif()
|
||||||
else(UUID_FOUND)
|
else()
|
||||||
if(UUID_FIND_REQUIRED)
|
if(UUID_FIND_REQUIRED)
|
||||||
message(FATAL_ERROR "Could not find UUID")
|
message(FATAL_ERROR "Could not find UUID")
|
||||||
endif(UUID_FIND_REQUIRED)
|
endif()
|
||||||
endif(UUID_FOUND)
|
endif()
|
||||||
|
|
||||||
# show the UUID_INCLUDE_DIRS and UUID_LIBRARIES variables only in the advanced
|
# show the UUID_INCLUDE_DIRS and UUID_LIBRARIES variables only in the advanced
|
||||||
# view
|
# view
|
||||||
mark_as_advanced(UUID_INCLUDE_DIRS UUID_LIBRARIES)
|
mark_as_advanced(UUID_INCLUDE_DIRS UUID_LIBRARIES)
|
||||||
|
|
||||||
endif(UUID_LIBRARIES AND UUID_INCLUDE_DIRS)
|
endif()
|
||||||
|
|
||||||
if(UUID_FOUND)
|
if(UUID_FOUND)
|
||||||
add_library(UUID_lib INTERFACE IMPORTED)
|
add_library(UUID_lib INTERFACE IMPORTED)
|
||||||
@ -112,7 +112,7 @@ if(UUID_FOUND)
|
|||||||
"${UUID_INCLUDE_DIRS}"
|
"${UUID_INCLUDE_DIRS}"
|
||||||
INTERFACE_LINK_LIBRARIES
|
INTERFACE_LINK_LIBRARIES
|
||||||
"${UUID_LIBRARIES}")
|
"${UUID_LIBRARIES}")
|
||||||
else(UUID_FOUND)
|
else()
|
||||||
set(UUID_LIBRARIES)
|
set(UUID_LIBRARIES)
|
||||||
set(UUID_INCLUDE_DIRS)
|
set(UUID_INCLUDE_DIRS)
|
||||||
endif(UUID_FOUND)
|
endif()
|
||||||
|
@ -2,14 +2,14 @@
|
|||||||
jsoncpp/1.9.4
|
jsoncpp/1.9.4
|
||||||
zlib/1.2.11
|
zlib/1.2.11
|
||||||
gtest/1.10.0
|
gtest/1.10.0
|
||||||
sqlite3/3.34.1
|
sqlite3/3.40.1
|
||||||
#libpq/13.2
|
#libpq/13.2
|
||||||
openssl/1.1.1j
|
openssl/1.1.1t
|
||||||
hiredis/1.0.0
|
hiredis/1.0.0
|
||||||
brotli/1.0.9
|
brotli/1.0.9
|
||||||
|
|
||||||
[generators]
|
[generators]
|
||||||
cmake_paths
|
CMakeToolchain
|
||||||
|
|
||||||
[options]
|
[options]
|
||||||
|
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
//ssl:The global SSL settings. "key" and "cert" are the path to the SSL key and certificate. While
|
//ssl:The global SSL settings. "key" and "cert" are the path to the SSL key and certificate. While
|
||||||
// "conf" is an array of 1 or 2-element tuples that supplies file style options for `SSL_CONF_cmd`.
|
// "conf" is an array of 1 or 2-element tuples that supplies file style options for `SSL_CONF_cmd`.
|
||||||
"ssl": {
|
"ssl": {
|
||||||
"cert": "../../trantor/trantor/tests/server.pem",
|
"cert": "../../trantor/trantor/tests/server.crt",
|
||||||
"key": "../../trantor/trantor/tests/server.pem",
|
"key": "../../trantor/trantor/tests/server.key",
|
||||||
"conf": [
|
"conf": [
|
||||||
//["Options", "-SessionTicket"],
|
//["Options", "-SessionTicket"],
|
||||||
//["Options", "Compression"]
|
//["Options", "Compression"]
|
||||||
@ -39,7 +39,7 @@
|
|||||||
"db_clients": [
|
"db_clients": [
|
||||||
{
|
{
|
||||||
//name: Name of the client,'default' by default
|
//name: Name of the client,'default' by default
|
||||||
//"name":"",
|
"name": "default",
|
||||||
//rdbms: Server type, postgresql,mysql or sqlite3, "postgresql" by default
|
//rdbms: Server type, postgresql,mysql or sqlite3, "postgresql" by default
|
||||||
"rdbms": "postgresql",
|
"rdbms": "postgresql",
|
||||||
//filename: Sqlite3 db file name
|
//filename: Sqlite3 db file name
|
||||||
@ -65,17 +65,25 @@
|
|||||||
"number_of_connections": 1,
|
"number_of_connections": 1,
|
||||||
//timeout: -1.0 by default, in seconds, the timeout for executing a SQL query.
|
//timeout: -1.0 by default, in seconds, the timeout for executing a SQL query.
|
||||||
//zero or negative value means no timeout.
|
//zero or negative value means no timeout.
|
||||||
"timeout": -1.0
|
"timeout": -1.0,
|
||||||
|
//auto_batch: this feature is only available for the PostgreSQL driver(version >= 14.0), see
|
||||||
|
//the wiki for more details.
|
||||||
|
"auto_batch": false
|
||||||
|
//connect_options: extra options for the connection. Only works for PostgreSQL now.
|
||||||
|
//For more information, see https://www.postgresql.org/docs/16/libpq-connect.html#LIBPQ-CONNECT-OPTIONS
|
||||||
|
//"connect_options": { "statement_timeout": "1s" }
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"redis_clients": [
|
"redis_clients": [
|
||||||
{
|
{
|
||||||
//name: Name of the client,'default' by default
|
//name: Name of the client,'default' by default
|
||||||
//"name":"",
|
"name": "default",
|
||||||
//host: Server IP, 127.0.0.1 by default
|
//host: Server IP, 127.0.0.1 by default
|
||||||
"host": "127.0.0.1",
|
"host": "127.0.0.1",
|
||||||
//port: Server port, 6379 by default
|
//port: Server port, 6379 by default
|
||||||
"port": 6379,
|
"port": 6379,
|
||||||
|
//username: '' by default which means 'default' in redis ACL
|
||||||
|
"username": "",
|
||||||
//passwd: '' by default
|
//passwd: '' by default
|
||||||
"passwd": "",
|
"passwd": "",
|
||||||
//db index: 0 by default
|
//db index: 0 by default
|
||||||
@ -98,7 +106,14 @@
|
|||||||
//enable_session: False by default
|
//enable_session: False by default
|
||||||
"enable_session": true,
|
"enable_session": true,
|
||||||
"session_timeout": 0,
|
"session_timeout": 0,
|
||||||
//document_root: Root path of HTTP document, defaut path is ./
|
//string value of SameSite attribute of the Set-Cookie HTTP response header
|
||||||
|
//valid value is either 'Null' (default), 'Lax', 'Strict' or 'None'
|
||||||
|
"session_same_site": "Null",
|
||||||
|
//session_cookie_key: The cookie key of the session, "JSESSIONID" by default
|
||||||
|
"session_cookie_key": "JSESSIONID",
|
||||||
|
//session_max_age: The max age of the session cookie, -1 by default
|
||||||
|
"session_max_age": -1,
|
||||||
|
//document_root: Root path of HTTP document, default path is ./
|
||||||
"document_root": "./",
|
"document_root": "./",
|
||||||
//home_page: Set the HTML file of the home page, the default value is "index.html"
|
//home_page: Set the HTML file of the home page, the default value is "index.html"
|
||||||
//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
|
//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
|
||||||
@ -111,10 +126,10 @@
|
|||||||
"implicit_page": "index.html",
|
"implicit_page": "index.html",
|
||||||
//static_file_headers: Headers for static files
|
//static_file_headers: Headers for static files
|
||||||
/*"static_file_headers": [
|
/*"static_file_headers": [
|
||||||
{
|
{
|
||||||
"name": "field-name",
|
"name": "field-name",
|
||||||
"value": "field-value"
|
"value": "field-value"
|
||||||
}
|
}
|
||||||
],*/
|
],*/
|
||||||
//upload_path: The path to save the uploaded file. "uploads" by default.
|
//upload_path: The path to save the uploaded file. "uploads" by default.
|
||||||
//If the path isn't prefixed with /, ./ or ../,
|
//If the path isn't prefixed with /, ./ or ../,
|
||||||
@ -137,8 +152,16 @@
|
|||||||
"xap",
|
"xap",
|
||||||
"apk",
|
"apk",
|
||||||
"cur",
|
"cur",
|
||||||
"xml"
|
"xml",
|
||||||
|
"webp",
|
||||||
|
"svg"
|
||||||
],
|
],
|
||||||
|
// mime: A dictionary that extends the internal MIME type support. Maps extensions into new MIME types
|
||||||
|
// note: This option only adds MIME to the sever. `file_types` above have to be set for the server to serve them.
|
||||||
|
"mime": {
|
||||||
|
// "text/markdown": "md",
|
||||||
|
// "text/gemini": ["gmi", "gemini"]
|
||||||
|
},
|
||||||
//locations: An array of locations of static files for GET requests.
|
//locations: An array of locations of static files for GET requests.
|
||||||
"locations": [
|
"locations": [
|
||||||
{
|
{
|
||||||
@ -164,7 +187,7 @@
|
|||||||
],
|
],
|
||||||
//max_connections: maximum number of connections, 100000 by default
|
//max_connections: maximum number of connections, 100000 by default
|
||||||
"max_connections": 100000,
|
"max_connections": 100000,
|
||||||
//max_connections_per_ip: maximum number of connections per clinet, 0 by default which means no limit
|
//max_connections_per_ip: maximum number of connections per client, 0 by default which means no limit
|
||||||
"max_connections_per_ip": 0,
|
"max_connections_per_ip": 0,
|
||||||
//Load_dynamic_views: False by default, when set to true, drogon
|
//Load_dynamic_views: False by default, when set to true, drogon
|
||||||
//compiles and loads dynamically "CSP View Files" in directories defined
|
//compiles and loads dynamically "CSP View Files" in directories defined
|
||||||
@ -179,6 +202,8 @@
|
|||||||
//files is the path where the csp files locate. If the path isn't prefixed with /, it is relative
|
//files is the path where the csp files locate. If the path isn't prefixed with /, it is relative
|
||||||
//path of the current working directory.
|
//path of the current working directory.
|
||||||
"dynamic_views_output_path": "",
|
"dynamic_views_output_path": "",
|
||||||
|
//json_parser_stack_limit: 1000 by default, the maximum number of stack depth when reading a json string by the jsoncpp library.
|
||||||
|
"json_parser_stack_limit": 1000,
|
||||||
//enable_unicode_escaping_in_json: true by default, enable unicode escaping in json.
|
//enable_unicode_escaping_in_json: true by default, enable unicode escaping in json.
|
||||||
"enable_unicode_escaping_in_json": true,
|
"enable_unicode_escaping_in_json": true,
|
||||||
//float_precision_in_json: set precision of float number in json.
|
//float_precision_in_json: set precision of float number in json.
|
||||||
@ -192,6 +217,8 @@
|
|||||||
},
|
},
|
||||||
//log: Set log output, drogon output logs to stdout by default
|
//log: Set log output, drogon output logs to stdout by default
|
||||||
"log": {
|
"log": {
|
||||||
|
//use_spdlog: Use spdlog library to log
|
||||||
|
"use_spdlog": false,
|
||||||
//log_path: Log file path,empty by default,in which case,logs are output to the stdout
|
//log_path: Log file path,empty by default,in which case,logs are output to the stdout
|
||||||
//"log_path": "./",
|
//"log_path": "./",
|
||||||
//logfile_base_name: Log file base name,empty by default which means drogon names logfile as
|
//logfile_base_name: Log file base name,empty by default which means drogon names logfile as
|
||||||
@ -200,9 +227,14 @@
|
|||||||
//log_size_limit: 100000000 bytes by default,
|
//log_size_limit: 100000000 bytes by default,
|
||||||
//When the log file size reaches "log_size_limit", the log file is switched.
|
//When the log file size reaches "log_size_limit", the log file is switched.
|
||||||
"log_size_limit": 100000000,
|
"log_size_limit": 100000000,
|
||||||
|
//max_files: 0 by default,
|
||||||
|
//When the number of old log files exceeds "max_files", the oldest file will be deleted. 0 means never delete.
|
||||||
|
"max_files": 0,
|
||||||
//log_level: "DEBUG" by default,options:"TRACE","DEBUG","INFO","WARN"
|
//log_level: "DEBUG" by default,options:"TRACE","DEBUG","INFO","WARN"
|
||||||
//The TRACE level is only valid when built in DEBUG mode.
|
//The TRACE level is only valid when built in DEBUG mode.
|
||||||
"log_level": "DEBUG"
|
"log_level": "DEBUG",
|
||||||
|
//display_local_time: false by default, if true, the log time is displayed in local time
|
||||||
|
"display_local_time": false
|
||||||
},
|
},
|
||||||
//run_as_daemon: False by default
|
//run_as_daemon: False by default
|
||||||
"run_as_daemon": false,
|
"run_as_daemon": false,
|
||||||
@ -221,19 +253,19 @@
|
|||||||
//0 means cache forever, the negative value means no cache
|
//0 means cache forever, the negative value means no cache
|
||||||
"static_files_cache_time": 5,
|
"static_files_cache_time": 5,
|
||||||
//simple_controllers_map: Used to configure mapping from path to simple controller
|
//simple_controllers_map: Used to configure mapping from path to simple controller
|
||||||
"simple_controllers_map": [
|
//"simple_controllers_map": [
|
||||||
{
|
// {
|
||||||
"path": "/path/name",
|
// "path": "/path/name",
|
||||||
"controller": "controllerClassName",
|
// "controller": "controllerClassName",
|
||||||
"http_methods": [
|
// "http_methods": [
|
||||||
"get",
|
// "get",
|
||||||
"post"
|
// "post"
|
||||||
],
|
// ],
|
||||||
"filters": [
|
// "filters": [
|
||||||
"FilterClassName"
|
// "FilterClassName"
|
||||||
]
|
// ]
|
||||||
}
|
// }
|
||||||
],
|
//],
|
||||||
//idle_connection_timeout: Defaults to 60 seconds, the lifetime
|
//idle_connection_timeout: Defaults to 60 seconds, the lifetime
|
||||||
//of the connection without read or write
|
//of the connection without read or write
|
||||||
"idle_connection_timeout": 60,
|
"idle_connection_timeout": 60,
|
||||||
@ -273,22 +305,43 @@
|
|||||||
//One can set it to "1024", "1k", "10M", "1G", etc. Setting it to "" means no limit.
|
//One can set it to "1024", "1k", "10M", "1G", etc. Setting it to "" means no limit.
|
||||||
"client_max_websocket_message_size": "128K",
|
"client_max_websocket_message_size": "128K",
|
||||||
//reuse_port: Defaults to false, users can run multiple processes listening on the same port at the same time.
|
//reuse_port: Defaults to false, users can run multiple processes listening on the same port at the same time.
|
||||||
"reuse_port": false
|
"reuse_port": false,
|
||||||
|
// enabled_compressed_request: Defaults to false. If true the server will automatically decompress compressed request bodies.
|
||||||
|
// Currently only gzip and br are supported. Note: max_memory_body_size and max_body_size applies twice for compressed requests.
|
||||||
|
// Once when receiving and once when decompressing. i.e. if the decompressed body is larger than max_body_size, the request
|
||||||
|
// will be rejected.
|
||||||
|
"enabled_compressed_request": false,
|
||||||
|
// enable_request_stream: Defaults to false. If true the server will enable stream mode for http requests.
|
||||||
|
// See the wiki for more details.
|
||||||
|
"enable_request_stream": false,
|
||||||
},
|
},
|
||||||
//plugins: Define all plugins running in the application
|
//plugins: Define all plugins running in the application
|
||||||
"plugins": [
|
"plugins": [
|
||||||
{
|
{
|
||||||
//name: The class name of the plugin
|
//name: The class name of the plugin
|
||||||
//"name": "drogon::plugin::SecureSSLRedirector",
|
"name": "drogon::plugin::PromExporter",
|
||||||
//dependencies: Plugins that the plugin depends on. It can be commented out
|
//dependencies: Plugins that the plugin depends on. It can be commented out
|
||||||
"dependencies": [],
|
"dependencies": [],
|
||||||
//config: The configuration of the plugin. This json object is the parameter to initialize the plugin.
|
//config: The configuration of the plugin. This json object is the parameter to initialize the plugin.
|
||||||
//It can be commented out
|
//It can be commented out
|
||||||
"config": {
|
"config": {
|
||||||
"ssl_redirect_exempt": [
|
"path": "/metrics"
|
||||||
".*\\.jpg"
|
}
|
||||||
],
|
},
|
||||||
"secure_ssl_host": "localhost:8849"
|
{
|
||||||
|
"name": "drogon::plugin::AccessLogger",
|
||||||
|
"dependencies": [],
|
||||||
|
"config": {
|
||||||
|
"use_spdlog": false,
|
||||||
|
"log_path": "",
|
||||||
|
"log_format": "",
|
||||||
|
"log_file": "access.log",
|
||||||
|
"log_size_limit": 0,
|
||||||
|
"use_local_time": true,
|
||||||
|
"log_index": 0,
|
||||||
|
// "show_microseconds": true,
|
||||||
|
// "custom_time_format": "",
|
||||||
|
// "use_real_ip": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
318
config.example.yaml
Normal file
318
config.example.yaml
Normal file
@ -0,0 +1,318 @@
|
|||||||
|
# This is a YAML format configuration file
|
||||||
|
|
||||||
|
# ssl:The global SSL settings. "key" and "cert" are the path to the SSL key and certificate. While
|
||||||
|
# "conf" is an array of 1 or 2-element tuples that supplies file style options for `SSL_CONF_cmd`.
|
||||||
|
# ssl:
|
||||||
|
# cert: ../../trantor/trantor/tests/server.crt
|
||||||
|
# key: ../../trantor/trantor/tests/server.key
|
||||||
|
# conf: [
|
||||||
|
# # [Options, -SessionTicket],
|
||||||
|
# # [Options, Compression]
|
||||||
|
# ]
|
||||||
|
# listeners:
|
||||||
|
# # address: Ip address,0.0.0.0 by default
|
||||||
|
# - address: 0.0.0.0
|
||||||
|
# # port: Port number
|
||||||
|
# port: 80
|
||||||
|
# # https: If true, use https for security,false by default
|
||||||
|
# https: false
|
||||||
|
# - address: 0.0.0.0
|
||||||
|
# port: 443
|
||||||
|
# https: true
|
||||||
|
# # cert,key: Cert file path and key file path, empty by default,
|
||||||
|
# # if empty, use the global setting
|
||||||
|
# cert: ''
|
||||||
|
# key: ''
|
||||||
|
# # use_old_tls: enable the TLS1.0/1.1, false by default
|
||||||
|
# use_old_tls: false
|
||||||
|
# ssl_conf: [
|
||||||
|
# # [MinProtocol, TLSv1.3]
|
||||||
|
# ]
|
||||||
|
# db_clients:
|
||||||
|
# # name: Name of the client,'default' by default
|
||||||
|
# - name: default
|
||||||
|
# # rdbms: Server type, postgresql,mysql or sqlite3, "postgresql" by default
|
||||||
|
# rdbms: postgresql
|
||||||
|
# # filename: Sqlite3 db file name
|
||||||
|
# # filename: ''
|
||||||
|
# # host: Server address,localhost by default
|
||||||
|
# host: 127.0.0.1
|
||||||
|
# # port: Server port, 5432 by default
|
||||||
|
# port: 5432
|
||||||
|
# # dbname: Database name
|
||||||
|
# dbname: test
|
||||||
|
# # user: 'postgres' by default
|
||||||
|
# user: ''
|
||||||
|
# # passwd: '' by default
|
||||||
|
# passwd: ''
|
||||||
|
# # is_fast: false by default, if it is true, the client is faster but user can't call
|
||||||
|
# # any synchronous interface of it.
|
||||||
|
# is_fast: false
|
||||||
|
# # client_encoding: The character set used by the client. it is empty string by default which
|
||||||
|
# # means use the default character set.
|
||||||
|
# # client_encoding: ''
|
||||||
|
# # number_of_connections: 1 by default, if the 'is_fast' is true, the number is the number of
|
||||||
|
# # connections per IO thread, otherwise it is the total number of all connections.
|
||||||
|
# number_of_connections: 1
|
||||||
|
# # timeout: -1 by default, in seconds, the timeout for executing a SQL query.
|
||||||
|
# # zero or negative value means no timeout.
|
||||||
|
# timeout: -1
|
||||||
|
# # auto_batch: this feature is only available for the PostgreSQL driver(version >= 14.0), see
|
||||||
|
# # the wiki for more details.
|
||||||
|
# auto_batch: false
|
||||||
|
# # connect_options: extra options for the connection. Only works for PostgreSQL now.
|
||||||
|
# # For more information, see https://www.postgresql.org/docs/16/libpq-connect.html#LIBPQ-CONNECT-OPTIONS
|
||||||
|
# # connect_options:
|
||||||
|
# # statement_timeout: '1s'
|
||||||
|
# redis_clients:
|
||||||
|
# # name: Name of the client,'default' by default
|
||||||
|
# - name: default
|
||||||
|
# # host: Server IP, 127.0.0.1 by default
|
||||||
|
# host: 127.0.0.1
|
||||||
|
# # port: Server port, 6379 by default
|
||||||
|
# port: 6379
|
||||||
|
# # username: '' by default which means 'default' in redis ACL
|
||||||
|
# username: ''
|
||||||
|
# # passwd: '' by default
|
||||||
|
# passwd: ''
|
||||||
|
# # db index: 0 by default
|
||||||
|
# db: 0
|
||||||
|
# # is_fast: false by default, if it is true, the client is faster but user can't call
|
||||||
|
# # any synchronous interface of it.
|
||||||
|
# is_fast: false
|
||||||
|
# # number_of_connections: 1 by default, if the 'is_fast' is true, the number is the number of
|
||||||
|
# # connections per IO thread, otherwise it is the total number of all connections.
|
||||||
|
# number_of_connections: 1
|
||||||
|
# # timeout: -1.0 by default, in seconds, the timeout for executing a command.
|
||||||
|
# # zero or negative value means no timeout.
|
||||||
|
# timeout: -1
|
||||||
|
app:
|
||||||
|
# number_of_threads: The number of IO threads, 1 by default, if the value is set to 0, the number of threads
|
||||||
|
# is the number of CPU cores
|
||||||
|
number_of_threads: 1
|
||||||
|
# enable_session: False by default
|
||||||
|
enable_session: true
|
||||||
|
session_timeout: 0
|
||||||
|
# string value of SameSite attribute of the Set-Cookie HTTP response header
|
||||||
|
# valid value is either 'Null' (default), 'Lax', 'Strict' or 'None'
|
||||||
|
session_same_site: 'Null'
|
||||||
|
# session_cookie_key: The cookie key of the session, "JSESSIONID" by default
|
||||||
|
session_cookie_key: 'JSESSIONID'
|
||||||
|
# session_max_age: The max age of the session cookie, -1 by default
|
||||||
|
session_max_age: -1
|
||||||
|
# document_root: Root path of HTTP document, default path is ./
|
||||||
|
document_root: ./
|
||||||
|
# home_page: Set the HTML file of the home page, the default value is "index.html"
|
||||||
|
# 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
|
||||||
|
# to the request for "/".
|
||||||
|
home_page: index.html
|
||||||
|
# use_implicit_page: enable implicit pages if true, true by default
|
||||||
|
use_implicit_page: true
|
||||||
|
# implicit_page: Set the file which would the server access in a directory that a user accessed.
|
||||||
|
# For example, by default, http://localhost/a-directory resolves to http://localhost/a-directory/index.html.
|
||||||
|
implicit_page: index.html
|
||||||
|
# static_file_headers: Headers for static files
|
||||||
|
# static_file_headers:
|
||||||
|
# - name: field-name
|
||||||
|
# value: field-value
|
||||||
|
# upload_path: The path to save the uploaded file. "uploads" by default.
|
||||||
|
# If the path isn't prefixed with /, ./ or ../,
|
||||||
|
# it is relative path of document_root path
|
||||||
|
upload_path: uploads
|
||||||
|
# file_types:
|
||||||
|
# HTTP download file types,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", etc.
|
||||||
|
file_types:
|
||||||
|
- gif
|
||||||
|
- png
|
||||||
|
- jpg
|
||||||
|
- js
|
||||||
|
- css
|
||||||
|
- html
|
||||||
|
- ico
|
||||||
|
- swf
|
||||||
|
- xap
|
||||||
|
- apk
|
||||||
|
- cur
|
||||||
|
- xml
|
||||||
|
# mime: A dictionary that extends the internal MIME type support. Maps extensions into new MIME types
|
||||||
|
# note: This option only adds MIME to the sever. `file_types` above have to be set for the server to serve them.
|
||||||
|
mime: {
|
||||||
|
# text/markdown: md
|
||||||
|
# text/gemini:
|
||||||
|
# - gmi
|
||||||
|
# - gemini
|
||||||
|
}
|
||||||
|
# locations: An array of locations of static files for GET requests.
|
||||||
|
locations:
|
||||||
|
# uri_prefix: The URI prefix of the location prefixed with "/", the default value is "" that disables the location.
|
||||||
|
- uri_prefix: '' # /.well-known/acme-challenge/
|
||||||
|
# default_content_type: The default content type of the static files without
|
||||||
|
# an extension. empty string by default.
|
||||||
|
default_content_type: text/plain
|
||||||
|
# alias: The location in file system, if it is prefixed with "/", it
|
||||||
|
# presents an absolute path, otherwise it presents a relative path to
|
||||||
|
# the document_root path.
|
||||||
|
# The default value is "" which means use the document root path as the location base path.
|
||||||
|
alias: ''
|
||||||
|
# is_case_sensitive: indicates whether the URI prefix is case sensitive.
|
||||||
|
is_case_sensitive: false
|
||||||
|
# allow_all: true by default. If it is set to false, only static files with a valid extension can be accessed.
|
||||||
|
allow_all: true
|
||||||
|
# is_recursive: true by default. If it is set to false, files in sub directories can't be accessed.
|
||||||
|
is_recursive: true
|
||||||
|
# filters: string array, the filters applied to the location.
|
||||||
|
filters: []
|
||||||
|
# max_connections: maximum number of connections, 100000 by default
|
||||||
|
max_connections: 100000
|
||||||
|
# max_connections_per_ip: maximum number of connections per client, 0 by default which means no limit
|
||||||
|
max_connections_per_ip: 0
|
||||||
|
# Load_dynamic_views: False by default, when set to true, drogon
|
||||||
|
# compiles and loads dynamically "CSP View Files" in directories defined
|
||||||
|
# by "dynamic_views_path"
|
||||||
|
load_dynamic_views: false
|
||||||
|
# dynamic_views_path: If the path isn't prefixed with /, ./ or ../,
|
||||||
|
# it is relative path of document_root path
|
||||||
|
dynamic_views_path:
|
||||||
|
- ./views
|
||||||
|
# dynamic_views_output_path: Default by an empty string which means the output path of source
|
||||||
|
# files is the path where the csp files locate. If the path isn't prefixed with /, it is relative
|
||||||
|
# path of the current working directory.
|
||||||
|
dynamic_views_output_path: ''
|
||||||
|
# json_parser_stack_limit: 1000 by default, the maximum number of stack depth when reading a json string by the jsoncpp library.
|
||||||
|
json_parser_stack_limit: 1000
|
||||||
|
# enable_unicode_escaping_in_json: true by default, enable unicode escaping in json.
|
||||||
|
enable_unicode_escaping_in_json: true
|
||||||
|
# float_precision_in_json: set precision of float number in json.
|
||||||
|
float_precision_in_json:
|
||||||
|
# precision: 0 by default, 0 means use the default precision of the jsoncpp lib.
|
||||||
|
precision: 0
|
||||||
|
# precision_type: must be "significant" or "decimal", defaults to "significant" that means
|
||||||
|
# setting max number of significant digits in string, "decimal" means setting max number of
|
||||||
|
# digits after "." in string
|
||||||
|
precision_type: significant
|
||||||
|
# log: Set log output, drogon output logs to stdout by default
|
||||||
|
log:
|
||||||
|
# use_spdlog: Use spdlog library to log
|
||||||
|
use_spdlog: false
|
||||||
|
# log_path: Log file path,empty by default,in which case,logs are output to the stdout
|
||||||
|
# log_path: ./
|
||||||
|
# logfile_base_name: Log file base name,empty by default which means drogon names logfile as
|
||||||
|
# drogon.log ...
|
||||||
|
logfile_base_name: ''
|
||||||
|
# log_size_limit: 100000000 bytes by default,
|
||||||
|
# When the log file size reaches "log_size_limit", the log file is switched.
|
||||||
|
log_size_limit: 100000000
|
||||||
|
# max_files: 0 by default,
|
||||||
|
# When the number of old log files exceeds "max_files", the oldest file will be deleted. 0 means never delete.
|
||||||
|
max_files: 0
|
||||||
|
# log_level: "DEBUG" by default,options:"TRACE","DEBUG","INFO","WARN"
|
||||||
|
# The TRACE level is only valid when built in DEBUG mode.
|
||||||
|
log_level: DEBUG
|
||||||
|
# display_local_time: false by default, if true, the log time is displayed in local time
|
||||||
|
display_local_time: false
|
||||||
|
# run_as_daemon: False by default
|
||||||
|
run_as_daemon: false
|
||||||
|
# handle_sig_term: True by default
|
||||||
|
handle_sig_term: true
|
||||||
|
# relaunch_on_error: False by default, if true, the program will be restart by the parent after exiting;
|
||||||
|
relaunch_on_error: false
|
||||||
|
# use_sendfile: True by default, if true, the program
|
||||||
|
# uses sendfile() system-call to send static files to clients;
|
||||||
|
use_sendfile: true
|
||||||
|
# use_gzip: True by default, use gzip to compress the response body's content;
|
||||||
|
use_gzip: true
|
||||||
|
# use_brotli: False by default, use brotli to compress the response body's content;
|
||||||
|
use_brotli: false
|
||||||
|
# static_files_cache_time: 5 (seconds) by default, the time in which the static file response is cached,
|
||||||
|
# 0 means cache forever, the negative value means no cache
|
||||||
|
static_files_cache_time: 5
|
||||||
|
# simple_controllers_map: Used to configure mapping from path to simple controller
|
||||||
|
# simple_controllers_map:
|
||||||
|
# - path: /path/name
|
||||||
|
# controller: controllerClassName
|
||||||
|
# http_methods:
|
||||||
|
# - get
|
||||||
|
# - post
|
||||||
|
# filters:
|
||||||
|
# - FilterClassName
|
||||||
|
# idle_connection_timeout: Defaults to 60 seconds, the lifetime
|
||||||
|
# of the connection without read or write
|
||||||
|
idle_connection_timeout: 60
|
||||||
|
# server_header_field: Set the 'Server' header field in each response sent by drogon,
|
||||||
|
# empty string by default with which the 'Server' header field is set to "Server: drogon/version string\r\n"
|
||||||
|
server_header_field: ''
|
||||||
|
# enable_server_header: Set true to force drogon to add a 'Server' header to each HTTP response. The default
|
||||||
|
# value is true.
|
||||||
|
enable_server_header: true
|
||||||
|
# enable_date_header: Set true to force drogon to add a 'Date' header to each HTTP response. The default
|
||||||
|
# value is true.
|
||||||
|
enable_date_header: true
|
||||||
|
# keepalive_requests: Set the maximum number of requests that can be served through one keep-alive connection.
|
||||||
|
# After the maximum number of requests are made, the connection is closed.
|
||||||
|
# The default value of 0 means no limit.
|
||||||
|
keepalive_requests: 0
|
||||||
|
# pipelining_requests: Set the maximum number of unhandled requests that can be cached in pipelining buffer.
|
||||||
|
# After the maximum number of requests are made, the connection is closed.
|
||||||
|
# The default value of 0 means no limit.
|
||||||
|
pipelining_requests: 0
|
||||||
|
# gzip_static: If it is set to true, when the client requests a static file, drogon first finds the compressed
|
||||||
|
# file with the extension ".gz" in the same path and send the compressed file to the client.
|
||||||
|
# The default value of gzip_static is true.
|
||||||
|
gzip_static: true
|
||||||
|
# br_static: If it is set to true, when the client requests a static file, drogon first finds the compressed
|
||||||
|
# file with the extension ".br" in the same path and send the compressed file to the client.
|
||||||
|
# The default value of br_static is true.
|
||||||
|
br_static: true
|
||||||
|
# client_max_body_size: Set the maximum body size of HTTP requests received by drogon. The default value is "1M".
|
||||||
|
# One can set it to "1024", "1k", "10M", "1G", etc. Setting it to "" means no limit.
|
||||||
|
client_max_body_size: 1M
|
||||||
|
# max_memory_body_size: Set the maximum body size in memory of HTTP requests received by drogon. The default value is "64K" bytes.
|
||||||
|
# If the body size of a HTTP request exceeds this limit, the body is stored to a temporary file for processing.
|
||||||
|
# Setting it to "" means no limit.
|
||||||
|
client_max_memory_body_size: 64K
|
||||||
|
# client_max_websocket_message_size: Set the maximum size of messages sent by WebSocket client. The default value is "128K".
|
||||||
|
# One can set it to "1024", "1k", "10M", "1G", etc. Setting it to "" means no limit.
|
||||||
|
client_max_websocket_message_size: 128K
|
||||||
|
# reuse_port: Defaults to false, users can run multiple processes listening on the same port at the same time.
|
||||||
|
reuse_port: false
|
||||||
|
# enabled_compressed_request: Defaults to false. If true the server will automatically decompress compressed request bodies.
|
||||||
|
# Currently only gzip and br are supported. Note: max_memory_body_size and max_body_size applies twice for compressed requests.
|
||||||
|
# Once when receiving and once when decompressing. i.e. if the decompressed body is larger than max_body_size, the request
|
||||||
|
# will be rejected.
|
||||||
|
enabled_compressed_request: false
|
||||||
|
# enable_request_stream: Defaults to false. If true the server will enable stream mode for http requests.
|
||||||
|
# See the wiki for more details.
|
||||||
|
enable_request_stream: false
|
||||||
|
# plugins: Define all plugins running in the application
|
||||||
|
plugins:
|
||||||
|
# name: The class name of the plugin
|
||||||
|
- name: drogon::plugin::PromExporter
|
||||||
|
# dependencies: Plugins that the plugin depends on. It can be commented out
|
||||||
|
dependencies: []
|
||||||
|
# config: The configuration of the plugin. This json object is the parameter to initialize the plugin.
|
||||||
|
# It can be commented out
|
||||||
|
config:
|
||||||
|
path: /metrics
|
||||||
|
- name: drogon::plugin::AccessLogger
|
||||||
|
dependencies: []
|
||||||
|
config:
|
||||||
|
use_spdlog: false
|
||||||
|
log_path: ''
|
||||||
|
log_format: ''
|
||||||
|
log_file: access.log
|
||||||
|
log_size_limit: 0
|
||||||
|
use_local_time: true
|
||||||
|
log_index: 0
|
||||||
|
# show_microseconds: true
|
||||||
|
# custom_time_format: ''
|
||||||
|
# use_real_ip: false
|
||||||
|
# custom_config: custom configuration for users. This object can be get by the app().getCustomConfig() method.
|
||||||
|
custom_config:
|
||||||
|
realm: drogonRealm
|
||||||
|
opaque: drogonOpaque
|
||||||
|
credentials:
|
||||||
|
- user: drogon
|
||||||
|
password: dr0g0n
|
42
docker/alpine/Dockerfile
Normal file
42
docker/alpine/Dockerfile
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
FROM alpine:3.14
|
||||||
|
|
||||||
|
ARG USER=drogon
|
||||||
|
ARG UID=1000
|
||||||
|
ARG GID=1000
|
||||||
|
ARG USER_HOME=/drogon
|
||||||
|
|
||||||
|
ENV TZ=UTC
|
||||||
|
|
||||||
|
RUN apk update && apk --no-cache --upgrade add tzdata \
|
||||||
|
&& ln -snf /usr/share/zoneinfo/$TZ /etc/localtime \
|
||||||
|
&& echo $TZ > /etc/timezone
|
||||||
|
|
||||||
|
RUN apk --no-cache --upgrade add \
|
||||||
|
sudo curl wget cmake make pkgconfig git gcc g++ \
|
||||||
|
openssl libressl-dev jsoncpp-dev util-linux-dev zlib-dev c-ares-dev \
|
||||||
|
postgresql-dev mariadb-dev sqlite-dev hiredis-dev
|
||||||
|
|
||||||
|
RUN addgroup -S -g $GID $USER \
|
||||||
|
&& adduser -D -u $UID -G $USER -h $USER_HOME $USER \
|
||||||
|
&& mkdir -p /etc/sudoers.d \
|
||||||
|
&& echo "$USER ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/$USER \
|
||||||
|
&& chmod 0440 /etc/sudoers.d/$USER
|
||||||
|
|
||||||
|
USER $USER
|
||||||
|
WORKDIR $USER_HOME
|
||||||
|
|
||||||
|
ENV LANG=en_US.UTF-8 \
|
||||||
|
LANGUAGE=en_US:en \
|
||||||
|
LC_ALL=en_US.UTF-8 \
|
||||||
|
CC=gcc \
|
||||||
|
CXX=g++ \
|
||||||
|
AR=gcc-ar \
|
||||||
|
RANLIB=gcc-ranlib \
|
||||||
|
DROGON_INSTALLED_ROOT=$USER_HOME/install
|
||||||
|
|
||||||
|
RUN wget -O $USER_HOME/version.json https://api.github.com/repos/an-tao/drogon/git/refs/heads/master \
|
||||||
|
&& git clone https://github.com/an-tao/drogon $DROGON_INSTALLED_ROOT
|
||||||
|
|
||||||
|
RUN cd $DROGON_INSTALLED_ROOT \
|
||||||
|
&& sed -i 's/bash/sh/' ./build.sh \
|
||||||
|
&& ./build.sh
|
32
docker/alpine/README.md
Normal file
32
docker/alpine/README.md
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
## Build Docker Image
|
||||||
|
|
||||||
|
```shell
|
||||||
|
$ cd drogon/docker/alpine # from this repository
|
||||||
|
$ docker build --no-cache --build-arg UID=`id -u` --build-arg GID=`id -g` -t drogon-alpine . # include last dot(.)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Create a Drogon Project
|
||||||
|
|
||||||
|
```shell
|
||||||
|
$ cd ~/drogon_app # example
|
||||||
|
$ docker run --rm -v="$PWD:/drogon/app" -w="/drogon/app" drogon-alpine drogon_ctl create project hello_world
|
||||||
|
```
|
||||||
|
|
||||||
|
## Build the Project
|
||||||
|
|
||||||
|
```shell
|
||||||
|
$ cd hello_world
|
||||||
|
$ docker run --rm --volume="$PWD:/drogon/app" -w="/drogon/app/build" drogon-alpine sh -c "cmake .. && make"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Start Server
|
||||||
|
|
||||||
|
```shell
|
||||||
|
$ docker run --name drogon_test --rm -u 0 -v="$PWD/build:/drogon/app" -w="/drogon/app" -p 8080:80 -d drogon-alpine ./hello_world # expose port 80 to 8080
|
||||||
|
```
|
||||||
|
|
||||||
|
## Stop Server
|
||||||
|
|
||||||
|
```shell
|
||||||
|
$ docker kill drogon_test
|
||||||
|
```
|
@ -1,29 +1,29 @@
|
|||||||
FROM ubuntu:20.04
|
FROM ubuntu:22.04
|
||||||
|
|
||||||
ENV TZ=UTC
|
ENV TZ=UTC
|
||||||
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
||||||
|
|
||||||
RUN apt-get update -yqq \
|
RUN apt-get update -yqq \
|
||||||
&& apt-get install -yqq --no-install-recommends software-properties-common \
|
&& apt-get install -yqq --no-install-recommends software-properties-common \
|
||||||
sudo curl wget cmake make pkg-config locales git gcc-10 g++-10 \
|
sudo curl wget cmake make pkg-config locales git gcc-11 g++-11 \
|
||||||
openssl libssl-dev libjsoncpp-dev uuid-dev zlib1g-dev libc-ares-dev\
|
openssl libssl-dev libjsoncpp-dev uuid-dev zlib1g-dev libc-ares-dev\
|
||||||
postgresql-server-dev-all libmariadbclient-dev libsqlite3-dev libhiredis-dev\
|
postgresql-server-dev-all libmariadb-dev libsqlite3-dev libhiredis-dev\
|
||||||
&& rm -rf /var/lib/apt/lists/* \
|
&& rm -rf /var/lib/apt/lists/* \
|
||||||
&& locale-gen en_US.UTF-8
|
&& locale-gen en_US.UTF-8
|
||||||
|
|
||||||
ENV LANG=en_US.UTF-8 \
|
ENV LANG=en_US.UTF-8 \
|
||||||
LANGUAGE=en_US:en \
|
LANGUAGE=en_US:en \
|
||||||
LC_ALL=en_US.UTF-8 \
|
LC_ALL=en_US.UTF-8 \
|
||||||
CC=gcc-10 \
|
CC=gcc-11 \
|
||||||
CXX=g++-10 \
|
CXX=g++-11 \
|
||||||
AR=gcc-ar-10 \
|
AR=gcc-ar-11 \
|
||||||
RANLIB=gcc-ranlib-10 \
|
RANLIB=gcc-ranlib-11 \
|
||||||
IROOT=/install
|
IROOT=/install
|
||||||
|
|
||||||
ENV DROGON_ROOT="$IROOT/drogon"
|
ENV DROGON_ROOT="$IROOT/drogon"
|
||||||
|
|
||||||
ADD https://api.github.com/repos/an-tao/drogon/git/refs/heads/master $IROOT/version.json
|
ADD https://api.github.com/repos/drogonframework/drogon/git/refs/heads/master $IROOT/version.json
|
||||||
RUN git clone https://github.com/an-tao/drogon $DROGON_ROOT
|
RUN git clone https://github.com/drogonframework/drogon $DROGON_ROOT
|
||||||
|
|
||||||
WORKDIR $DROGON_ROOT
|
WORKDIR $DROGON_ROOT
|
||||||
|
|
||||||
|
@ -17,9 +17,13 @@ add_executable(_drogon_ctl
|
|||||||
create.cc
|
create.cc
|
||||||
create_view.cc)
|
create_view.cc)
|
||||||
target_link_libraries(_drogon_ctl ${PROJECT_NAME})
|
target_link_libraries(_drogon_ctl ${PROJECT_NAME})
|
||||||
if (WIN32 AND BUILD_DROGON_SHARED)
|
if (WIN32 AND BUILD_SHARED_LIBS)
|
||||||
set(DROGON_FILE $<TARGET_FILE:drogon>)
|
set(DROGON_FILE $<TARGET_FILE:drogon>)
|
||||||
set(TRANTOR_FILE $<TARGET_FILE:trantor>)
|
if (USE_SUBMODULE)
|
||||||
|
set(TRANTOR_FILE $<TARGET_FILE:trantor>)
|
||||||
|
else()
|
||||||
|
set(TRANTOR_FILE $<TARGET_FILE:Trantor::Trantor>)
|
||||||
|
endif()
|
||||||
add_custom_command(TARGET _drogon_ctl POST_BUILD
|
add_custom_command(TARGET _drogon_ctl POST_BUILD
|
||||||
COMMAND ${CMAKE_COMMAND}
|
COMMAND ${CMAKE_COMMAND}
|
||||||
-DCTL_FILE=${DROGON_FILE}
|
-DCTL_FILE=${DROGON_FILE}
|
||||||
@ -53,7 +57,7 @@ target_link_libraries(drogon_ctl PRIVATE ${PROJECT_NAME})
|
|||||||
target_include_directories(drogon_ctl PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
target_include_directories(drogon_ctl PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
add_dependencies(drogon_ctl _drogon_ctl)
|
add_dependencies(drogon_ctl _drogon_ctl)
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
target_link_libraries(drogon_ctl PRIVATE ws2_32 Rpcrt4)
|
target_link_libraries(drogon_ctl PRIVATE ws2_32 rpcrt4 iphlpapi)
|
||||||
endif(WIN32)
|
endif(WIN32)
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
target_link_libraries(drogon_ctl PRIVATE resolv)
|
target_link_libraries(drogon_ctl PRIVATE resolv)
|
||||||
|
@ -22,18 +22,22 @@ class CommandHandler : public virtual drogon::DrObjectBase
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void handleCommand(std::vector<std::string> ¶meters) = 0;
|
virtual void handleCommand(std::vector<std::string> ¶meters) = 0;
|
||||||
|
|
||||||
virtual bool isTopCommand()
|
virtual bool isTopCommand()
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::string script()
|
virtual std::string script()
|
||||||
{
|
{
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual std::string detail()
|
virtual std::string detail()
|
||||||
{
|
{
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~CommandHandler()
|
virtual ~CommandHandler()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -18,14 +18,15 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
using namespace drogon_ctl;
|
using namespace drogon_ctl;
|
||||||
|
|
||||||
std::string create::detail()
|
std::string create::detail()
|
||||||
{
|
{
|
||||||
return "Use create command to create some source files of drogon webapp\n\n"
|
return "Use create command to create some source files of drogon webapp\n\n"
|
||||||
"Usage:drogon_ctl create <view|controller|filter|project|model> "
|
"Usage:drogon_ctl create <view|controller|filter|project|model> "
|
||||||
"[-options] <object name>\n\n"
|
"[-options] <object name>\n\n"
|
||||||
"drogon_ctl create view <csp file name> [-o <output path>] [-n "
|
"drogon_ctl create view <csp file name> [-o <output path>] [-n "
|
||||||
"<namespace>]|[--path-to-namespace]//create HttpView source files "
|
"<namespace>] [--path-to-namespace] //create HttpView source files "
|
||||||
"from csp files\n\n"
|
"from csp files, namespace is prefixed of path-to-namespace\n\n"
|
||||||
"drogon_ctl create controller [-s] <[namespace::]class_name> //"
|
"drogon_ctl create controller [-s] <[namespace::]class_name> //"
|
||||||
"create HttpSimpleController source files\n\n"
|
"create HttpSimpleController source files\n\n"
|
||||||
"drogon_ctl create controller -h <[namespace::]class_name> //"
|
"drogon_ctl create controller -h <[namespace::]class_name> //"
|
||||||
@ -41,7 +42,8 @@ std::string create::detail()
|
|||||||
"create a plugin named class_name\n\n"
|
"create a plugin named class_name\n\n"
|
||||||
"drogon_ctl create project <project_name> //"
|
"drogon_ctl create project <project_name> //"
|
||||||
"create a project named project_name\n\n"
|
"create a project named project_name\n\n"
|
||||||
"drogon_ctl create model <model_path> [--table=<table_name>] [-f]//"
|
"drogon_ctl create model <model_path> [-o <output path>] "
|
||||||
|
"[--table=<table_name>] [-f]//"
|
||||||
"create model classes in model_path\n";
|
"create model classes in model_path\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,21 +17,25 @@
|
|||||||
#include <drogon/DrObject.h>
|
#include <drogon/DrObject.h>
|
||||||
#include "CommandHandler.h"
|
#include "CommandHandler.h"
|
||||||
using namespace drogon;
|
using namespace drogon;
|
||||||
|
|
||||||
namespace drogon_ctl
|
namespace drogon_ctl
|
||||||
{
|
{
|
||||||
class create : public DrObject<create>, public CommandHandler
|
class create : public DrObject<create>, public CommandHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void handleCommand(std::vector<std::string> ¶meters) override;
|
void handleCommand(std::vector<std::string> ¶meters) override;
|
||||||
virtual std::string script() override
|
|
||||||
|
std::string script() override
|
||||||
{
|
{
|
||||||
return "create some source files(Use 'drogon_ctl help create' for more "
|
return "create some source files(Use 'drogon_ctl help create' for more "
|
||||||
"information)";
|
"information)";
|
||||||
}
|
}
|
||||||
virtual bool isTopCommand() override
|
|
||||||
|
bool isTopCommand() override
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
virtual std::string detail() override;
|
|
||||||
|
std::string detail() override;
|
||||||
};
|
};
|
||||||
} // namespace drogon_ctl
|
} // namespace drogon_ctl
|
||||||
|
@ -95,8 +95,11 @@ void create_controller::newSimpleControllerHeaderFile(
|
|||||||
const std::string &className)
|
const std::string &className)
|
||||||
{
|
{
|
||||||
file << "#pragma once\n";
|
file << "#pragma once\n";
|
||||||
|
file << "\n";
|
||||||
file << "#include <drogon/HttpSimpleController.h>\n";
|
file << "#include <drogon/HttpSimpleController.h>\n";
|
||||||
|
file << "\n";
|
||||||
file << "using namespace drogon;\n";
|
file << "using namespace drogon;\n";
|
||||||
|
file << "\n";
|
||||||
std::string class_name = className;
|
std::string class_name = className;
|
||||||
std::string namepace_path = "/";
|
std::string namepace_path = "/";
|
||||||
auto pos = class_name.find("::");
|
auto pos = class_name.find("::");
|
||||||
@ -111,19 +114,19 @@ void create_controller::newSimpleControllerHeaderFile(
|
|||||||
file << "{\n";
|
file << "{\n";
|
||||||
pos = class_name.find("::");
|
pos = class_name.find("::");
|
||||||
}
|
}
|
||||||
file << "class " << class_name << ":public drogon::HttpSimpleController<"
|
file << "class " << class_name << " : public drogon::HttpSimpleController<"
|
||||||
<< class_name << ">\n";
|
<< class_name << ">\n";
|
||||||
file << "{\n";
|
file << "{\n";
|
||||||
file << " public:\n";
|
file << " public:\n";
|
||||||
file << " virtual void asyncHandleHttpRequest(const HttpRequestPtr& "
|
file << " void asyncHandleHttpRequest(const HttpRequestPtr& "
|
||||||
"req, std::function<void (const HttpResponsePtr &)> &&callback) "
|
"req, std::function<void (const HttpResponsePtr &)> &&callback) "
|
||||||
"override;\n";
|
"override;\n";
|
||||||
|
|
||||||
file << " PATH_LIST_BEGIN\n";
|
file << " PATH_LIST_BEGIN\n";
|
||||||
file << " //list path definitions here;\n";
|
file << " // list path definitions here;\n";
|
||||||
file << " "
|
file << " "
|
||||||
"//PATH_ADD(\"/"
|
"// PATH_ADD(\"/"
|
||||||
"path\",\"filter1\",\"filter2\",HttpMethod1,HttpMethod2...);\n";
|
"path\", \"filter1\", \"filter2\", HttpMethod1, HttpMethod2...);\n";
|
||||||
file << " PATH_LIST_END\n";
|
file << " PATH_LIST_END\n";
|
||||||
file << "};\n";
|
file << "};\n";
|
||||||
while (namespaceCount > 0)
|
while (namespaceCount > 0)
|
||||||
@ -132,26 +135,29 @@ void create_controller::newSimpleControllerHeaderFile(
|
|||||||
file << "}\n";
|
file << "}\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void create_controller::newSimpleControllerSourceFile(
|
void create_controller::newSimpleControllerSourceFile(
|
||||||
std::ofstream &file,
|
std::ofstream &file,
|
||||||
const std::string &className,
|
const std::string &className,
|
||||||
const std::string &filename)
|
const std::string &filename)
|
||||||
{
|
{
|
||||||
file << "#include \"" << filename << ".h\"\n";
|
file << "#include \"" << filename << ".h\"\n";
|
||||||
|
file << "\n";
|
||||||
auto pos = className.rfind("::");
|
auto pos = className.rfind("::");
|
||||||
auto class_name = className;
|
auto class_name = className;
|
||||||
if (pos != std::string::npos)
|
if (pos != std::string::npos)
|
||||||
{
|
{
|
||||||
auto namespacename = className.substr(0, pos);
|
auto namespacename = className.substr(0, pos);
|
||||||
file << "using namespace " << namespacename << ";\n";
|
file << "using namespace " << namespacename << ";\n";
|
||||||
|
file << "\n";
|
||||||
class_name = className.substr(pos + 2);
|
class_name = className.substr(pos + 2);
|
||||||
}
|
}
|
||||||
file << "void " << class_name
|
file << "void " << class_name
|
||||||
<< "::asyncHandleHttpRequest(const HttpRequestPtr& req, "
|
<< "::asyncHandleHttpRequest(const HttpRequestPtr& req, "
|
||||||
"std::function<void (const HttpResponsePtr &)> &&callback)\n";
|
"std::function<void (const HttpResponsePtr &)> &&callback)\n";
|
||||||
file << "{\n";
|
file << "{\n";
|
||||||
file << " //write your application logic here\n";
|
file << " // write your application logic here\n";
|
||||||
file << "}";
|
file << "}\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void create_controller::newWebsockControllerHeaderFile(
|
void create_controller::newWebsockControllerHeaderFile(
|
||||||
@ -159,8 +165,11 @@ void create_controller::newWebsockControllerHeaderFile(
|
|||||||
const std::string &className)
|
const std::string &className)
|
||||||
{
|
{
|
||||||
file << "#pragma once\n";
|
file << "#pragma once\n";
|
||||||
|
file << "\n";
|
||||||
file << "#include <drogon/WebSocketController.h>\n";
|
file << "#include <drogon/WebSocketController.h>\n";
|
||||||
|
file << "\n";
|
||||||
file << "using namespace drogon;\n";
|
file << "using namespace drogon;\n";
|
||||||
|
file << "\n";
|
||||||
std::string class_name = className;
|
std::string class_name = className;
|
||||||
std::string namepace_path = "/";
|
std::string namepace_path = "/";
|
||||||
auto pos = class_name.find("::");
|
auto pos = class_name.find("::");
|
||||||
@ -175,23 +184,22 @@ void create_controller::newWebsockControllerHeaderFile(
|
|||||||
file << "{\n";
|
file << "{\n";
|
||||||
pos = class_name.find("::");
|
pos = class_name.find("::");
|
||||||
}
|
}
|
||||||
file << "class " << class_name << ":public drogon::WebSocketController<"
|
file << "class " << class_name << " : public drogon::WebSocketController<"
|
||||||
<< class_name << ">\n";
|
<< class_name << ">\n";
|
||||||
file << "{\n";
|
file << "{\n";
|
||||||
file << " public:\n";
|
file << " public:\n";
|
||||||
file
|
file << " void handleNewMessage(const WebSocketConnectionPtr&,\n";
|
||||||
<< " virtual void handleNewMessage(const WebSocketConnectionPtr&,\n";
|
|
||||||
file << " std::string &&,\n";
|
file << " std::string &&,\n";
|
||||||
file << " const WebSocketMessageType &) "
|
file << " const WebSocketMessageType &) "
|
||||||
"override;\n";
|
"override;\n";
|
||||||
file << " virtual void handleNewConnection(const HttpRequestPtr &,\n";
|
file << " void handleNewConnection(const HttpRequestPtr &,\n";
|
||||||
file << " const "
|
file << " const "
|
||||||
"WebSocketConnectionPtr&)override;\n";
|
"WebSocketConnectionPtr&) override;\n";
|
||||||
file << " virtual void handleConnectionClosed(const "
|
file << " void handleConnectionClosed(const "
|
||||||
"WebSocketConnectionPtr&)override;\n";
|
"WebSocketConnectionPtr&) override;\n";
|
||||||
file << " WS_PATH_LIST_BEGIN\n";
|
file << " WS_PATH_LIST_BEGIN\n";
|
||||||
file << " //list path definitions here;\n";
|
file << " // list path definitions here;\n";
|
||||||
file << " //WS_PATH_ADD(\"/path\",\"filter1\",\"filter2\",...);\n";
|
file << " // WS_PATH_ADD(\"/path\", \"filter1\", \"filter2\", ...);\n";
|
||||||
file << " WS_PATH_LIST_END\n";
|
file << " WS_PATH_LIST_END\n";
|
||||||
file << "};\n";
|
file << "};\n";
|
||||||
while (namespaceCount > 0)
|
while (namespaceCount > 0)
|
||||||
@ -200,37 +208,42 @@ void create_controller::newWebsockControllerHeaderFile(
|
|||||||
file << "}\n";
|
file << "}\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void create_controller::newWebsockControllerSourceFile(
|
void create_controller::newWebsockControllerSourceFile(
|
||||||
std::ofstream &file,
|
std::ofstream &file,
|
||||||
const std::string &className,
|
const std::string &className,
|
||||||
const std::string &filename)
|
const std::string &filename)
|
||||||
{
|
{
|
||||||
file << "#include \"" << filename << ".h\"\n";
|
file << "#include \"" << filename << ".h\"\n";
|
||||||
|
file << "\n";
|
||||||
auto pos = className.rfind("::");
|
auto pos = className.rfind("::");
|
||||||
auto class_name = className;
|
auto class_name = className;
|
||||||
if (pos != std::string::npos)
|
if (pos != std::string::npos)
|
||||||
{
|
{
|
||||||
auto namespacename = className.substr(0, pos);
|
auto namespacename = className.substr(0, pos);
|
||||||
file << "using namespace " << namespacename << ";\n";
|
file << "using namespace " << namespacename << ";\n";
|
||||||
|
file << "\n";
|
||||||
class_name = className.substr(pos + 2);
|
class_name = className.substr(pos + 2);
|
||||||
}
|
}
|
||||||
file << "void " << class_name
|
file << "void " << class_name
|
||||||
<< "::handleNewMessage(const WebSocketConnectionPtr& wsConnPtr, "
|
<< "::handleNewMessage(const WebSocketConnectionPtr& wsConnPtr, "
|
||||||
"std::string &&message, const WebSocketMessageType &type)\n";
|
"std::string &&message, const WebSocketMessageType &type)\n";
|
||||||
file << "{\n";
|
file << "{\n";
|
||||||
file << " //write your application logic here\n";
|
file << " // write your application logic here\n";
|
||||||
file << "}\n";
|
file << "}\n";
|
||||||
|
file << "\n";
|
||||||
file << "void " << class_name
|
file << "void " << class_name
|
||||||
<< "::handleNewConnection(const HttpRequestPtr &req,const "
|
<< "::handleNewConnection(const HttpRequestPtr &req, const "
|
||||||
"WebSocketConnectionPtr& wsConnPtr)\n";
|
"WebSocketConnectionPtr& wsConnPtr)\n";
|
||||||
file << "{\n";
|
file << "{\n";
|
||||||
file << " //write your application logic here\n";
|
file << " // write your application logic here\n";
|
||||||
file << "}\n";
|
file << "}\n";
|
||||||
|
file << "\n";
|
||||||
file << "void " << class_name
|
file << "void " << class_name
|
||||||
<< "::handleConnectionClosed(const WebSocketConnectionPtr& "
|
<< "::handleConnectionClosed(const WebSocketConnectionPtr& "
|
||||||
"wsConnPtr)\n";
|
"wsConnPtr)\n";
|
||||||
file << "{\n";
|
file << "{\n";
|
||||||
file << " //write your application logic here\n";
|
file << " // write your application logic here\n";
|
||||||
file << "}\n";
|
file << "}\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,8 +252,11 @@ void create_controller::newHttpControllerHeaderFile(
|
|||||||
const std::string &className)
|
const std::string &className)
|
||||||
{
|
{
|
||||||
file << "#pragma once\n";
|
file << "#pragma once\n";
|
||||||
|
file << "\n";
|
||||||
file << "#include <drogon/HttpController.h>\n";
|
file << "#include <drogon/HttpController.h>\n";
|
||||||
|
file << "\n";
|
||||||
file << "using namespace drogon;\n";
|
file << "using namespace drogon;\n";
|
||||||
|
file << "\n";
|
||||||
std::string class_name = className;
|
std::string class_name = className;
|
||||||
std::string namepace_path = "/";
|
std::string namepace_path = "/";
|
||||||
auto pos = class_name.find("::");
|
auto pos = class_name.find("::");
|
||||||
@ -255,33 +271,33 @@ void create_controller::newHttpControllerHeaderFile(
|
|||||||
file << "{\n";
|
file << "{\n";
|
||||||
pos = class_name.find("::");
|
pos = class_name.find("::");
|
||||||
}
|
}
|
||||||
file << "class " << class_name << ":public drogon::HttpController<"
|
file << "class " << class_name << " : public drogon::HttpController<"
|
||||||
<< class_name << ">\n";
|
<< class_name << ">\n";
|
||||||
file << "{\n";
|
file << "{\n";
|
||||||
file << " public:\n";
|
file << " public:\n";
|
||||||
file << " METHOD_LIST_BEGIN\n";
|
file << " METHOD_LIST_BEGIN\n";
|
||||||
file << " //use METHOD_ADD to add your custom processing function "
|
file << " // use METHOD_ADD to add your custom processing function "
|
||||||
"here;\n";
|
"here;\n";
|
||||||
file << " //METHOD_ADD(" << class_name
|
file << " // METHOD_ADD(" << class_name
|
||||||
<< "::get,\"/{2}/{1}\",Get);"
|
<< "::get, \"/{2}/{1}\", Get);"
|
||||||
"//path is "
|
" // path is "
|
||||||
<< namepace_path << class_name << "/{arg2}/{arg1}\n";
|
<< namepace_path << class_name << "/{arg2}/{arg1}\n";
|
||||||
file << " //METHOD_ADD(" << class_name
|
file << " // METHOD_ADD(" << class_name
|
||||||
<< "::your_method_name,\"/{1}/{2}/list\",Get);"
|
<< "::your_method_name, \"/{1}/{2}/list\", Get);"
|
||||||
"//path is "
|
" // path is "
|
||||||
<< namepace_path << class_name << "/{arg1}/{arg2}/list\n";
|
<< namepace_path << class_name << "/{arg1}/{arg2}/list\n";
|
||||||
file << " //ADD_METHOD_TO(" << class_name
|
file << " // ADD_METHOD_TO(" << class_name
|
||||||
<< "::your_method_name,\"/absolute/path/{1}/{2}/list\",Get);"
|
<< "::your_method_name, \"/absolute/path/{1}/{2}/list\", Get);"
|
||||||
"//path is /absolute/path/{arg1}/{arg2}/list\n";
|
" // path is /absolute/path/{arg1}/{arg2}/list\n";
|
||||||
file << "\n";
|
file << "\n";
|
||||||
file << " METHOD_LIST_END\n";
|
file << " METHOD_LIST_END\n";
|
||||||
file << " // your declaration of processing function maybe like this:\n";
|
file << " // your declaration of processing function maybe like this:\n";
|
||||||
file << " // void get(const HttpRequestPtr& req,"
|
file << " // void get(const HttpRequestPtr& req, "
|
||||||
"std::function<void (const HttpResponsePtr &)> &&callback,int "
|
"std::function<void (const HttpResponsePtr &)> &&callback, int "
|
||||||
"p1,std::string p2);\n";
|
"p1, std::string p2);\n";
|
||||||
file << " // void your_method_name(const HttpRequestPtr& req,"
|
file << " // void your_method_name(const HttpRequestPtr& req, "
|
||||||
"std::function<void (const HttpResponsePtr &)> &&callback,double "
|
"std::function<void (const HttpResponsePtr &)> &&callback, double "
|
||||||
"p1,int p2) const;\n";
|
"p1, int p2) const;\n";
|
||||||
file << "};\n";
|
file << "};\n";
|
||||||
while (namespaceCount > 0)
|
while (namespaceCount > 0)
|
||||||
{
|
{
|
||||||
@ -289,22 +305,25 @@ void create_controller::newHttpControllerHeaderFile(
|
|||||||
file << "}\n";
|
file << "}\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void create_controller::newHttpControllerSourceFile(
|
void create_controller::newHttpControllerSourceFile(
|
||||||
std::ofstream &file,
|
std::ofstream &file,
|
||||||
const std::string &className,
|
const std::string &className,
|
||||||
const std::string &filename)
|
const std::string &filename)
|
||||||
{
|
{
|
||||||
file << "#include \"" << filename << ".h\"\n";
|
file << "#include \"" << filename << ".h\"\n";
|
||||||
|
file << "\n";
|
||||||
auto pos = className.rfind("::");
|
auto pos = className.rfind("::");
|
||||||
auto class_name = className;
|
auto class_name = className;
|
||||||
if (pos != std::string::npos)
|
if (pos != std::string::npos)
|
||||||
{
|
{
|
||||||
auto namespacename = className.substr(0, pos);
|
auto namespacename = className.substr(0, pos);
|
||||||
file << "using namespace " << namespacename << ";\n";
|
file << "using namespace " << namespacename << ";\n";
|
||||||
|
file << "\n";
|
||||||
class_name = className.substr(pos + 2);
|
class_name = className.substr(pos + 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
file << "//add definition of your processing function here\n";
|
file << "// Add definition of your processing function here\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void create_controller::createController(std::vector<std::string> &httpClasses,
|
void create_controller::createController(std::vector<std::string> &httpClasses,
|
||||||
@ -360,20 +379,21 @@ void create_controller::createController(const std::string &className,
|
|||||||
}
|
}
|
||||||
if (type == Http)
|
if (type == Http)
|
||||||
{
|
{
|
||||||
std::cout << "create a http controller:" << className << std::endl;
|
std::cout << "Create a http controller: " << className << std::endl;
|
||||||
newHttpControllerHeaderFile(oHeadFile, className);
|
newHttpControllerHeaderFile(oHeadFile, className);
|
||||||
newHttpControllerSourceFile(oSourceFile, className, ctlName);
|
newHttpControllerSourceFile(oSourceFile, className, ctlName);
|
||||||
}
|
}
|
||||||
else if (type == Simple)
|
else if (type == Simple)
|
||||||
{
|
{
|
||||||
std::cout << "create a http simple controller:" << className
|
std::cout << "Create a http simple controller: " << className
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
newSimpleControllerHeaderFile(oHeadFile, className);
|
newSimpleControllerHeaderFile(oHeadFile, className);
|
||||||
newSimpleControllerSourceFile(oSourceFile, className, ctlName);
|
newSimpleControllerSourceFile(oSourceFile, className, ctlName);
|
||||||
}
|
}
|
||||||
else if (type == WebSocket)
|
else if (type == WebSocket)
|
||||||
{
|
{
|
||||||
std::cout << "create a websocket controller:" << className << std::endl;
|
std::cout << "Create a websocket controller: " << className
|
||||||
|
<< std::endl;
|
||||||
newWebsockControllerHeaderFile(oHeadFile, className);
|
newWebsockControllerHeaderFile(oHeadFile, className);
|
||||||
newWebsockControllerSourceFile(oSourceFile, className, ctlName);
|
newWebsockControllerSourceFile(oSourceFile, className, ctlName);
|
||||||
}
|
}
|
||||||
@ -444,8 +464,8 @@ void create_controller::createARestfulController(const std::string &className,
|
|||||||
std::cerr << err.what() << std::endl;
|
std::cerr << err.what() << std::endl;
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
std::cout << "create a http restful API controller:" << className
|
std::cout << "Create a http restful API controller: " << className
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
std::cout << "file name: " << ctlName << ".h and " << ctlName << ".cc"
|
std::cout << "File name: " << ctlName << ".h and " << ctlName << ".cc"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
}
|
}
|
||||||
|
@ -18,14 +18,16 @@
|
|||||||
#include <drogon/DrTemplateBase.h>
|
#include <drogon/DrTemplateBase.h>
|
||||||
#include "CommandHandler.h"
|
#include "CommandHandler.h"
|
||||||
using namespace drogon;
|
using namespace drogon;
|
||||||
|
|
||||||
namespace drogon_ctl
|
namespace drogon_ctl
|
||||||
{
|
{
|
||||||
class create_controller : public DrObject<create_controller>,
|
class create_controller : public DrObject<create_controller>,
|
||||||
public CommandHandler
|
public CommandHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void handleCommand(std::vector<std::string> ¶meters) override;
|
void handleCommand(std::vector<std::string> ¶meters) override;
|
||||||
virtual std::string script() override
|
|
||||||
|
std::string script() override
|
||||||
{
|
{
|
||||||
return "create controller files";
|
return "create controller files";
|
||||||
}
|
}
|
||||||
|
@ -69,6 +69,7 @@ static void createFilterSourceFile(std::ofstream &file,
|
|||||||
data.insert("filename", fileName);
|
data.insert("filename", fileName);
|
||||||
file << templ->genText(data);
|
file << templ->genText(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void create_filter::handleCommand(std::vector<std::string> ¶meters)
|
void create_filter::handleCommand(std::vector<std::string> ¶meters)
|
||||||
{
|
{
|
||||||
if (parameters.size() < 1)
|
if (parameters.size() < 1)
|
||||||
|
@ -17,13 +17,15 @@
|
|||||||
#include <drogon/DrObject.h>
|
#include <drogon/DrObject.h>
|
||||||
#include "CommandHandler.h"
|
#include "CommandHandler.h"
|
||||||
using namespace drogon;
|
using namespace drogon;
|
||||||
|
|
||||||
namespace drogon_ctl
|
namespace drogon_ctl
|
||||||
{
|
{
|
||||||
class create_filter : public DrObject<create_filter>, public CommandHandler
|
class create_filter : public DrObject<create_filter>, public CommandHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void handleCommand(std::vector<std::string> ¶meters) override;
|
void handleCommand(std::vector<std::string> ¶meters) override;
|
||||||
virtual std::string script() override
|
|
||||||
|
std::string script() override
|
||||||
{
|
{
|
||||||
return "create filter class files";
|
return "create filter class files";
|
||||||
}
|
}
|
||||||
|
@ -36,10 +36,13 @@
|
|||||||
|
|
||||||
using namespace std::chrono_literals;
|
using namespace std::chrono_literals;
|
||||||
using namespace drogon_ctl;
|
using namespace drogon_ctl;
|
||||||
|
|
||||||
static std::string toLower(const std::string &str)
|
static std::string toLower(const std::string &str)
|
||||||
{
|
{
|
||||||
auto ret = str;
|
auto ret = str;
|
||||||
std::transform(ret.begin(), ret.end(), ret.begin(), tolower);
|
std::transform(ret.begin(), ret.end(), ret.begin(), [](unsigned char c) {
|
||||||
|
return tolower(c);
|
||||||
|
});
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,6 +66,17 @@ static std::string escapeConnString(const std::string &str)
|
|||||||
return escaped;
|
return escaped;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string drogon_ctl::escapeIdentifier(const std::string &identifier,
|
||||||
|
const std::string &rdbms)
|
||||||
|
{
|
||||||
|
if (rdbms != "postgresql")
|
||||||
|
{
|
||||||
|
return identifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "\\\"" + identifier + "\\\"";
|
||||||
|
}
|
||||||
|
|
||||||
static std::map<std::string, std::vector<ConvertMethod>> getConvertMethods(
|
static std::map<std::string, std::vector<ConvertMethod>> getConvertMethods(
|
||||||
const Json::Value &convertColumns)
|
const Json::Value &convertColumns)
|
||||||
{
|
{
|
||||||
@ -163,7 +177,7 @@ void create_model::createModelClassFromPG(
|
|||||||
auto className = nameTransform(tableName, true);
|
auto className = nameTransform(tableName, true);
|
||||||
HttpViewData data;
|
HttpViewData data;
|
||||||
data["className"] = className;
|
data["className"] = className;
|
||||||
data["tableName"] = toLower(tableName);
|
data["tableName"] = tableName;
|
||||||
data["hasPrimaryKey"] = (int)0;
|
data["hasPrimaryKey"] = (int)0;
|
||||||
data["primaryKeyName"] = "";
|
data["primaryKeyName"] = "";
|
||||||
data["dbName"] = dbname_;
|
data["dbName"] = dbname_;
|
||||||
@ -175,10 +189,10 @@ void create_model::createModelClassFromPG(
|
|||||||
data["schema"] = schema;
|
data["schema"] = schema;
|
||||||
}
|
}
|
||||||
std::vector<ColumnInfo> cols;
|
std::vector<ColumnInfo> cols;
|
||||||
*client << "SELECT * \
|
*client << "SELECT * "
|
||||||
FROM information_schema.columns \
|
"FROM information_schema.columns "
|
||||||
WHERE table_schema = $1 \
|
"WHERE table_schema = $1 "
|
||||||
AND table_name = $2"
|
"AND table_name = $2"
|
||||||
<< schema << tableName << Mode::Blocking >>
|
<< schema << tableName << Mode::Blocking >>
|
||||||
[&](const Result &r) {
|
[&](const Result &r) {
|
||||||
if (r.size() == 0)
|
if (r.size() == 0)
|
||||||
@ -281,14 +295,14 @@ void create_model::createModelClassFromPG(
|
|||||||
exit(1);
|
exit(1);
|
||||||
};
|
};
|
||||||
size_t pkNumber = 0;
|
size_t pkNumber = 0;
|
||||||
*client << "SELECT \
|
*client << "SELECT "
|
||||||
pg_constraint.conname AS pk_name,\
|
"pg_constraint.conname AS pk_name,"
|
||||||
pg_constraint.conkey AS pk_vector \
|
"pg_constraint.conkey AS pk_vector "
|
||||||
FROM pg_constraint \
|
"FROM pg_constraint "
|
||||||
INNER JOIN pg_class ON pg_constraint.conrelid = pg_class.oid \
|
"INNER JOIN pg_class ON pg_constraint.conrelid = pg_class.oid "
|
||||||
WHERE \
|
"WHERE "
|
||||||
pg_class.relname = $1 \
|
"pg_class.relname = $1 "
|
||||||
AND pg_constraint.contype = 'p'"
|
"AND pg_constraint.contype = 'p'"
|
||||||
<< tableName << Mode::Blocking >>
|
<< tableName << Mode::Blocking >>
|
||||||
[&](bool isNull,
|
[&](bool isNull,
|
||||||
const std::string &pkName,
|
const std::string &pkName,
|
||||||
@ -305,16 +319,18 @@ void create_model::createModelClassFromPG(
|
|||||||
data["hasPrimaryKey"] = (int)pkNumber;
|
data["hasPrimaryKey"] = (int)pkNumber;
|
||||||
if (pkNumber == 1)
|
if (pkNumber == 1)
|
||||||
{
|
{
|
||||||
*client << "SELECT \
|
*client << "SELECT "
|
||||||
pg_attribute.attname AS colname,\
|
"pg_attribute.attname AS colname,"
|
||||||
pg_type.typname AS typename,\
|
"pg_type.typname AS typename,"
|
||||||
pg_constraint.contype AS contype \
|
"pg_constraint.contype AS contype "
|
||||||
FROM pg_constraint \
|
"FROM pg_constraint "
|
||||||
INNER JOIN pg_class ON pg_constraint.conrelid = pg_class.oid \
|
"INNER JOIN pg_class ON pg_constraint.conrelid = "
|
||||||
INNER JOIN pg_attribute ON pg_attribute.attrelid = pg_class.oid \
|
"pg_class.oid "
|
||||||
AND pg_attribute.attnum = pg_constraint.conkey [ 1 ] \
|
"INNER JOIN pg_attribute ON pg_attribute.attrelid = "
|
||||||
INNER JOIN pg_type ON pg_type.oid = pg_attribute.atttypid \
|
"pg_class.oid "
|
||||||
WHERE pg_class.relname = $1 and pg_constraint.contype='p'"
|
"AND pg_attribute.attnum = pg_constraint.conkey [ 1 ] "
|
||||||
|
"INNER JOIN pg_type ON pg_type.oid = pg_attribute.atttypid "
|
||||||
|
"WHERE pg_class.relname = $1 and pg_constraint.contype='p'"
|
||||||
<< tableName << Mode::Blocking >>
|
<< tableName << Mode::Blocking >>
|
||||||
[&](bool isNull,
|
[&](bool isNull,
|
||||||
const std::string &colName,
|
const std::string &colName,
|
||||||
@ -342,16 +358,20 @@ void create_model::createModelClassFromPG(
|
|||||||
std::vector<std::string> pkNames, pkTypes, pkValNames;
|
std::vector<std::string> pkNames, pkTypes, pkValNames;
|
||||||
for (size_t i = 1; i <= pkNumber; ++i)
|
for (size_t i = 1; i <= pkNumber; ++i)
|
||||||
{
|
{
|
||||||
*client << "SELECT \
|
*client << "SELECT "
|
||||||
pg_attribute.attname AS colname,\
|
"pg_attribute.attname AS colname,"
|
||||||
pg_type.typname AS typename,\
|
"pg_type.typname AS typename,"
|
||||||
pg_constraint.contype AS contype \
|
"pg_constraint.contype AS contype "
|
||||||
FROM pg_constraint \
|
"FROM pg_constraint "
|
||||||
INNER JOIN pg_class ON pg_constraint.conrelid = pg_class.oid \
|
"INNER JOIN pg_class ON pg_constraint.conrelid = "
|
||||||
INNER JOIN pg_attribute ON pg_attribute.attrelid = pg_class.oid \
|
"pg_class.oid "
|
||||||
AND pg_attribute.attnum = pg_constraint.conkey [ $1 ] \
|
"INNER JOIN pg_attribute ON pg_attribute.attrelid = "
|
||||||
INNER JOIN pg_type ON pg_type.oid = pg_attribute.atttypid \
|
"pg_class.oid "
|
||||||
WHERE pg_class.relname = $2 and pg_constraint.contype='p'"
|
"AND pg_attribute.attnum = pg_constraint.conkey [ $1 ] "
|
||||||
|
"INNER JOIN pg_type ON pg_type.oid = "
|
||||||
|
"pg_attribute.atttypid "
|
||||||
|
"WHERE pg_class.relname = $2 and "
|
||||||
|
"pg_constraint.contype='p'"
|
||||||
<< (int)i << tableName << Mode::Blocking >>
|
<< (int)i << tableName << Mode::Blocking >>
|
||||||
[&](bool isNull, std::string colName, const std::string &type) {
|
[&](bool isNull, std::string colName, const std::string &type) {
|
||||||
if (isNull)
|
if (isNull)
|
||||||
@ -387,6 +407,7 @@ void create_model::createModelClassFromPG(
|
|||||||
sourceFile << templ->genText(data);
|
sourceFile << templ->genText(data);
|
||||||
createRestfulAPIController(data, restfulApiConfig);
|
createRestfulAPIController(data, restfulApiConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
void create_model::createModelFromPG(
|
void create_model::createModelFromPG(
|
||||||
const std::string &path,
|
const std::string &path,
|
||||||
const DbClientPtr &client,
|
const DbClientPtr &client,
|
||||||
@ -450,7 +471,7 @@ void create_model::createModelClassFromMysql(
|
|||||||
data["convertMethods"] = convertMethods;
|
data["convertMethods"] = convertMethods;
|
||||||
std::vector<ColumnInfo> cols;
|
std::vector<ColumnInfo> cols;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
*client << "desc " + tableName << Mode::Blocking >>
|
*client << "desc `" + tableName + "`" << Mode::Blocking >>
|
||||||
[&i, &cols](bool isNull,
|
[&i, &cols](bool isNull,
|
||||||
const std::string &field,
|
const std::string &field,
|
||||||
const std::string &type,
|
const std::string &type,
|
||||||
@ -479,6 +500,11 @@ void create_model::createModelClassFromMysql(
|
|||||||
info.colType_ = "int16_t";
|
info.colType_ = "int16_t";
|
||||||
info.colLength_ = 2;
|
info.colLength_ = 2;
|
||||||
}
|
}
|
||||||
|
else if (type.find("mediumint") == 0)
|
||||||
|
{
|
||||||
|
info.colType_ = "int32_t";
|
||||||
|
info.colLength_ = 3;
|
||||||
|
}
|
||||||
else if (type.find("int") == 0)
|
else if (type.find("int") == 0)
|
||||||
{
|
{
|
||||||
info.colType_ = "int32_t";
|
info.colType_ = "int32_t";
|
||||||
@ -577,6 +603,7 @@ void create_model::createModelClassFromMysql(
|
|||||||
sourceFile << templ->genText(data);
|
sourceFile << templ->genText(data);
|
||||||
createRestfulAPIController(data, restfulApiConfig);
|
createRestfulAPIController(data, restfulApiConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
void create_model::createModelFromMysql(
|
void create_model::createModelFromMysql(
|
||||||
const std::string &path,
|
const std::string &path,
|
||||||
const DbClientPtr &client,
|
const DbClientPtr &client,
|
||||||
@ -630,7 +657,10 @@ void create_model::createModelClassFromSqlite3(
|
|||||||
bool notnull = row["notnull"].as<bool>();
|
bool notnull = row["notnull"].as<bool>();
|
||||||
bool primary = row["pk"].as<int>();
|
bool primary = row["pk"].as<int>();
|
||||||
auto type = row["type"].as<std::string>();
|
auto type = row["type"].as<std::string>();
|
||||||
std::transform(type.begin(), type.end(), type.begin(), tolower);
|
std::transform(type.begin(),
|
||||||
|
type.end(),
|
||||||
|
type.begin(),
|
||||||
|
[](unsigned char c) { return tolower(c); });
|
||||||
ColumnInfo info;
|
ColumnInfo info;
|
||||||
info.index_ = index++;
|
info.index_ = index++;
|
||||||
info.dbType_ = "sqlite3";
|
info.dbType_ = "sqlite3";
|
||||||
@ -657,7 +687,9 @@ void create_model::createModelClassFromSqlite3(
|
|||||||
std::transform(sql.begin(),
|
std::transform(sql.begin(),
|
||||||
sql.end(),
|
sql.end(),
|
||||||
sql.begin(),
|
sql.begin(),
|
||||||
tolower);
|
[](unsigned char c) {
|
||||||
|
return tolower(c);
|
||||||
|
});
|
||||||
if (sql.find("autoincrement") !=
|
if (sql.find("autoincrement") !=
|
||||||
std::string::npos)
|
std::string::npos)
|
||||||
{
|
{
|
||||||
@ -678,7 +710,7 @@ void create_model::createModelClassFromSqlite3(
|
|||||||
|
|
||||||
if (type.find("int") != std::string::npos)
|
if (type.find("int") != std::string::npos)
|
||||||
{
|
{
|
||||||
info.colType_ = "uint64_t";
|
info.colType_ = "int64_t";
|
||||||
info.colLength_ = 8;
|
info.colLength_ = 8;
|
||||||
}
|
}
|
||||||
else if (type.find("char") != std::string::npos || type == "text" ||
|
else if (type.find("char") != std::string::npos || type == "text" ||
|
||||||
@ -733,6 +765,11 @@ void create_model::createModelClassFromSqlite3(
|
|||||||
}
|
}
|
||||||
else if (pkNames.size() > 1)
|
else if (pkNames.size() > 1)
|
||||||
{
|
{
|
||||||
|
for (auto &col : cols)
|
||||||
|
{
|
||||||
|
col.isAutoVal_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
data["primaryKeyName"] = pkNames;
|
data["primaryKeyName"] = pkNames;
|
||||||
data["primaryKeyType"] = pkTypes;
|
data["primaryKeyType"] = pkTypes;
|
||||||
data["primaryKeyValNames"] = pkValNames;
|
data["primaryKeyValNames"] = pkValNames;
|
||||||
@ -782,10 +819,14 @@ void create_model::createModel(const std::string &path,
|
|||||||
const std::string &singleModelName)
|
const std::string &singleModelName)
|
||||||
{
|
{
|
||||||
auto dbType = config.get("rdbms", "no dbms").asString();
|
auto dbType = config.get("rdbms", "no dbms").asString();
|
||||||
std::transform(dbType.begin(), dbType.end(), dbType.begin(), tolower);
|
std::transform(dbType.begin(),
|
||||||
|
dbType.end(),
|
||||||
|
dbType.begin(),
|
||||||
|
[](unsigned char c) { return tolower(c); });
|
||||||
auto restfulApiConfig = config["restful_api_controllers"];
|
auto restfulApiConfig = config["restful_api_controllers"];
|
||||||
auto relationships = getRelationships(config["relationships"]);
|
auto relationships = getRelationships(config["relationships"]);
|
||||||
auto convertMethods = getConvertMethods(config["convert"]);
|
auto convertMethods = getConvertMethods(config["convert"]);
|
||||||
|
drogon::utils::createPath(path);
|
||||||
if (dbType == "postgresql")
|
if (dbType == "postgresql")
|
||||||
{
|
{
|
||||||
#if USE_POSTGRESQL
|
#if USE_POSTGRESQL
|
||||||
@ -869,7 +910,7 @@ void create_model::createModel(const std::string &path,
|
|||||||
std::transform(tableName.begin(),
|
std::transform(tableName.begin(),
|
||||||
tableName.end(),
|
tableName.end(),
|
||||||
tableName.begin(),
|
tableName.begin(),
|
||||||
tolower);
|
[](unsigned char c) { return tolower(c); });
|
||||||
std::cout << "table name:" << tableName << std::endl;
|
std::cout << "table name:" << tableName << std::endl;
|
||||||
createModelClassFromPG(path,
|
createModelClassFromPG(path,
|
||||||
client,
|
client,
|
||||||
@ -978,7 +1019,7 @@ void create_model::createModel(const std::string &path,
|
|||||||
std::transform(tableName.begin(),
|
std::transform(tableName.begin(),
|
||||||
tableName.end(),
|
tableName.end(),
|
||||||
tableName.begin(),
|
tableName.begin(),
|
||||||
tolower);
|
[](unsigned char c) { return tolower(c); });
|
||||||
std::cout << "table name:" << tableName << std::endl;
|
std::cout << "table name:" << tableName << std::endl;
|
||||||
createModelClassFromMysql(path,
|
createModelClassFromMysql(path,
|
||||||
client,
|
client,
|
||||||
@ -1053,7 +1094,7 @@ void create_model::createModel(const std::string &path,
|
|||||||
std::transform(tableName.begin(),
|
std::transform(tableName.begin(),
|
||||||
tableName.end(),
|
tableName.end(),
|
||||||
tableName.begin(),
|
tableName.begin(),
|
||||||
tolower);
|
[](unsigned char c) { return tolower(c); });
|
||||||
std::cout << "table name:" << tableName << std::endl;
|
std::cout << "table name:" << tableName << std::endl;
|
||||||
createModelClassFromSqlite3(path,
|
createModelClassFromSqlite3(path,
|
||||||
client,
|
client,
|
||||||
@ -1092,6 +1133,7 @@ void create_model::createModel(const std::string &path,
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void create_model::createModel(const std::string &path,
|
void create_model::createModel(const std::string &path,
|
||||||
const std::string &singleModelName)
|
const std::string &singleModelName)
|
||||||
{
|
{
|
||||||
@ -1132,7 +1174,9 @@ void create_model::createModel(const std::string &path,
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
infile >> configJsonRoot;
|
infile >> configJsonRoot;
|
||||||
createModel(path, configJsonRoot, singleModelName);
|
createModel(outputPath_.empty() ? path : outputPath_,
|
||||||
|
configJsonRoot,
|
||||||
|
singleModelName);
|
||||||
}
|
}
|
||||||
catch (const std::exception &exception)
|
catch (const std::exception &exception)
|
||||||
{
|
{
|
||||||
@ -1170,6 +1214,22 @@ void create_model::handleCommand(std::vector<std::string> ¶meters)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (auto iter = parameters.begin(); iter != parameters.end();)
|
||||||
|
{
|
||||||
|
auto &file = *iter;
|
||||||
|
if (file == "-o" || file == "--output")
|
||||||
|
{
|
||||||
|
iter = parameters.erase(iter);
|
||||||
|
if (iter != parameters.end())
|
||||||
|
{
|
||||||
|
outputPath_ = *iter;
|
||||||
|
iter = parameters.erase(iter);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
++iter;
|
||||||
|
}
|
||||||
|
|
||||||
for (auto const &path : parameters)
|
for (auto const &path : parameters)
|
||||||
{
|
{
|
||||||
createModel(path, singleModelName);
|
createModel(path, singleModelName);
|
||||||
@ -1194,7 +1254,10 @@ void create_model::createRestfulAPIController(
|
|||||||
restfulApiConfig.get("resource_uri", "/*").asString(),
|
restfulApiConfig.get("resource_uri", "/*").asString(),
|
||||||
regex,
|
regex,
|
||||||
modelClassName);
|
modelClassName);
|
||||||
std::transform(resource.begin(), resource.end(), resource.begin(), tolower);
|
std::transform(resource.begin(),
|
||||||
|
resource.end(),
|
||||||
|
resource.begin(),
|
||||||
|
[](unsigned char c) { return tolower(c); });
|
||||||
auto ctrlClassName =
|
auto ctrlClassName =
|
||||||
std::regex_replace(restfulApiConfig.get("class_name", "/*").asString(),
|
std::regex_replace(restfulApiConfig.get("class_name", "/*").asString(),
|
||||||
regex,
|
regex,
|
||||||
|
@ -47,7 +47,9 @@ struct ColumnInfo
|
|||||||
inline std::string nameTransform(const std::string &origName, bool isType)
|
inline std::string nameTransform(const std::string &origName, bool isType)
|
||||||
{
|
{
|
||||||
auto str = origName;
|
auto str = origName;
|
||||||
std::transform(str.begin(), str.end(), str.begin(), tolower);
|
std::transform(str.begin(), str.end(), str.begin(), [](unsigned char c) {
|
||||||
|
return tolower(c);
|
||||||
|
});
|
||||||
std::string::size_type startPos = 0;
|
std::string::size_type startPos = 0;
|
||||||
std::string::size_type pos;
|
std::string::size_type pos;
|
||||||
std::string ret;
|
std::string ret;
|
||||||
@ -75,10 +77,15 @@ inline std::string nameTransform(const std::string &origName, bool isType)
|
|||||||
ret[0] += ('A' - 'a');
|
ret[0] += ('A' - 'a');
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string escapeIdentifier(const std::string &identifier,
|
||||||
|
const std::string &rdbms);
|
||||||
|
|
||||||
class PivotTable
|
class PivotTable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PivotTable() = default;
|
PivotTable() = default;
|
||||||
|
|
||||||
PivotTable(const Json::Value &json)
|
PivotTable(const Json::Value &json)
|
||||||
: tableName_(json.get("table_name", "").asString())
|
: tableName_(json.get("table_name", "").asString())
|
||||||
{
|
{
|
||||||
@ -97,6 +104,7 @@ class PivotTable
|
|||||||
throw std::runtime_error("target_key can't be empty");
|
throw std::runtime_error("target_key can't be empty");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PivotTable reverse() const
|
PivotTable reverse() const
|
||||||
{
|
{
|
||||||
PivotTable pivot;
|
PivotTable pivot;
|
||||||
@ -105,14 +113,17 @@ class PivotTable
|
|||||||
pivot.targetKey_ = originalKey_;
|
pivot.targetKey_ = originalKey_;
|
||||||
return pivot;
|
return pivot;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string &tableName() const
|
const std::string &tableName() const
|
||||||
{
|
{
|
||||||
return tableName_;
|
return tableName_;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string &originalKey() const
|
const std::string &originalKey() const
|
||||||
{
|
{
|
||||||
return originalKey_;
|
return originalKey_;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string &targetKey() const
|
const std::string &targetKey() const
|
||||||
{
|
{
|
||||||
return targetKey_;
|
return targetKey_;
|
||||||
@ -158,6 +169,7 @@ class ConvertMethod
|
|||||||
includeFiles_.push_back(i.asString());
|
includeFiles_.push_back(i.asString());
|
||||||
} // for
|
} // for
|
||||||
}
|
}
|
||||||
|
|
||||||
ConvertMethod() = default;
|
ConvertMethod() = default;
|
||||||
|
|
||||||
bool shouldConvert(const std::string &tableName,
|
bool shouldConvert(const std::string &tableName,
|
||||||
@ -167,18 +179,22 @@ class ConvertMethod
|
|||||||
{
|
{
|
||||||
return tableName_;
|
return tableName_;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string &colName() const
|
const std::string &colName() const
|
||||||
{
|
{
|
||||||
return colName_;
|
return colName_;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string &methodBeforeDbWrite() const
|
const std::string &methodBeforeDbWrite() const
|
||||||
{
|
{
|
||||||
return methodBeforeDbWrite_;
|
return methodBeforeDbWrite_;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string &methodAfterDbRead() const
|
const std::string &methodAfterDbRead() const
|
||||||
{
|
{
|
||||||
return methodAfterDbRead_;
|
return methodAfterDbRead_;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<std::string> &includeFiles() const
|
const std::vector<std::string> &includeFiles() const
|
||||||
{
|
{
|
||||||
return includeFiles_;
|
return includeFiles_;
|
||||||
@ -201,6 +217,7 @@ class Relationship
|
|||||||
HasMany,
|
HasMany,
|
||||||
ManyToMany
|
ManyToMany
|
||||||
};
|
};
|
||||||
|
|
||||||
Relationship(const Json::Value &relationship)
|
Relationship(const Json::Value &relationship)
|
||||||
{
|
{
|
||||||
auto type = relationship.get("type", "has one").asString();
|
auto type = relationship.get("type", "has one").asString();
|
||||||
@ -262,7 +279,9 @@ class Relationship
|
|||||||
pivotTable_ = PivotTable(pivot);
|
pivotTable_ = PivotTable(pivot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Relationship() = default;
|
Relationship() = default;
|
||||||
|
|
||||||
Relationship reverse() const
|
Relationship reverse() const
|
||||||
{
|
{
|
||||||
Relationship r;
|
Relationship r;
|
||||||
@ -284,38 +303,47 @@ class Relationship
|
|||||||
r.pivotTable_ = pivotTable_.reverse();
|
r.pivotTable_ = pivotTable_.reverse();
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
Type type() const
|
Type type() const
|
||||||
{
|
{
|
||||||
return type_;
|
return type_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool enableReverse() const
|
bool enableReverse() const
|
||||||
{
|
{
|
||||||
return enableReverse_;
|
return enableReverse_;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string &originalTableName() const
|
const std::string &originalTableName() const
|
||||||
{
|
{
|
||||||
return originalTableName_;
|
return originalTableName_;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string &originalTableAlias() const
|
const std::string &originalTableAlias() const
|
||||||
{
|
{
|
||||||
return originalTableAlias_;
|
return originalTableAlias_;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string &originalKey() const
|
const std::string &originalKey() const
|
||||||
{
|
{
|
||||||
return originalKey_;
|
return originalKey_;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string &targetTableName() const
|
const std::string &targetTableName() const
|
||||||
{
|
{
|
||||||
return targetTableName_;
|
return targetTableName_;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string &targetTableAlias() const
|
const std::string &targetTableAlias() const
|
||||||
{
|
{
|
||||||
return targetTableAlias_;
|
return targetTableAlias_;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string &targetKey() const
|
const std::string &targetKey() const
|
||||||
{
|
{
|
||||||
return targetKey_;
|
return targetKey_;
|
||||||
}
|
}
|
||||||
|
|
||||||
const PivotTable &pivotTable() const
|
const PivotTable &pivotTable() const
|
||||||
{
|
{
|
||||||
return pivotTable_;
|
return pivotTable_;
|
||||||
@ -332,11 +360,13 @@ class Relationship
|
|||||||
bool enableReverse_{false};
|
bool enableReverse_{false};
|
||||||
PivotTable pivotTable_;
|
PivotTable pivotTable_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class create_model : public DrObject<create_model>, public CommandHandler
|
class create_model : public DrObject<create_model>, public CommandHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void handleCommand(std::vector<std::string> ¶meters) override;
|
void handleCommand(std::vector<std::string> ¶meters) override;
|
||||||
virtual std::string script() override
|
|
||||||
|
std::string script() override
|
||||||
{
|
{
|
||||||
return "create Model classes files";
|
return "create Model classes files";
|
||||||
}
|
}
|
||||||
@ -399,5 +429,6 @@ class create_model : public DrObject<create_model>, public CommandHandler
|
|||||||
const Json::Value &restfulApiConfig);
|
const Json::Value &restfulApiConfig);
|
||||||
std::string dbname_;
|
std::string dbname_;
|
||||||
bool forceOverwrite_{false};
|
bool forceOverwrite_{false};
|
||||||
|
std::string outputPath_;
|
||||||
};
|
};
|
||||||
} // namespace drogon_ctl
|
} // namespace drogon_ctl
|
||||||
|
@ -69,6 +69,7 @@ static void createPluginSourceFile(std::ofstream &file,
|
|||||||
data.insert("filename", fileName);
|
data.insert("filename", fileName);
|
||||||
file << templ->genText(data);
|
file << templ->genText(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void create_plugin::handleCommand(std::vector<std::string> ¶meters)
|
void create_plugin::handleCommand(std::vector<std::string> ¶meters)
|
||||||
{
|
{
|
||||||
if (parameters.size() < 1)
|
if (parameters.size() < 1)
|
||||||
|
@ -17,13 +17,15 @@
|
|||||||
#include <drogon/DrObject.h>
|
#include <drogon/DrObject.h>
|
||||||
#include "CommandHandler.h"
|
#include "CommandHandler.h"
|
||||||
using namespace drogon;
|
using namespace drogon;
|
||||||
|
|
||||||
namespace drogon_ctl
|
namespace drogon_ctl
|
||||||
{
|
{
|
||||||
class create_plugin : public DrObject<create_plugin>, public CommandHandler
|
class create_plugin : public DrObject<create_plugin>, public CommandHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void handleCommand(std::vector<std::string> ¶meters) override;
|
void handleCommand(std::vector<std::string> ¶meters) override;
|
||||||
virtual std::string script() override
|
|
||||||
|
std::string script() override
|
||||||
{
|
{
|
||||||
return "create plugin class files";
|
return "create plugin class files";
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,7 @@ void create_project::handleCommand(std::vector<std::string> ¶meters)
|
|||||||
auto pName = parameters[0];
|
auto pName = parameters[0];
|
||||||
createProject(pName);
|
createProject(pName);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void newCmakeFile(std::ofstream &cmakeFile,
|
static void newCmakeFile(std::ofstream &cmakeFile,
|
||||||
const std::string &projectName)
|
const std::string &projectName)
|
||||||
{
|
{
|
||||||
@ -46,32 +47,43 @@ static void newCmakeFile(std::ofstream &cmakeFile,
|
|||||||
auto templ = DrTemplateBase::newTemplate("cmake.csp");
|
auto templ = DrTemplateBase::newTemplate("cmake.csp");
|
||||||
cmakeFile << templ->genText(data);
|
cmakeFile << templ->genText(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void newMainFile(std::ofstream &mainFile)
|
static void newMainFile(std::ofstream &mainFile)
|
||||||
{
|
{
|
||||||
auto templ = DrTemplateBase::newTemplate("demoMain");
|
auto templ = DrTemplateBase::newTemplate("demoMain");
|
||||||
mainFile << templ->genText();
|
mainFile << templ->genText();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void newGitIgFile(std::ofstream &gitFile)
|
static void newGitIgFile(std::ofstream &gitFile)
|
||||||
{
|
{
|
||||||
auto templ = DrTemplateBase::newTemplate("gitignore.csp");
|
auto templ = DrTemplateBase::newTemplate("gitignore.csp");
|
||||||
gitFile << templ->genText();
|
gitFile << templ->genText();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void newConfigFile(std::ofstream &configFile)
|
static void newConfigJsonFile(std::ofstream &configJsonFile)
|
||||||
{
|
{
|
||||||
auto templ = DrTemplateBase::newTemplate("config");
|
auto templ = DrTemplateBase::newTemplate("config_json");
|
||||||
configFile << templ->genText();
|
configJsonFile << templ->genText();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void newConfigYamlFile(std::ofstream &configYamlFile)
|
||||||
|
{
|
||||||
|
auto templ = DrTemplateBase::newTemplate("config_yaml");
|
||||||
|
configYamlFile << templ->genText();
|
||||||
|
}
|
||||||
|
|
||||||
static void newModelConfigFile(std::ofstream &configFile)
|
static void newModelConfigFile(std::ofstream &configFile)
|
||||||
{
|
{
|
||||||
auto templ = DrTemplateBase::newTemplate("model_json");
|
auto templ = DrTemplateBase::newTemplate("model_json");
|
||||||
configFile << templ->genText();
|
configFile << templ->genText();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void newTestMainFile(std::ofstream &mainFile)
|
static void newTestMainFile(std::ofstream &mainFile)
|
||||||
{
|
{
|
||||||
auto templ = DrTemplateBase::newTemplate("test_main");
|
auto templ = DrTemplateBase::newTemplate("test_main");
|
||||||
mainFile << templ->genText();
|
mainFile << templ->genText();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void newTestCmakeFile(std::ofstream &testCmakeFile,
|
static void newTestCmakeFile(std::ofstream &testCmakeFile,
|
||||||
const std::string &projectName)
|
const std::string &projectName)
|
||||||
{
|
{
|
||||||
@ -80,6 +92,7 @@ static void newTestCmakeFile(std::ofstream &testCmakeFile,
|
|||||||
auto templ = DrTemplateBase::newTemplate("test_cmake");
|
auto templ = DrTemplateBase::newTemplate("test_cmake");
|
||||||
testCmakeFile << templ->genText(data);
|
testCmakeFile << templ->genText(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void create_project::createProject(const std::string &projectName)
|
void create_project::createProject(const std::string &projectName)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@ -117,8 +130,10 @@ void create_project::createProject(const std::string &projectName)
|
|||||||
|
|
||||||
std::ofstream gitFile(".gitignore", std::ofstream::out);
|
std::ofstream gitFile(".gitignore", std::ofstream::out);
|
||||||
newGitIgFile(gitFile);
|
newGitIgFile(gitFile);
|
||||||
std::ofstream configFile("config.json", std::ofstream::out);
|
std::ofstream configJsonFile("config.json", std::ofstream::out);
|
||||||
newConfigFile(configFile);
|
newConfigJsonFile(configJsonFile);
|
||||||
|
std::ofstream configYamlFile("config.yaml", std::ofstream::out);
|
||||||
|
newConfigYamlFile(configYamlFile);
|
||||||
std::ofstream modelConfigFile("models/model.json", std::ofstream::out);
|
std::ofstream modelConfigFile("models/model.json", std::ofstream::out);
|
||||||
newModelConfigFile(modelConfigFile);
|
newModelConfigFile(modelConfigFile);
|
||||||
std::ofstream testMainFile("test/test_main.cc", std::ofstream::out);
|
std::ofstream testMainFile("test/test_main.cc", std::ofstream::out);
|
||||||
|
@ -16,13 +16,15 @@
|
|||||||
#include <drogon/DrObject.h>
|
#include <drogon/DrObject.h>
|
||||||
#include "CommandHandler.h"
|
#include "CommandHandler.h"
|
||||||
using namespace drogon;
|
using namespace drogon;
|
||||||
|
|
||||||
namespace drogon_ctl
|
namespace drogon_ctl
|
||||||
{
|
{
|
||||||
class create_project : public DrObject<create_project>, public CommandHandler
|
class create_project : public DrObject<create_project>, public CommandHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void handleCommand(std::vector<std::string> ¶meters) override;
|
void handleCommand(std::vector<std::string> ¶meters) override;
|
||||||
virtual std::string script() override
|
|
||||||
|
std::string script() override
|
||||||
{
|
{
|
||||||
return "create a project";
|
return "create a project";
|
||||||
}
|
}
|
||||||
|
@ -53,6 +53,7 @@ static std::string &replace_all(std::string &str,
|
|||||||
}
|
}
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void parseCxxLine(std::ofstream &oSrcFile,
|
static void parseCxxLine(std::ofstream &oSrcFile,
|
||||||
const std::string &line,
|
const std::string &line,
|
||||||
const std::string &streamName,
|
const std::string &streamName,
|
||||||
@ -66,6 +67,7 @@ static void parseCxxLine(std::ofstream &oSrcFile,
|
|||||||
oSrcFile << tmp << "\n";
|
oSrcFile << tmp << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void outputVal(std::ofstream &oSrcFile,
|
static void outputVal(std::ofstream &oSrcFile,
|
||||||
const std::string &streamName,
|
const std::string &streamName,
|
||||||
const std::string &viewDataName,
|
const std::string &viewDataName,
|
||||||
@ -76,12 +78,12 @@ static void outputVal(std::ofstream &oSrcFile,
|
|||||||
<< "\"];\n";
|
<< "\"];\n";
|
||||||
oSrcFile << " if(val.type()==typeid(const char *)){\n";
|
oSrcFile << " if(val.type()==typeid(const char *)){\n";
|
||||||
oSrcFile << " " << streamName
|
oSrcFile << " " << streamName
|
||||||
<< "<<*any_cast<const char *>(&val);\n";
|
<< "<<*(std::any_cast<const char *>(&val));\n";
|
||||||
oSrcFile << " }else "
|
oSrcFile << " }else "
|
||||||
"if(val.type()==typeid(std::string)||val.type()==typeid(const "
|
"if(val.type()==typeid(std::string)||val.type()==typeid(const "
|
||||||
"std::string)){\n";
|
"std::string)){\n";
|
||||||
oSrcFile << " " << streamName
|
oSrcFile << " " << streamName
|
||||||
<< "<<*any_cast<const std::string>(&val);\n";
|
<< "<<*(std::any_cast<const std::string>(&val));\n";
|
||||||
oSrcFile << " }\n";
|
oSrcFile << " }\n";
|
||||||
oSrcFile << "}\n";
|
oSrcFile << "}\n";
|
||||||
}
|
}
|
||||||
@ -118,7 +120,7 @@ static void parseLine(std::ofstream &oSrcFile,
|
|||||||
{
|
{
|
||||||
// std::cout<<"blank line!"<<std::endl;
|
// std::cout<<"blank line!"<<std::endl;
|
||||||
// std::cout<<streamName<<"<<\"\\n\";\n";
|
// std::cout<<streamName<<"<<\"\\n\";\n";
|
||||||
if (returnFlag)
|
if (returnFlag && !cxx_flag)
|
||||||
oSrcFile << streamName << "<<\"\\n\";\n";
|
oSrcFile << streamName << "<<\"\\n\";\n";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -286,6 +288,7 @@ void create_view::handleCommand(std::vector<std::string> ¶meters)
|
|||||||
}
|
}
|
||||||
createViewFiles(parameters);
|
createViewFiles(parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
void create_view::createViewFiles(std::vector<std::string> &cspFileNames)
|
void create_view::createViewFiles(std::vector<std::string> &cspFileNames)
|
||||||
{
|
{
|
||||||
for (auto const &file : cspFileNames)
|
for (auto const &file : cspFileNames)
|
||||||
@ -295,6 +298,7 @@ void create_view::createViewFiles(std::vector<std::string> &cspFileNames)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int create_view::createViewFile(const std::string &script_filename)
|
int create_view::createViewFile(const std::string &script_filename)
|
||||||
{
|
{
|
||||||
std::cout << "create HttpView Class file by " << script_filename
|
std::cout << "create HttpView Class file by " << script_filename
|
||||||
@ -374,6 +378,7 @@ int create_view::createViewFile(const std::string &script_filename)
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void create_view::newViewHeaderFile(std::ofstream &file,
|
void create_view::newViewHeaderFile(std::ofstream &file,
|
||||||
const std::string &className)
|
const std::string &className)
|
||||||
{
|
{
|
||||||
@ -406,6 +411,7 @@ void create_view::newViewSourceFile(std::ofstream &file,
|
|||||||
"automatically,don't modify it!\n";
|
"automatically,don't modify it!\n";
|
||||||
file << "#include \"" << namespacePrefix << className << ".h\"\n";
|
file << "#include \"" << namespacePrefix << className << ".h\"\n";
|
||||||
file << "#include <drogon/utils/OStringStream.h>\n";
|
file << "#include <drogon/utils/OStringStream.h>\n";
|
||||||
|
file << "#include <drogon/utils/Utilities.h>\n";
|
||||||
file << "#include <string>\n";
|
file << "#include <string>\n";
|
||||||
file << "#include <map>\n";
|
file << "#include <map>\n";
|
||||||
file << "#include <vector>\n";
|
file << "#include <vector>\n";
|
||||||
@ -446,7 +452,7 @@ void create_view::newViewSourceFile(std::ofstream &file,
|
|||||||
std::transform(lowerBuffer.begin(),
|
std::transform(lowerBuffer.begin(),
|
||||||
lowerBuffer.end(),
|
lowerBuffer.end(),
|
||||||
lowerBuffer.begin(),
|
lowerBuffer.begin(),
|
||||||
::tolower);
|
[](unsigned char c) { return tolower(c); });
|
||||||
if ((pos = lowerBuffer.find(cxx_include)) != std::string::npos)
|
if ((pos = lowerBuffer.find(cxx_include)) != std::string::npos)
|
||||||
{
|
{
|
||||||
// std::cout<<"haha find it!"<<endl;
|
// std::cout<<"haha find it!"<<endl;
|
||||||
|
@ -17,13 +17,15 @@
|
|||||||
#include <drogon/DrObject.h>
|
#include <drogon/DrObject.h>
|
||||||
#include "CommandHandler.h"
|
#include "CommandHandler.h"
|
||||||
using namespace drogon;
|
using namespace drogon;
|
||||||
|
|
||||||
namespace drogon_ctl
|
namespace drogon_ctl
|
||||||
{
|
{
|
||||||
class create_view : public DrObject<create_view>, public CommandHandler
|
class create_view : public DrObject<create_view>, public CommandHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void handleCommand(std::vector<std::string> ¶meters) override;
|
void handleCommand(std::vector<std::string> ¶meters) override;
|
||||||
virtual std::string script() override
|
|
||||||
|
std::string script() override
|
||||||
{
|
{
|
||||||
return "create view class files";
|
return "create view class files";
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
using namespace drogon_ctl;
|
using namespace drogon_ctl;
|
||||||
|
|
||||||
void help::handleCommand(std::vector<std::string> ¶meters)
|
void help::handleCommand(std::vector<std::string> ¶meters)
|
||||||
{
|
{
|
||||||
if (parameters.size() == 0)
|
if (parameters.size() == 0)
|
||||||
|
@ -17,17 +17,20 @@
|
|||||||
#include <drogon/DrObject.h>
|
#include <drogon/DrObject.h>
|
||||||
#include "CommandHandler.h"
|
#include "CommandHandler.h"
|
||||||
using namespace drogon;
|
using namespace drogon;
|
||||||
|
|
||||||
namespace drogon_ctl
|
namespace drogon_ctl
|
||||||
{
|
{
|
||||||
class help : public DrObject<help>, public CommandHandler
|
class help : public DrObject<help>, public CommandHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void handleCommand(std::vector<std::string> ¶meters) override;
|
void handleCommand(std::vector<std::string> ¶meters) override;
|
||||||
virtual std::string script() override
|
|
||||||
|
std::string script() override
|
||||||
{
|
{
|
||||||
return "display this message";
|
return "display this message";
|
||||||
}
|
}
|
||||||
virtual bool isTopCommand() override
|
|
||||||
|
bool isTopCommand() override
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -18,12 +18,17 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <stdlib.h>
|
#include <cstdlib>
|
||||||
|
#include <json/json.h>
|
||||||
|
#include <fstream>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using namespace drogon_ctl;
|
using namespace drogon_ctl;
|
||||||
|
|
||||||
std::string press::detail()
|
std::string press::detail()
|
||||||
{
|
{
|
||||||
return "Use press command to do stress testing\n"
|
return "Use press command to do stress testing\n"
|
||||||
@ -31,17 +36,19 @@ std::string press::detail()
|
|||||||
" -n num number of requests(default : 1)\n"
|
" -n num number of requests(default : 1)\n"
|
||||||
" -t num number of threads(default : 1)\n"
|
" -t num number of threads(default : 1)\n"
|
||||||
" -c num concurrent connections(default : 1)\n"
|
" -c num concurrent connections(default : 1)\n"
|
||||||
// " -k keep alive(default: no)\n"
|
" -k disable SSL certificate validation(default: enable)\n"
|
||||||
" -q no progress indication(default: no)\n\n"
|
" -f customize http request json file(default: disenable)\n"
|
||||||
|
" -q no progress indication(default: show)\n\n"
|
||||||
"example: drogon_ctl press -n 10000 -c 100 -t 4 -q "
|
"example: drogon_ctl press -n 10000 -c 100 -t 4 -q "
|
||||||
"http://localhost:8080/index.html\n";
|
"http://localhost:8080/index.html -f ./http_request.json\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void outputErrorAndExit(const string_view &err)
|
void outputErrorAndExit(const std::string_view &err)
|
||||||
{
|
{
|
||||||
std::cout << err << std::endl;
|
std::cout << err << std::endl;
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void press::handleCommand(std::vector<std::string> ¶meters)
|
void press::handleCommand(std::vector<std::string> ¶meters)
|
||||||
{
|
{
|
||||||
for (auto iter = parameters.begin(); iter != parameters.end(); iter++)
|
for (auto iter = parameters.begin(); iter != parameters.end(); iter++)
|
||||||
@ -149,11 +156,29 @@ void press::handleCommand(std::vector<std::string> ¶meters)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// else if (param == "-k")
|
else if (param.find("-f") == 0)
|
||||||
// {
|
{
|
||||||
// keepAlive_ = true;
|
if (param == "-f")
|
||||||
// continue;
|
{
|
||||||
// }
|
++iter;
|
||||||
|
if (iter == parameters.end())
|
||||||
|
{
|
||||||
|
outputErrorAndExit("No http request json file!");
|
||||||
|
}
|
||||||
|
httpRequestJsonFile_ = *iter;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
httpRequestJsonFile_ = param.substr(2);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (param == "-k")
|
||||||
|
{
|
||||||
|
certValidation_ = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
else if (param == "-q")
|
else if (param == "-q")
|
||||||
{
|
{
|
||||||
processIndication_ = false;
|
processIndication_ = false;
|
||||||
@ -176,7 +201,7 @@ void press::handleCommand(std::vector<std::string> ¶meters)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto pos = url_.find("://");
|
auto pos = url_.find("://");
|
||||||
auto posOfPath = url_.find("/", pos + 3);
|
auto posOfPath = url_.find('/', pos + 3);
|
||||||
if (posOfPath == std::string::npos)
|
if (posOfPath == std::string::npos)
|
||||||
{
|
{
|
||||||
host_ = url_;
|
host_ = url_;
|
||||||
@ -188,6 +213,118 @@ void press::handleCommand(std::vector<std::string> ¶meters)
|
|||||||
path_ = url_.substr(posOfPath);
|
path_ = url_.substr(posOfPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
http_request.json
|
||||||
|
{
|
||||||
|
"method": "POST",
|
||||||
|
"header": {
|
||||||
|
"token": "e2e9d0fe-dd14-4eaf-8ac1-0997730a805d"
|
||||||
|
},
|
||||||
|
"body": {
|
||||||
|
"passwd": "123456",
|
||||||
|
"account": "10001"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
if (!httpRequestJsonFile_.empty())
|
||||||
|
{
|
||||||
|
Json::Value httpRequestJson;
|
||||||
|
std::ifstream httpRequestFile(httpRequestJsonFile_,
|
||||||
|
std::ifstream::binary);
|
||||||
|
if (!httpRequestFile.is_open())
|
||||||
|
{
|
||||||
|
outputErrorAndExit(std::string{"No "} + httpRequestJsonFile_);
|
||||||
|
}
|
||||||
|
httpRequestFile >> httpRequestJson;
|
||||||
|
|
||||||
|
if (!httpRequestJson.isMember("method"))
|
||||||
|
{
|
||||||
|
outputErrorAndExit("No contain method");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto methodStr = httpRequestJson["method"].asString();
|
||||||
|
std::transform(methodStr.begin(),
|
||||||
|
methodStr.end(),
|
||||||
|
methodStr.begin(),
|
||||||
|
::toupper);
|
||||||
|
|
||||||
|
auto toHttpMethod = [&]() -> drogon::HttpMethod {
|
||||||
|
if (methodStr == "GET")
|
||||||
|
{
|
||||||
|
return drogon::HttpMethod::Get;
|
||||||
|
}
|
||||||
|
else if (methodStr == "POST")
|
||||||
|
{
|
||||||
|
return drogon::HttpMethod::Post;
|
||||||
|
}
|
||||||
|
else if (methodStr == "HEAD")
|
||||||
|
{
|
||||||
|
return drogon::HttpMethod::Head;
|
||||||
|
}
|
||||||
|
else if (methodStr == "PUT")
|
||||||
|
{
|
||||||
|
return drogon::HttpMethod::Put;
|
||||||
|
}
|
||||||
|
else if (methodStr == "DELETE")
|
||||||
|
{
|
||||||
|
return drogon::HttpMethod::Delete;
|
||||||
|
}
|
||||||
|
else if (methodStr == "OPTIONS")
|
||||||
|
{
|
||||||
|
return drogon::HttpMethod::Options;
|
||||||
|
}
|
||||||
|
else if (methodStr == "PATCH")
|
||||||
|
{
|
||||||
|
return drogon::HttpMethod::Patch;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
outputErrorAndExit("invalid method");
|
||||||
|
}
|
||||||
|
return drogon::HttpMethod::Get;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::unordered_map<std::string, std::string> header;
|
||||||
|
if (httpRequestJson.isMember("header"))
|
||||||
|
{
|
||||||
|
auto &jsonValue = httpRequestJson["header"];
|
||||||
|
for (const auto &key : jsonValue.getMemberNames())
|
||||||
|
{
|
||||||
|
if (jsonValue[key].isString())
|
||||||
|
{
|
||||||
|
header[key] = jsonValue[key].asString();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
header[key] = jsonValue[key].toStyledString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string body;
|
||||||
|
if (httpRequestJson.isMember("body"))
|
||||||
|
{
|
||||||
|
Json::FastWriter fastWriter;
|
||||||
|
body = fastWriter.write(httpRequestJson["body"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
createHttpRequestFunc_ = [this,
|
||||||
|
method = toHttpMethod(),
|
||||||
|
body = std::move(body),
|
||||||
|
header =
|
||||||
|
std::move(header)]() -> HttpRequestPtr {
|
||||||
|
auto request = HttpRequest::newHttpRequest();
|
||||||
|
request->setPath(path_);
|
||||||
|
request->setMethod(method);
|
||||||
|
for (const auto &[field, val] : header)
|
||||||
|
request->addHeader(field, val);
|
||||||
|
if (!body.empty())
|
||||||
|
request->setBody(body);
|
||||||
|
return request;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// std::cout << "host=" << host_ << std::endl;
|
// std::cout << "host=" << host_ << std::endl;
|
||||||
// std::cout << "path=" << path_ << std::endl;
|
// std::cout << "path=" << path_ << std::endl;
|
||||||
doTesting();
|
doTesting();
|
||||||
@ -214,8 +351,10 @@ void press::createRequestAndClients()
|
|||||||
loopPool_->start();
|
loopPool_->start();
|
||||||
for (size_t i = 0; i < numOfConnections_; ++i)
|
for (size_t i = 0; i < numOfConnections_; ++i)
|
||||||
{
|
{
|
||||||
auto client =
|
auto client = HttpClient::newHttpClient(host_,
|
||||||
HttpClient::newHttpClient(host_, loopPool_->getNextLoop());
|
loopPool_->getNextLoop(),
|
||||||
|
false,
|
||||||
|
certValidation_);
|
||||||
client->enableCookies();
|
client->enableCookies();
|
||||||
clients_.push_back(client);
|
clients_.push_back(client);
|
||||||
}
|
}
|
||||||
@ -228,9 +367,19 @@ void press::sendRequest(const HttpClientPtr &client)
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto request = HttpRequest::newHttpRequest();
|
|
||||||
request->setPath(path_);
|
HttpRequestPtr request;
|
||||||
request->setMethod(Get);
|
if (createHttpRequestFunc_)
|
||||||
|
{
|
||||||
|
request = createHttpRequestFunc_();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
request = HttpRequest::newHttpRequest();
|
||||||
|
request->setPath(path_);
|
||||||
|
request->setMethod(Get);
|
||||||
|
}
|
||||||
|
|
||||||
// std::cout << "send!" << std::endl;
|
// std::cout << "send!" << std::endl;
|
||||||
client->sendRequest(
|
client->sendRequest(
|
||||||
request,
|
request,
|
||||||
@ -282,7 +431,6 @@ void press::sendRequest(const HttpClientPtr &client)
|
|||||||
|
|
||||||
void press::outputResults()
|
void press::outputResults()
|
||||||
{
|
{
|
||||||
static std::mutex mtx;
|
|
||||||
size_t totalSent = 0;
|
size_t totalSent = 0;
|
||||||
size_t totalRecv = 0;
|
size_t totalRecv = 0;
|
||||||
for (auto &client : clients_)
|
for (auto &client : clients_)
|
||||||
@ -294,7 +442,7 @@ void press::outputResults()
|
|||||||
auto microSecs = now.microSecondsSinceEpoch() -
|
auto microSecs = now.microSecondsSinceEpoch() -
|
||||||
statistics_.startDate_.microSecondsSinceEpoch();
|
statistics_.startDate_.microSecondsSinceEpoch();
|
||||||
double seconds = (double)microSecs / 1000000.0;
|
double seconds = (double)microSecs / 1000000.0;
|
||||||
size_t rps = static_cast<size_t>(statistics_.numOfGoodResponse_ / seconds);
|
auto rps = static_cast<size_t>(statistics_.numOfGoodResponse_ / seconds);
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
std::cout << "TOTALS: " << numOfConnections_ << " connect, "
|
std::cout << "TOTALS: " << numOfConnections_ << " connect, "
|
||||||
<< numOfRequests_ << " requests, "
|
<< numOfRequests_ << " requests, "
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include <drogon/HttpClient.h>
|
#include <drogon/HttpClient.h>
|
||||||
#include <trantor/utils/Date.h>
|
#include <trantor/utils/Date.h>
|
||||||
#include <trantor/net/EventLoopThreadPool.h>
|
#include <trantor/net/EventLoopThreadPool.h>
|
||||||
|
#include <functional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -39,26 +40,32 @@ struct Statistics
|
|||||||
trantor::Date startDate_;
|
trantor::Date startDate_;
|
||||||
trantor::Date endDate_;
|
trantor::Date endDate_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class press : public DrObject<press>, public CommandHandler
|
class press : public DrObject<press>, public CommandHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void handleCommand(std::vector<std::string> ¶meters) override;
|
void handleCommand(std::vector<std::string> ¶meters) override;
|
||||||
virtual std::string script() override
|
|
||||||
|
std::string script() override
|
||||||
{
|
{
|
||||||
return "Do stress testing(Use 'drogon_ctl help press' for more "
|
return "Do stress testing(Use 'drogon_ctl help press' for more "
|
||||||
"information)";
|
"information)";
|
||||||
}
|
}
|
||||||
virtual bool isTopCommand() override
|
|
||||||
|
bool isTopCommand() override
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
virtual std::string detail() override;
|
|
||||||
|
std::string detail() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
size_t numOfThreads_{1};
|
size_t numOfThreads_{1};
|
||||||
size_t numOfRequests_{1};
|
size_t numOfRequests_{1};
|
||||||
size_t numOfConnections_{1};
|
size_t numOfConnections_{1};
|
||||||
// bool keepAlive_ = false;
|
std::string httpRequestJsonFile_;
|
||||||
|
std::function<HttpRequestPtr()> createHttpRequestFunc_;
|
||||||
|
bool certValidation_{true};
|
||||||
bool processIndication_{true};
|
bool processIndication_{true};
|
||||||
std::string url_;
|
std::string url_;
|
||||||
std::string host_;
|
std::string host_;
|
||||||
|
@ -34,10 +34,7 @@ target_link_libraries(${PROJECT_NAME} PRIVATE Drogon::Drogon)
|
|||||||
# ##############################################################################
|
# ##############################################################################
|
||||||
|
|
||||||
if (CMAKE_CXX_STANDARD LESS 17)
|
if (CMAKE_CXX_STANDARD LESS 17)
|
||||||
# With C++14, use boost to support any, string_view and filesystem
|
message(FATAL_ERROR "c++17 or higher is required")
|
||||||
message(STATUS "use c++14")
|
|
||||||
find_package(Boost 1.61.0 REQUIRED)
|
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC Boost::boost)
|
|
||||||
elseif (CMAKE_CXX_STANDARD LESS 20)
|
elseif (CMAKE_CXX_STANDARD LESS 20)
|
||||||
message(STATUS "use c++17")
|
message(STATUS "use c++17")
|
||||||
else ()
|
else ()
|
||||||
@ -54,6 +51,10 @@ drogon_create_views(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/views
|
|||||||
# use the following line to create views with namespaces.
|
# use the following line to create views with namespaces.
|
||||||
# drogon_create_views(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/views
|
# drogon_create_views(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/views
|
||||||
# ${CMAKE_CURRENT_BINARY_DIR} TRUE)
|
# ${CMAKE_CURRENT_BINARY_DIR} TRUE)
|
||||||
|
# use the following line to create views with namespace CHANGE_ME prefixed
|
||||||
|
# and path namespaces.
|
||||||
|
# drogon_create_views(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/views
|
||||||
|
# ${CMAKE_CURRENT_BINARY_DIR} TRUE CHANGE_ME)
|
||||||
|
|
||||||
target_include_directories(${PROJECT_NAME}
|
target_include_directories(${PROJECT_NAME}
|
||||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
|
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
350
drogon_ctl/templates/config_json.csp
Normal file
350
drogon_ctl/templates/config_json.csp
Normal file
@ -0,0 +1,350 @@
|
|||||||
|
/* This is a JSON format configuration file
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
//ssl:The global SSL settings. "key" and "cert" are the path to the SSL key and certificate. While
|
||||||
|
// "conf" is an array of 1 or 2-element tuples that supplies file style options for `SSL_CONF_cmd`.
|
||||||
|
"ssl": {
|
||||||
|
"cert": "../../trantor/trantor/tests/server.crt",
|
||||||
|
"key": "../../trantor/trantor/tests/server.key",
|
||||||
|
"conf": [
|
||||||
|
//["Options", "-SessionTicket"],
|
||||||
|
//["Options", "Compression"]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"listeners": [
|
||||||
|
{
|
||||||
|
//address: Ip address,0.0.0.0 by default
|
||||||
|
"address": "0.0.0.0",
|
||||||
|
//port: Port number
|
||||||
|
"port": 80,
|
||||||
|
//https: If true, use https for security,false by default
|
||||||
|
"https": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "0.0.0.0",
|
||||||
|
"port": 443,
|
||||||
|
"https": true,
|
||||||
|
//cert,key: Cert file path and key file path, empty by default,
|
||||||
|
//if empty, use the global setting
|
||||||
|
"cert": "",
|
||||||
|
"key": "",
|
||||||
|
//use_old_tls: enable the TLS1.0/1.1, false by default
|
||||||
|
"use_old_tls": false,
|
||||||
|
"ssl_conf": [
|
||||||
|
//["MinProtocol", "TLSv1.3"]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"db_clients": [
|
||||||
|
{
|
||||||
|
//name: Name of the client,'default' by default
|
||||||
|
"name": "default",
|
||||||
|
//rdbms: Server type, postgresql,mysql or sqlite3, "postgresql" by default
|
||||||
|
"rdbms": "postgresql",
|
||||||
|
//filename: Sqlite3 db file name
|
||||||
|
//"filename":"",
|
||||||
|
//host: Server address,localhost by default
|
||||||
|
"host": "127.0.0.1",
|
||||||
|
//port: Server port, 5432 by default
|
||||||
|
"port": 5432,
|
||||||
|
//dbname: Database name
|
||||||
|
"dbname": "test",
|
||||||
|
//user: 'postgres' by default
|
||||||
|
"user": "",
|
||||||
|
//passwd: '' by default
|
||||||
|
"passwd": "",
|
||||||
|
//is_fast: false by default, if it is true, the client is faster but user can't call
|
||||||
|
//any synchronous interface of it.
|
||||||
|
"is_fast": false,
|
||||||
|
//client_encoding: The character set used by the client. it is empty string by default which
|
||||||
|
//means use the default character set.
|
||||||
|
//"client_encoding": "",
|
||||||
|
//number_of_connections: 1 by default, if the 'is_fast' is true, the number is the number of
|
||||||
|
//connections per IO thread, otherwise it is the total number of all connections.
|
||||||
|
"number_of_connections": 1,
|
||||||
|
//timeout: -1.0 by default, in seconds, the timeout for executing a SQL query.
|
||||||
|
//zero or negative value means no timeout.
|
||||||
|
"timeout": -1.0,
|
||||||
|
//auto_batch: this feature is only available for the PostgreSQL driver(version >= 14.0), see
|
||||||
|
//the wiki for more details.
|
||||||
|
"auto_batch": false
|
||||||
|
//connect_options: extra options for the connection. Only works for PostgreSQL now.
|
||||||
|
//For more information, see https://www.postgresql.org/docs/16/libpq-connect.html#LIBPQ-CONNECT-OPTIONS
|
||||||
|
//"connect_options": { "statement_timeout": "1s" }
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"redis_clients": [
|
||||||
|
{
|
||||||
|
//name: Name of the client,'default' by default
|
||||||
|
"name": "default",
|
||||||
|
//host: Server IP, 127.0.0.1 by default
|
||||||
|
"host": "127.0.0.1",
|
||||||
|
//port: Server port, 6379 by default
|
||||||
|
"port": 6379,
|
||||||
|
//username: '' by default which means 'default' in redis ACL
|
||||||
|
"username": "",
|
||||||
|
//passwd: '' by default
|
||||||
|
"passwd": "",
|
||||||
|
//db index: 0 by default
|
||||||
|
"db": 0,
|
||||||
|
//is_fast: false by default, if it is true, the client is faster but user can't call
|
||||||
|
//any synchronous interface of it.
|
||||||
|
"is_fast": false,
|
||||||
|
//number_of_connections: 1 by default, if the 'is_fast' is true, the number is the number of
|
||||||
|
//connections per IO thread, otherwise it is the total number of all connections.
|
||||||
|
"number_of_connections": 1,
|
||||||
|
//timeout: -1.0 by default, in seconds, the timeout for executing a command.
|
||||||
|
//zero or negative value means no timeout.
|
||||||
|
"timeout": -1.0
|
||||||
|
}
|
||||||
|
],*/
|
||||||
|
"app": {
|
||||||
|
//number_of_threads: The number of IO threads, 1 by default, if the value is set to 0, the number of threads
|
||||||
|
//is the number of CPU cores
|
||||||
|
"number_of_threads": 1,
|
||||||
|
//enable_session: False by default
|
||||||
|
"enable_session": false,
|
||||||
|
"session_timeout": 0,
|
||||||
|
//string value of SameSite attribute of the Set-Cookie HTTP response header
|
||||||
|
//valid value is either 'Null' (default), 'Lax', 'Strict' or 'None'
|
||||||
|
"session_same_site" : "Null",
|
||||||
|
//session_cookie_key: The cookie key of the session, "JSESSIONID" by default
|
||||||
|
"session_cookie_key": "JSESSIONID",
|
||||||
|
//session_max_age: The max age of the session cookie, -1 by default
|
||||||
|
"session_max_age": -1,
|
||||||
|
//document_root: Root path of HTTP document, default path is ./
|
||||||
|
"document_root": "./",
|
||||||
|
//home_page: Set the HTML file of the home page, the default value is "index.html"
|
||||||
|
//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
|
||||||
|
//to the request for "/".
|
||||||
|
"home_page": "index.html",
|
||||||
|
//use_implicit_page: enable implicit pages if true, true by default
|
||||||
|
"use_implicit_page": true,
|
||||||
|
//implicit_page: Set the file which would the server access in a directory that a user accessed.
|
||||||
|
//For example, by default, http://localhost/a-directory resolves to http://localhost/a-directory/index.html.
|
||||||
|
"implicit_page": "index.html",
|
||||||
|
//static_file_headers: Headers for static files
|
||||||
|
/*"static_file_headers": [
|
||||||
|
{
|
||||||
|
"name": "field-name",
|
||||||
|
"value": "field-value"
|
||||||
|
}
|
||||||
|
],*/
|
||||||
|
//upload_path: The path to save the uploaded file. "uploads" by default.
|
||||||
|
//If the path isn't prefixed with /, ./ or ../,
|
||||||
|
//it is relative path of document_root path
|
||||||
|
"upload_path": "uploads",
|
||||||
|
/* file_types:
|
||||||
|
* HTTP download file types,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", etc. */
|
||||||
|
"file_types": [
|
||||||
|
"gif",
|
||||||
|
"png",
|
||||||
|
"jpg",
|
||||||
|
"js",
|
||||||
|
"css",
|
||||||
|
"html",
|
||||||
|
"ico",
|
||||||
|
"swf",
|
||||||
|
"xap",
|
||||||
|
"apk",
|
||||||
|
"cur",
|
||||||
|
"xml",
|
||||||
|
"webp",
|
||||||
|
"svg"
|
||||||
|
],
|
||||||
|
// mime: A dictionary that extends the internal MIME type support. Maps extensions into new MIME types
|
||||||
|
// note: This option only adds MIME to the sever. `file_types` above have to be set for the server to serve them.
|
||||||
|
"mime": {
|
||||||
|
// "text/markdown": "md",
|
||||||
|
// "text/gemini": ["gmi", "gemini"]
|
||||||
|
},
|
||||||
|
//locations: An array of locations of static files for GET requests.
|
||||||
|
"locations": [
|
||||||
|
{
|
||||||
|
//uri_prefix: The URI prefix of the location prefixed with "/", the default value is "" that disables the location.
|
||||||
|
//"uri_prefix": "/.well-known/acme-challenge/",
|
||||||
|
//default_content_type: The default content type of the static files without
|
||||||
|
//an extension. empty string by default.
|
||||||
|
"default_content_type": "text/plain",
|
||||||
|
//alias: The location in file system, if it is prefixed with "/", it
|
||||||
|
//presents an absolute path, otherwise it presents a relative path to
|
||||||
|
//the document_root path.
|
||||||
|
//The default value is "" which means use the document root path as the location base path.
|
||||||
|
"alias": "",
|
||||||
|
//is_case_sensitive: indicates whether the URI prefix is case sensitive.
|
||||||
|
"is_case_sensitive": false,
|
||||||
|
//allow_all: true by default. If it is set to false, only static files with a valid extension can be accessed.
|
||||||
|
"allow_all": true,
|
||||||
|
//is_recursive: true by default. If it is set to false, files in sub directories can't be accessed.
|
||||||
|
"is_recursive": true,
|
||||||
|
//filters: string array, the filters applied to the location.
|
||||||
|
"filters": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
//max_connections: maximum number of connections, 100000 by default
|
||||||
|
"max_connections": 100000,
|
||||||
|
//max_connections_per_ip: maximum number of connections per client, 0 by default which means no limit
|
||||||
|
"max_connections_per_ip": 0,
|
||||||
|
//Load_dynamic_views: False by default, when set to true, drogon
|
||||||
|
//compiles and loads dynamically "CSP View Files" in directories defined
|
||||||
|
//by "dynamic_views_path"
|
||||||
|
"load_dynamic_views": false,
|
||||||
|
//dynamic_views_path: If the path isn't prefixed with /, ./ or ../,
|
||||||
|
//it is relative path of document_root path
|
||||||
|
"dynamic_views_path": [
|
||||||
|
"./views"
|
||||||
|
],
|
||||||
|
//dynamic_views_output_path: Default by an empty string which means the output path of source
|
||||||
|
//files is the path where the csp files locate. If the path isn't prefixed with /, it is relative
|
||||||
|
//path of the current working directory.
|
||||||
|
"dynamic_views_output_path": "",
|
||||||
|
//json_parser_stack_limit: 1000 by default, the maximum number of stack depth when reading a json string by the jsoncpp library.
|
||||||
|
"json_parser_stack_limit": 1000,
|
||||||
|
//enable_unicode_escaping_in_json: true by default, enable unicode escaping in json.
|
||||||
|
"enable_unicode_escaping_in_json": true,
|
||||||
|
//float_precision_in_json: set precision of float number in json.
|
||||||
|
"float_precision_in_json": {
|
||||||
|
//precision: 0 by default, 0 means use the default precision of the jsoncpp lib.
|
||||||
|
"precision": 0,
|
||||||
|
//precision_type: must be "significant" or "decimal", defaults to "significant" that means
|
||||||
|
//setting max number of significant digits in string, "decimal" means setting max number of
|
||||||
|
//digits after "." in string
|
||||||
|
"precision_type": "significant"
|
||||||
|
},
|
||||||
|
//log: Set log output, drogon output logs to stdout by default
|
||||||
|
"log": {
|
||||||
|
//use_spdlog: Use spdlog library to log
|
||||||
|
"use_spdlog": false,
|
||||||
|
//log_path: Log file path,empty by default,in which case,logs are output to the stdout
|
||||||
|
//"log_path": "./",
|
||||||
|
//logfile_base_name: Log file base name,empty by default which means drogon names logfile as
|
||||||
|
//drogon.log ...
|
||||||
|
"logfile_base_name": "",
|
||||||
|
//log_size_limit: 100000000 bytes by default,
|
||||||
|
//When the log file size reaches "log_size_limit", the log file is switched.
|
||||||
|
"log_size_limit": 100000000,
|
||||||
|
//max_files: 0 by default,
|
||||||
|
//When the number of old log files exceeds "max_files", the oldest file will be deleted. 0 means never delete.
|
||||||
|
"max_files": 0,
|
||||||
|
//log_level: "DEBUG" by default,options:"TRACE","DEBUG","INFO","WARN"
|
||||||
|
//The TRACE level is only valid when built in DEBUG mode.
|
||||||
|
"log_level": "DEBUG",
|
||||||
|
//display_local_time: false by default, if true, the log time is displayed in local time
|
||||||
|
"display_local_time": false
|
||||||
|
},
|
||||||
|
//run_as_daemon: False by default
|
||||||
|
"run_as_daemon": false,
|
||||||
|
//handle_sig_term: True by default
|
||||||
|
"handle_sig_term": true,
|
||||||
|
//relaunch_on_error: False by default, if true, the program will be restart by the parent after exiting;
|
||||||
|
"relaunch_on_error": false,
|
||||||
|
//use_sendfile: True by default, if true, the program
|
||||||
|
//uses sendfile() system-call to send static files to clients;
|
||||||
|
"use_sendfile": true,
|
||||||
|
//use_gzip: True by default, use gzip to compress the response body's content;
|
||||||
|
"use_gzip": true,
|
||||||
|
//use_brotli: False by default, use brotli to compress the response body's content;
|
||||||
|
"use_brotli": false,
|
||||||
|
//static_files_cache_time: 5 (seconds) by default, the time in which the static file response is cached,
|
||||||
|
//0 means cache forever, the negative value means no cache
|
||||||
|
"static_files_cache_time": 5,
|
||||||
|
//simple_controllers_map: Used to configure mapping from path to simple controller
|
||||||
|
//"simple_controllers_map": [
|
||||||
|
// {
|
||||||
|
// "path": "/path/name",
|
||||||
|
// "controller": "controllerClassName",
|
||||||
|
// "http_methods": [
|
||||||
|
// "get",
|
||||||
|
// "post"
|
||||||
|
// ],
|
||||||
|
// "filters": [
|
||||||
|
// "FilterClassName"
|
||||||
|
// ]
|
||||||
|
// }
|
||||||
|
//],
|
||||||
|
//idle_connection_timeout: Defaults to 60 seconds, the lifetime
|
||||||
|
//of the connection without read or write
|
||||||
|
"idle_connection_timeout": 60,
|
||||||
|
//server_header_field: Set the 'Server' header field in each response sent by drogon,
|
||||||
|
//empty string by default with which the 'Server' header field is set to "Server: drogon/version string\r\n"
|
||||||
|
"server_header_field": "",
|
||||||
|
//enable_server_header: Set true to force drogon to add a 'Server' header to each HTTP response. The default
|
||||||
|
//value is true.
|
||||||
|
"enable_server_header": true,
|
||||||
|
//enable_date_header: Set true to force drogon to add a 'Date' header to each HTTP response. The default
|
||||||
|
//value is true.
|
||||||
|
"enable_date_header": true,
|
||||||
|
//keepalive_requests: Set the maximum number of requests that can be served through one keep-alive connection.
|
||||||
|
//After the maximum number of requests are made, the connection is closed.
|
||||||
|
//The default value of 0 means no limit.
|
||||||
|
"keepalive_requests": 0,
|
||||||
|
//pipelining_requests: Set the maximum number of unhandled requests that can be cached in pipelining buffer.
|
||||||
|
//After the maximum number of requests are made, the connection is closed.
|
||||||
|
//The default value of 0 means no limit.
|
||||||
|
"pipelining_requests": 0,
|
||||||
|
//gzip_static: If it is set to true, when the client requests a static file, drogon first finds the compressed
|
||||||
|
//file with the extension ".gz" in the same path and send the compressed file to the client.
|
||||||
|
//The default value of gzip_static is true.
|
||||||
|
"gzip_static": true,
|
||||||
|
//br_static: If it is set to true, when the client requests a static file, drogon first finds the compressed
|
||||||
|
//file with the extension ".br" in the same path and send the compressed file to the client.
|
||||||
|
//The default value of br_static is true.
|
||||||
|
"br_static": true,
|
||||||
|
//client_max_body_size: Set the maximum body size of HTTP requests received by drogon. The default value is "1M".
|
||||||
|
//One can set it to "1024", "1k", "10M", "1G", etc. Setting it to "" means no limit.
|
||||||
|
"client_max_body_size": "1M",
|
||||||
|
//max_memory_body_size: Set the maximum body size in memory of HTTP requests received by drogon. The default value is "64K" bytes.
|
||||||
|
//If the body size of a HTTP request exceeds this limit, the body is stored to a temporary file for processing.
|
||||||
|
//Setting it to "" means no limit.
|
||||||
|
"client_max_memory_body_size": "64K",
|
||||||
|
//client_max_websocket_message_size: Set the maximum size of messages sent by WebSocket client. The default value is "128K".
|
||||||
|
//One can set it to "1024", "1k", "10M", "1G", etc. Setting it to "" means no limit.
|
||||||
|
"client_max_websocket_message_size": "128K",
|
||||||
|
//reuse_port: Defaults to false, users can run multiple processes listening on the same port at the same time.
|
||||||
|
"reuse_port": false,
|
||||||
|
// enabled_compressed_request: Defaults to false. If true the server will automatically decompress compressed request bodies.
|
||||||
|
// Currently only gzip and br are supported. Note: max_memory_body_size and max_body_size applies twice for compressed requests.
|
||||||
|
// Once when receiving and once when decompressing. i.e. if the decompressed body is larger than max_body_size, the request
|
||||||
|
// will be rejected.
|
||||||
|
"enabled_compressed_request": false,
|
||||||
|
// enable_request_stream: Defaults to false. If true the server will enable stream mode for http requests.
|
||||||
|
// See the wiki for more details.
|
||||||
|
"enable_request_stream": false,
|
||||||
|
},
|
||||||
|
//plugins: Define all plugins running in the application
|
||||||
|
"plugins": [
|
||||||
|
{
|
||||||
|
//name: The class name of the plugin
|
||||||
|
"name": "drogon::plugin::PromExporter",
|
||||||
|
//dependencies: Plugins that the plugin depends on. It can be commented out
|
||||||
|
"dependencies": [],
|
||||||
|
//config: The configuration of the plugin. This json object is the parameter to initialize the plugin.
|
||||||
|
//It can be commented out
|
||||||
|
"config": {
|
||||||
|
"path": "/metrics"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "drogon::plugin::AccessLogger",
|
||||||
|
"dependencies": [],
|
||||||
|
"config": {
|
||||||
|
"use_spdlog": false,
|
||||||
|
"log_path": "",
|
||||||
|
"log_format": "",
|
||||||
|
"log_file": "access.log",
|
||||||
|
"log_size_limit": 0,
|
||||||
|
"use_local_time": true,
|
||||||
|
"log_index": 0,
|
||||||
|
// "show_microseconds": true,
|
||||||
|
// "custom_time_format": "",
|
||||||
|
// "use_real_ip": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
//custom_config: custom configuration for users. This object can be get by the app().getCustomConfig() method.
|
||||||
|
"custom_config": {}
|
||||||
|
}
|
313
drogon_ctl/templates/config_yaml.csp
Normal file
313
drogon_ctl/templates/config_yaml.csp
Normal file
@ -0,0 +1,313 @@
|
|||||||
|
# This is a YAML format configuration file
|
||||||
|
|
||||||
|
# ssl:The global SSL settings. "key" and "cert" are the path to the SSL key and certificate. While
|
||||||
|
# "conf" is an array of 1 or 2-element tuples that supplies file style options for `SSL_CONF_cmd`.
|
||||||
|
# ssl:
|
||||||
|
# cert: ../../trantor/trantor/tests/server.crt
|
||||||
|
# key: ../../trantor/trantor/tests/server.key
|
||||||
|
# conf: [
|
||||||
|
# # [Options, -SessionTicket],
|
||||||
|
# # [Options, Compression]
|
||||||
|
# ]
|
||||||
|
# listeners:
|
||||||
|
# # address: Ip address,0.0.0.0 by default
|
||||||
|
# - address: 0.0.0.0
|
||||||
|
# # port: Port number
|
||||||
|
# port: 80
|
||||||
|
# # https: If true, use https for security,false by default
|
||||||
|
# https: false
|
||||||
|
# - address: 0.0.0.0
|
||||||
|
# port: 443
|
||||||
|
# https: true
|
||||||
|
# # cert,key: Cert file path and key file path, empty by default,
|
||||||
|
# # if empty, use the global setting
|
||||||
|
# cert: ''
|
||||||
|
# key: ''
|
||||||
|
# # use_old_tls: enable the TLS1.0/1.1, false by default
|
||||||
|
# use_old_tls: false
|
||||||
|
# ssl_conf: [
|
||||||
|
# # [MinProtocol, TLSv1.3]
|
||||||
|
# ]
|
||||||
|
# db_clients:
|
||||||
|
# # name: Name of the client,'default' by default
|
||||||
|
# - name: default
|
||||||
|
# # rdbms: Server type, postgresql,mysql or sqlite3, "postgresql" by default
|
||||||
|
# rdbms: postgresql
|
||||||
|
# # filename: Sqlite3 db file name
|
||||||
|
# # filename: ''
|
||||||
|
# # host: Server address,localhost by default
|
||||||
|
# host: 127.0.0.1
|
||||||
|
# # port: Server port, 5432 by default
|
||||||
|
# port: 5432
|
||||||
|
# # dbname: Database name
|
||||||
|
# dbname: test
|
||||||
|
# # user: 'postgres' by default
|
||||||
|
# user: ''
|
||||||
|
# # passwd: '' by default
|
||||||
|
# passwd: ''
|
||||||
|
# # is_fast: false by default, if it is true, the client is faster but user can't call
|
||||||
|
# # any synchronous interface of it.
|
||||||
|
# is_fast: false
|
||||||
|
# # client_encoding: The character set used by the client. it is empty string by default which
|
||||||
|
# # means use the default character set.
|
||||||
|
# # client_encoding: ''
|
||||||
|
# # number_of_connections: 1 by default, if the 'is_fast' is true, the number is the number of
|
||||||
|
# # connections per IO thread, otherwise it is the total number of all connections.
|
||||||
|
# number_of_connections: 1
|
||||||
|
# # timeout: -1 by default, in seconds, the timeout for executing a SQL query.
|
||||||
|
# # zero or negative value means no timeout.
|
||||||
|
# timeout: -1
|
||||||
|
# # auto_batch: this feature is only available for the PostgreSQL driver(version >= 14.0), see
|
||||||
|
# # the wiki for more details.
|
||||||
|
# auto_batch: false
|
||||||
|
# # connect_options: extra options for the connection. Only works for PostgreSQL now.
|
||||||
|
# # For more information, see https://www.postgresql.org/docs/16/libpq-connect.html#LIBPQ-CONNECT-OPTIONS
|
||||||
|
# # connect_options:
|
||||||
|
# # statement_timeout: '1s'
|
||||||
|
# redis_clients:
|
||||||
|
# # name: Name of the client,'default' by default
|
||||||
|
# - name: default
|
||||||
|
# # host: Server IP, 127.0.0.1 by default
|
||||||
|
# host: 127.0.0.1
|
||||||
|
# # port: Server port, 6379 by default
|
||||||
|
# port: 6379
|
||||||
|
# # username: '' by default which means 'default' in redis ACL
|
||||||
|
# username: ''
|
||||||
|
# # passwd: '' by default
|
||||||
|
# passwd: ''
|
||||||
|
# # db index: 0 by default
|
||||||
|
# db: 0
|
||||||
|
# # is_fast: false by default, if it is true, the client is faster but user can't call
|
||||||
|
# # any synchronous interface of it.
|
||||||
|
# is_fast: false
|
||||||
|
# # number_of_connections: 1 by default, if the 'is_fast' is true, the number is the number of
|
||||||
|
# # connections per IO thread, otherwise it is the total number of all connections.
|
||||||
|
# number_of_connections: 1
|
||||||
|
# # timeout: -1.0 by default, in seconds, the timeout for executing a command.
|
||||||
|
# # zero or negative value means no timeout.
|
||||||
|
# timeout: -1
|
||||||
|
app:
|
||||||
|
# number_of_threads: The number of IO threads, 1 by default, if the value is set to 0, the number of threads
|
||||||
|
# is the number of CPU cores
|
||||||
|
number_of_threads: 1
|
||||||
|
# enable_session: False by default
|
||||||
|
enable_session: false
|
||||||
|
session_timeout: 0
|
||||||
|
# string value of SameSite attribute of the Set-Cookie HTTP response header
|
||||||
|
# valid value is either 'Null' (default), 'Lax', 'Strict' or 'None'
|
||||||
|
session_same_site: 'Null'
|
||||||
|
# session_cookie_key: The cookie key of the session, "JSESSIONID" by default
|
||||||
|
session_cookie_key: 'JSESSIONID'
|
||||||
|
# session_max_age: The max age of the session cookie, -1 by default
|
||||||
|
session_max_age: -1
|
||||||
|
# document_root: Root path of HTTP document, default path is ./
|
||||||
|
document_root: ./
|
||||||
|
# home_page: Set the HTML file of the home page, the default value is "index.html"
|
||||||
|
# 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
|
||||||
|
# to the request for "/".
|
||||||
|
home_page: index.html
|
||||||
|
# use_implicit_page: enable implicit pages if true, true by default
|
||||||
|
use_implicit_page: true
|
||||||
|
# implicit_page: Set the file which would the server access in a directory that a user accessed.
|
||||||
|
# For example, by default, http://localhost/a-directory resolves to http://localhost/a-directory/index.html.
|
||||||
|
implicit_page: index.html
|
||||||
|
# static_file_headers: Headers for static files
|
||||||
|
# static_file_headers:
|
||||||
|
# - name: field-name
|
||||||
|
# value: field-value
|
||||||
|
# upload_path: The path to save the uploaded file. "uploads" by default.
|
||||||
|
# If the path isn't prefixed with /, ./ or ../,
|
||||||
|
# it is relative path of document_root path
|
||||||
|
upload_path: uploads
|
||||||
|
# file_types:
|
||||||
|
# HTTP download file types,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", etc.
|
||||||
|
file_types:
|
||||||
|
- gif
|
||||||
|
- png
|
||||||
|
- jpg
|
||||||
|
- js
|
||||||
|
- css
|
||||||
|
- html
|
||||||
|
- ico
|
||||||
|
- swf
|
||||||
|
- xap
|
||||||
|
- apk
|
||||||
|
- cur
|
||||||
|
- xml
|
||||||
|
# mime: A dictionary that extends the internal MIME type support. Maps extensions into new MIME types
|
||||||
|
# note: This option only adds MIME to the sever. `file_types` above have to be set for the server to serve them.
|
||||||
|
mime: {
|
||||||
|
# text/markdown: md
|
||||||
|
# text/gemini:
|
||||||
|
# - gmi
|
||||||
|
# - gemini
|
||||||
|
}
|
||||||
|
# locations: An array of locations of static files for GET requests.
|
||||||
|
locations:
|
||||||
|
# uri_prefix: The URI prefix of the location prefixed with "/", the default value is "" that disables the location.
|
||||||
|
- uri_prefix: '' # /.well-known/acme-challenge/
|
||||||
|
# default_content_type: The default content type of the static files without
|
||||||
|
# an extension. empty string by default.
|
||||||
|
default_content_type: text/plain
|
||||||
|
# alias: The location in file system, if it is prefixed with "/", it
|
||||||
|
# presents an absolute path, otherwise it presents a relative path to
|
||||||
|
# the document_root path.
|
||||||
|
# The default value is "" which means use the document root path as the location base path.
|
||||||
|
alias: ''
|
||||||
|
# is_case_sensitive: indicates whether the URI prefix is case sensitive.
|
||||||
|
is_case_sensitive: false
|
||||||
|
# allow_all: true by default. If it is set to false, only static files with a valid extension can be accessed.
|
||||||
|
allow_all: true
|
||||||
|
# is_recursive: true by default. If it is set to false, files in sub directories can't be accessed.
|
||||||
|
is_recursive: true
|
||||||
|
# filters: string array, the filters applied to the location.
|
||||||
|
filters: []
|
||||||
|
# max_connections: maximum number of connections, 100000 by default
|
||||||
|
max_connections: 100000
|
||||||
|
# max_connections_per_ip: maximum number of connections per client, 0 by default which means no limit
|
||||||
|
max_connections_per_ip: 0
|
||||||
|
# Load_dynamic_views: False by default, when set to true, drogon
|
||||||
|
# compiles and loads dynamically "CSP View Files" in directories defined
|
||||||
|
# by "dynamic_views_path"
|
||||||
|
load_dynamic_views: false
|
||||||
|
# dynamic_views_path: If the path isn't prefixed with /, ./ or ../,
|
||||||
|
# it is relative path of document_root path
|
||||||
|
dynamic_views_path:
|
||||||
|
- ./views
|
||||||
|
# dynamic_views_output_path: Default by an empty string which means the output path of source
|
||||||
|
# files is the path where the csp files locate. If the path isn't prefixed with /, it is relative
|
||||||
|
# path of the current working directory.
|
||||||
|
dynamic_views_output_path: ''
|
||||||
|
# json_parser_stack_limit: 1000 by default, the maximum number of stack depth when reading a json string by the jsoncpp library.
|
||||||
|
json_parser_stack_limit: 1000
|
||||||
|
# enable_unicode_escaping_in_json: true by default, enable unicode escaping in json.
|
||||||
|
enable_unicode_escaping_in_json: true
|
||||||
|
# float_precision_in_json: set precision of float number in json.
|
||||||
|
float_precision_in_json:
|
||||||
|
# precision: 0 by default, 0 means use the default precision of the jsoncpp lib.
|
||||||
|
precision: 0
|
||||||
|
# precision_type: must be "significant" or "decimal", defaults to "significant" that means
|
||||||
|
# setting max number of significant digits in string, "decimal" means setting max number of
|
||||||
|
# digits after "." in string
|
||||||
|
precision_type: significant
|
||||||
|
# log: Set log output, drogon output logs to stdout by default
|
||||||
|
log:
|
||||||
|
# use_spdlog: Use spdlog library to log
|
||||||
|
use_spdlog: false
|
||||||
|
# log_path: Log file path,empty by default,in which case,logs are output to the stdout
|
||||||
|
# log_path: ./
|
||||||
|
# logfile_base_name: Log file base name,empty by default which means drogon names logfile as
|
||||||
|
# drogon.log ...
|
||||||
|
logfile_base_name: ''
|
||||||
|
# log_size_limit: 100000000 bytes by default,
|
||||||
|
# When the log file size reaches "log_size_limit", the log file is switched.
|
||||||
|
log_size_limit: 100000000
|
||||||
|
# max_files: 0 by default,
|
||||||
|
# When the number of old log files exceeds "max_files", the oldest file will be deleted. 0 means never delete.
|
||||||
|
max_files: 0
|
||||||
|
# log_level: "DEBUG" by default,options:"TRACE","DEBUG","INFO","WARN"
|
||||||
|
# The TRACE level is only valid when built in DEBUG mode.
|
||||||
|
log_level: DEBUG
|
||||||
|
# display_local_time: false by default, if true, the log time is displayed in local time
|
||||||
|
display_local_time: false
|
||||||
|
# run_as_daemon: False by default
|
||||||
|
run_as_daemon: false
|
||||||
|
# handle_sig_term: True by default
|
||||||
|
handle_sig_term: true
|
||||||
|
# relaunch_on_error: False by default, if true, the program will be restart by the parent after exiting;
|
||||||
|
relaunch_on_error: false
|
||||||
|
# use_sendfile: True by default, if true, the program
|
||||||
|
# uses sendfile() system-call to send static files to clients;
|
||||||
|
use_sendfile: true
|
||||||
|
# use_gzip: True by default, use gzip to compress the response body's content;
|
||||||
|
use_gzip: true
|
||||||
|
# use_brotli: False by default, use brotli to compress the response body's content;
|
||||||
|
use_brotli: false
|
||||||
|
# static_files_cache_time: 5 (seconds) by default, the time in which the static file response is cached,
|
||||||
|
# 0 means cache forever, the negative value means no cache
|
||||||
|
static_files_cache_time: 5
|
||||||
|
# simple_controllers_map: Used to configure mapping from path to simple controller
|
||||||
|
# simple_controllers_map:
|
||||||
|
# - path: /path/name
|
||||||
|
# controller: controllerClassName
|
||||||
|
# http_methods:
|
||||||
|
# - get
|
||||||
|
# - post
|
||||||
|
# filters:
|
||||||
|
# - FilterClassName
|
||||||
|
# idle_connection_timeout: Defaults to 60 seconds, the lifetime
|
||||||
|
# of the connection without read or write
|
||||||
|
idle_connection_timeout: 60
|
||||||
|
# server_header_field: Set the 'Server' header field in each response sent by drogon,
|
||||||
|
# empty string by default with which the 'Server' header field is set to "Server: drogon/version string\r\n"
|
||||||
|
server_header_field: ''
|
||||||
|
# enable_server_header: Set true to force drogon to add a 'Server' header to each HTTP response. The default
|
||||||
|
# value is true.
|
||||||
|
enable_server_header: true
|
||||||
|
# enable_date_header: Set true to force drogon to add a 'Date' header to each HTTP response. The default
|
||||||
|
# value is true.
|
||||||
|
enable_date_header: true
|
||||||
|
# keepalive_requests: Set the maximum number of requests that can be served through one keep-alive connection.
|
||||||
|
# After the maximum number of requests are made, the connection is closed.
|
||||||
|
# The default value of 0 means no limit.
|
||||||
|
keepalive_requests: 0
|
||||||
|
# pipelining_requests: Set the maximum number of unhandled requests that can be cached in pipelining buffer.
|
||||||
|
# After the maximum number of requests are made, the connection is closed.
|
||||||
|
# The default value of 0 means no limit.
|
||||||
|
pipelining_requests: 0
|
||||||
|
# gzip_static: If it is set to true, when the client requests a static file, drogon first finds the compressed
|
||||||
|
# file with the extension ".gz" in the same path and send the compressed file to the client.
|
||||||
|
# The default value of gzip_static is true.
|
||||||
|
gzip_static: true
|
||||||
|
# br_static: If it is set to true, when the client requests a static file, drogon first finds the compressed
|
||||||
|
# file with the extension ".br" in the same path and send the compressed file to the client.
|
||||||
|
# The default value of br_static is true.
|
||||||
|
br_static: true
|
||||||
|
# client_max_body_size: Set the maximum body size of HTTP requests received by drogon. The default value is "1M".
|
||||||
|
# One can set it to "1024", "1k", "10M", "1G", etc. Setting it to "" means no limit.
|
||||||
|
client_max_body_size: 1M
|
||||||
|
# max_memory_body_size: Set the maximum body size in memory of HTTP requests received by drogon. The default value is "64K" bytes.
|
||||||
|
# If the body size of a HTTP request exceeds this limit, the body is stored to a temporary file for processing.
|
||||||
|
# Setting it to "" means no limit.
|
||||||
|
client_max_memory_body_size: 64K
|
||||||
|
# client_max_websocket_message_size: Set the maximum size of messages sent by WebSocket client. The default value is "128K".
|
||||||
|
# One can set it to "1024", "1k", "10M", "1G", etc. Setting it to "" means no limit.
|
||||||
|
client_max_websocket_message_size: 128K
|
||||||
|
# reuse_port: Defaults to false, users can run multiple processes listening on the same port at the same time.
|
||||||
|
reuse_port: false
|
||||||
|
# enabled_compressed_request: Defaults to false. If true the server will automatically decompress compressed request bodies.
|
||||||
|
# Currently only gzip and br are supported. Note: max_memory_body_size and max_body_size applies twice for compressed requests.
|
||||||
|
# Once when receiving and once when decompressing. i.e. if the decompressed body is larger than max_body_size, the request
|
||||||
|
# will be rejected.
|
||||||
|
enabled_compressed_request: false
|
||||||
|
# enable_request_stream: Defaults to false. If true the server will enable stream mode for http requests.
|
||||||
|
# See the wiki for more details.
|
||||||
|
enable_request_stream: false
|
||||||
|
# plugins: Define all plugins running in the application
|
||||||
|
plugins:
|
||||||
|
# name: The class name of the plugin
|
||||||
|
- name: drogon::plugin::PromExporter
|
||||||
|
# dependencies: Plugins that the plugin depends on. It can be commented out
|
||||||
|
dependencies: []
|
||||||
|
# config: The configuration of the plugin. This json object is the parameter to initialize the plugin.
|
||||||
|
# It can be commented out
|
||||||
|
config:
|
||||||
|
path: /metrics
|
||||||
|
- name: drogon::plugin::AccessLogger
|
||||||
|
dependencies: []
|
||||||
|
config:
|
||||||
|
use_spdlog: false
|
||||||
|
log_path: ''
|
||||||
|
log_format: ''
|
||||||
|
log_file: access.log
|
||||||
|
log_size_limit: 0
|
||||||
|
use_local_time: true
|
||||||
|
log_index: 0
|
||||||
|
# show_microseconds: true
|
||||||
|
# custom_time_format: ''
|
||||||
|
# use_real_ip: false
|
||||||
|
# custom_config: custom configuration for users. This object can be get by the app().getCustomConfig() method.
|
||||||
|
custom_config: {}
|
@ -1,10 +1,11 @@
|
|||||||
#include <drogon/drogon.h>
|
#include <drogon/drogon.h>
|
||||||
int main() {
|
int main() {
|
||||||
//Set HTTP listener address and port
|
//Set HTTP listener address and port
|
||||||
drogon::app().addListener("0.0.0.0",80);
|
drogon::app().addListener("0.0.0.0", 5555);
|
||||||
//Load config file
|
//Load config file
|
||||||
//drogon::app().loadConfigFile("../config.json");
|
//drogon::app().loadConfigFile("../config.json");
|
||||||
|
//drogon::app().loadConfigFile("../config.yaml");
|
||||||
//Run HTTP framework,the method will block in the internal event loop
|
//Run HTTP framework,the method will block in the internal event loop
|
||||||
drogon::app().run();
|
drogon::app().run();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -22,9 +22,9 @@ class [[className]] : public HttpFilter<[[className]]>
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
[[className]]() {}
|
[[className]]() {}
|
||||||
virtual void doFilter(const HttpRequestPtr &req,
|
void doFilter(const HttpRequestPtr &req,
|
||||||
FilterCallback &&fcb,
|
FilterCallback &&fcb,
|
||||||
FilterChainCallback &&fccb) override;
|
FilterChainCallback &&fccb) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
<%c++for(size_t i=0;i<namespaceVector.size();i++){%>
|
<%c++for(size_t i=0;i<namespaceVector.size();i++){%>
|
||||||
|
@ -61,6 +61,7 @@ for(auto convertMethod : convertMethods ) {
|
|||||||
%>
|
%>
|
||||||
|
|
||||||
using namespace drogon;
|
using namespace drogon;
|
||||||
|
using namespace drogon::orm;
|
||||||
using namespace drogon_model::[[dbName]]<%c++
|
using namespace drogon_model::[[dbName]]<%c++
|
||||||
auto &schema=@@.get<std::string>("schema");
|
auto &schema=@@.get<std::string>("schema");
|
||||||
if(!schema.empty())
|
if(!schema.empty())
|
||||||
@ -75,7 +76,7 @@ else
|
|||||||
|
|
||||||
<%c++for(auto col:cols){
|
<%c++for(auto col:cols){
|
||||||
%>
|
%>
|
||||||
const std::string [[className]]::Cols::_{%col.colName_%} = "{%col.colName_%}";
|
const std::string [[className]]::Cols::_{%col.colName_%} = "{%escapeIdentifier(col.colName_, rdbms)%}";
|
||||||
<%c++
|
<%c++
|
||||||
}%>
|
}%>
|
||||||
<%c++if(@@.get<int>("hasPrimaryKey")<=1){%>
|
<%c++if(@@.get<int>("hasPrimaryKey")<=1){%>
|
||||||
@ -101,7 +102,7 @@ if(!schema.empty())
|
|||||||
{
|
{
|
||||||
$$<<schema<<".";
|
$$<<schema<<".";
|
||||||
}
|
}
|
||||||
%>[[tableName]]";
|
%>{%escapeIdentifier(@@.get<std::string>("tableName"), rdbms)%}";
|
||||||
|
|
||||||
const std::vector<typename [[className]]::MetaData> [[className]]::metaData_={
|
const std::vector<typename [[className]]::MetaData> [[className]]::metaData_={
|
||||||
<%c++for(size_t i=0;i<cols.size();i++){
|
<%c++for(size_t i=0;i<cols.size();i++){
|
||||||
@ -176,10 +177,10 @@ const std::string &[[className]]::getColumnName(size_t index) noexcept(false)
|
|||||||
$$<<" }\n";
|
$$<<" }\n";
|
||||||
$$<<" }\n";
|
$$<<" }\n";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if(col.colDatabaseType_=="bytea")
|
else if(col.colDatabaseType_=="bytea")
|
||||||
{
|
{
|
||||||
$$<<" auto str = r[\""<<col.colName_<<"\"].as<string_view>();\n";
|
$$<<" auto str = r[\""<<col.colName_<<"\"].as<std::string_view>();\n";
|
||||||
$$<<" if(str.length()>=2&&\n";
|
$$<<" if(str.length()>=2&&\n";
|
||||||
$$<<" str[0]=='\\\\'&&str[1]=='x')\n";
|
$$<<" str[0]=='\\\\'&&str[1]=='x')\n";
|
||||||
$$<<" {\n";
|
$$<<" {\n";
|
||||||
@ -191,7 +192,7 @@ const std::string &[[className]]::getColumnName(size_t index) noexcept(false)
|
|||||||
$$<<" }\n";
|
$$<<" }\n";
|
||||||
$$<<" }\n";
|
$$<<" }\n";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
%>
|
%>
|
||||||
{%col.colValName_%}_=std::make_shared<{%col.colType_%}>(r["{%col.colName_%}"].as<{%col.colType_%}>());
|
{%col.colValName_%}_=std::make_shared<{%col.colType_%}>(r["{%col.colName_%}"].as<{%col.colType_%}>());
|
||||||
<%c++
|
<%c++
|
||||||
@ -267,10 +268,10 @@ const std::string &[[className]]::getColumnName(size_t index) noexcept(false)
|
|||||||
$$<<" }\n";
|
$$<<" }\n";
|
||||||
$$<<" }\n";
|
$$<<" }\n";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if(col.colDatabaseType_=="bytea")
|
else if(col.colDatabaseType_=="bytea")
|
||||||
{
|
{
|
||||||
$$<<" auto str = r[index].as<string_view>();\n";
|
$$<<" auto str = r[index].as<std::string_view>();\n";
|
||||||
$$<<" if(str.length()>=2&&\n";
|
$$<<" if(str.length()>=2&&\n";
|
||||||
$$<<" str[0]=='\\\\'&&str[1]=='x')\n";
|
$$<<" str[0]=='\\\\'&&str[1]=='x')\n";
|
||||||
$$<<" {\n";
|
$$<<" {\n";
|
||||||
@ -282,7 +283,7 @@ const std::string &[[className]]::getColumnName(size_t index) noexcept(false)
|
|||||||
$$<<" }\n";
|
$$<<" }\n";
|
||||||
$$<<" }\n";
|
$$<<" }\n";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
%>
|
%>
|
||||||
{%col.colValName_%}_=std::make_shared<{%col.colType_%}>(r[index].as<{%col.colType_%}>());
|
{%col.colValName_%}_=std::make_shared<{%col.colType_%}>(r[index].as<{%col.colType_%}>());
|
||||||
<%c++
|
<%c++
|
||||||
@ -306,7 +307,7 @@ const std::string &[[className]]::getColumnName(size_t index) noexcept(false)
|
|||||||
<%c++
|
<%c++
|
||||||
for(size_t i=0; i<cols.size(); ++i)
|
for(size_t i=0; i<cols.size(); ++i)
|
||||||
{
|
{
|
||||||
auto &col = cols[i];
|
auto &col = cols[i];
|
||||||
if(col.colType_.empty())
|
if(col.colType_.empty())
|
||||||
continue;
|
continue;
|
||||||
%>
|
%>
|
||||||
@ -378,7 +379,7 @@ const std::string &[[className]]::getColumnName(size_t index) noexcept(false)
|
|||||||
$$<<" }\n";
|
$$<<" }\n";
|
||||||
$$<<" }\n";
|
$$<<" }\n";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if(col.colDatabaseType_=="bytea" || col.colDatabaseType_.find("blob") != std::string::npos)
|
else if(col.colDatabaseType_=="bytea" || col.colDatabaseType_.find("blob") != std::string::npos)
|
||||||
{
|
{
|
||||||
$$<<" if(!pJson[pMasqueradingVector["<<i<<"]].isNull())\n";
|
$$<<" if(!pJson[pMasqueradingVector["<<i<<"]].isNull())\n";
|
||||||
@ -392,7 +393,7 @@ const std::string &[[className]]::getColumnName(size_t index) noexcept(false)
|
|||||||
$$<<" }\n";
|
$$<<" }\n";
|
||||||
$$<<" }\n";
|
$$<<" }\n";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if(col.colType_.find("uint") == 0 || col.colType_ == "unsigned short")
|
else if(col.colType_.find("uint") == 0 || col.colType_ == "unsigned short")
|
||||||
{
|
{
|
||||||
$$<<" if(!pJson[pMasqueradingVector["<<i<<"]].isNull())\n";
|
$$<<" if(!pJson[pMasqueradingVector["<<i<<"]].isNull())\n";
|
||||||
@ -457,10 +458,10 @@ const std::string &[[className]]::getColumnName(size_t index) noexcept(false)
|
|||||||
$$<<" }\n";
|
$$<<" }\n";
|
||||||
$$<<" }\n";
|
$$<<" }\n";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
%>
|
%>
|
||||||
}
|
}
|
||||||
<%c++
|
<%c++
|
||||||
}
|
}
|
||||||
%>
|
%>
|
||||||
}
|
}
|
||||||
@ -538,10 +539,10 @@ const std::string &[[className]]::getColumnName(size_t index) noexcept(false)
|
|||||||
$$<<" "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
|
$$<<" "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
|
||||||
} //endif
|
} //endif
|
||||||
$$<<" }\n";
|
$$<<" }\n";
|
||||||
$$<<" }\n";
|
$$<<" }\n";
|
||||||
$$<<" }\n";
|
$$<<" }\n";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if(col.colDatabaseType_=="bytea" || col.colDatabaseType_.find("blob") != std::string::npos)
|
else if(col.colDatabaseType_=="bytea" || col.colDatabaseType_.find("blob") != std::string::npos)
|
||||||
{
|
{
|
||||||
$$<<" if(!pJson[\""<<col.colName_<<"\"].isNull())\n";
|
$$<<" if(!pJson[\""<<col.colName_<<"\"].isNull())\n";
|
||||||
@ -552,10 +553,10 @@ const std::string &[[className]]::getColumnName(size_t index) noexcept(false)
|
|||||||
if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
|
if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
|
||||||
$$<<" "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
|
$$<<" "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
|
||||||
} //endif
|
} //endif
|
||||||
$$<<" }\n";
|
$$<<" }\n";
|
||||||
$$<<" }\n";
|
$$<<" }\n";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if(col.colType_.find("uint") == 0 || col.colType_ == "unsigned short")
|
else if(col.colType_.find("uint") == 0 || col.colType_ == "unsigned short")
|
||||||
{
|
{
|
||||||
$$<<" if(!pJson[\""<<col.colName_<<"\"].isNull())\n";
|
$$<<" if(!pJson[\""<<col.colName_<<"\"].isNull())\n";
|
||||||
@ -565,7 +566,7 @@ const std::string &[[className]]::getColumnName(size_t index) noexcept(false)
|
|||||||
if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
|
if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
|
||||||
$$<<" "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
|
$$<<" "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
|
||||||
} //endif
|
} //endif
|
||||||
$$<<" }\n";
|
$$<<" }\n";
|
||||||
$$<<" }\n";
|
$$<<" }\n";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -578,7 +579,7 @@ const std::string &[[className]]::getColumnName(size_t index) noexcept(false)
|
|||||||
if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
|
if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
|
||||||
$$<<" "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
|
$$<<" "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
|
||||||
} //endif
|
} //endif
|
||||||
$$<<" }\n";
|
$$<<" }\n";
|
||||||
$$<<" }\n";
|
$$<<" }\n";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -591,7 +592,7 @@ const std::string &[[className]]::getColumnName(size_t index) noexcept(false)
|
|||||||
if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
|
if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
|
||||||
$$<<" "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
|
$$<<" "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
|
||||||
} //endif
|
} //endif
|
||||||
$$<<" }\n";
|
$$<<" }\n";
|
||||||
$$<<" }\n";
|
$$<<" }\n";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -604,7 +605,7 @@ const std::string &[[className]]::getColumnName(size_t index) noexcept(false)
|
|||||||
if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
|
if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
|
||||||
$$<<" "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
|
$$<<" "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
|
||||||
} //endif
|
} //endif
|
||||||
$$<<" }\n";
|
$$<<" }\n";
|
||||||
$$<<" }\n";
|
$$<<" }\n";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -617,10 +618,10 @@ const std::string &[[className]]::getColumnName(size_t index) noexcept(false)
|
|||||||
if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
|
if (convertMethod != convertMethods.end() && convertMethod->methodBeforeDbWrite() != "") {
|
||||||
$$<<" "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
|
$$<<" "<< convertMethod->methodBeforeDbWrite() << "(" << col.colValName_ << "_);\n";
|
||||||
} //endif
|
} //endif
|
||||||
$$<<" }\n";
|
$$<<" }\n";
|
||||||
$$<<" }\n";
|
$$<<" }\n";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
%>
|
%>
|
||||||
}
|
}
|
||||||
<%c++
|
<%c++
|
||||||
@ -713,7 +714,7 @@ void [[className]]::updateByMasqueradedJson(const Json::Value &pJson,
|
|||||||
$$<<" }\n";
|
$$<<" }\n";
|
||||||
$$<<" }\n";
|
$$<<" }\n";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if(col.colDatabaseType_=="bytea" || col.colDatabaseType_.find("blob") != std::string::npos)
|
else if(col.colDatabaseType_=="bytea" || col.colDatabaseType_.find("blob") != std::string::npos)
|
||||||
{
|
{
|
||||||
$$<<" if(!pJson[pMasqueradingVector["<<i<<"]].isNull())\n";
|
$$<<" if(!pJson[pMasqueradingVector["<<i<<"]].isNull())\n";
|
||||||
@ -727,7 +728,7 @@ void [[className]]::updateByMasqueradedJson(const Json::Value &pJson,
|
|||||||
$$<<" }\n";
|
$$<<" }\n";
|
||||||
$$<<" }\n";
|
$$<<" }\n";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if(col.colType_.find("uint") == 0 || col.colType_ == "unsigned short")
|
else if(col.colType_.find("uint") == 0 || col.colType_ == "unsigned short")
|
||||||
{
|
{
|
||||||
$$<<" if(!pJson[pMasqueradingVector["<<i<<"]].isNull())\n";
|
$$<<" if(!pJson[pMasqueradingVector["<<i<<"]].isNull())\n";
|
||||||
@ -792,14 +793,14 @@ void [[className]]::updateByMasqueradedJson(const Json::Value &pJson,
|
|||||||
$$<<" }\n";
|
$$<<" }\n";
|
||||||
$$<<" }\n";
|
$$<<" }\n";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
%>
|
%>
|
||||||
}
|
}
|
||||||
<%c++
|
<%c++
|
||||||
}
|
}
|
||||||
%>
|
%>
|
||||||
}
|
}
|
||||||
|
|
||||||
void [[className]]::updateByJson(const Json::Value &pJson) noexcept(false)
|
void [[className]]::updateByJson(const Json::Value &pJson) noexcept(false)
|
||||||
{
|
{
|
||||||
<%c++
|
<%c++
|
||||||
@ -879,7 +880,7 @@ void [[className]]::updateByJson(const Json::Value &pJson) noexcept(false)
|
|||||||
$$<<" }\n";
|
$$<<" }\n";
|
||||||
$$<<" }\n";
|
$$<<" }\n";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if(col.colDatabaseType_=="bytea" || col.colDatabaseType_.find("blob") != std::string::npos)
|
else if(col.colDatabaseType_=="bytea" || col.colDatabaseType_.find("blob") != std::string::npos)
|
||||||
{
|
{
|
||||||
$$<<" if(!pJson[\""<<col.colName_<<"\"].isNull())\n";
|
$$<<" if(!pJson[\""<<col.colName_<<"\"].isNull())\n";
|
||||||
@ -893,7 +894,7 @@ void [[className]]::updateByJson(const Json::Value &pJson) noexcept(false)
|
|||||||
$$<<" }\n";
|
$$<<" }\n";
|
||||||
$$<<" }\n";
|
$$<<" }\n";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if(col.colType_.find("uint") == 0 || col.colType_ == "unsigned short")
|
else if(col.colType_.find("uint") == 0 || col.colType_ == "unsigned short")
|
||||||
{
|
{
|
||||||
$$<<" if(!pJson[\""<<col.colName_<<"\"].isNull())\n";
|
$$<<" if(!pJson[\""<<col.colName_<<"\"].isNull())\n";
|
||||||
@ -958,7 +959,7 @@ void [[className]]::updateByJson(const Json::Value &pJson) noexcept(false)
|
|||||||
$$<<" }\n";
|
$$<<" }\n";
|
||||||
$$<<" }\n";
|
$$<<" }\n";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
%>
|
%>
|
||||||
}
|
}
|
||||||
<%c++
|
<%c++
|
||||||
@ -974,7 +975,7 @@ void [[className]]::updateByJson(const Json::Value &pJson) noexcept(false)
|
|||||||
{
|
{
|
||||||
$$<<"const "<<col.colType_<<" &"<<className<<"::getValueOf"<<col.colTypeName_<<"() const noexcept\n";
|
$$<<"const "<<col.colType_<<" &"<<className<<"::getValueOf"<<col.colTypeName_<<"() const noexcept\n";
|
||||||
$$<<"{\n";
|
$$<<"{\n";
|
||||||
$$<<" const static "<<col.colType_<<" defaultValue = "<<col.colType_<<"();\n";
|
$$<<" static const "<<col.colType_<<" defaultValue = "<<col.colType_<<"();\n";
|
||||||
$$<<" if("<<col.colValName_<<"_)\n";
|
$$<<" if("<<col.colValName_<<"_)\n";
|
||||||
$$<<" return *"<<col.colValName_<<"_;\n";
|
$$<<" return *"<<col.colValName_<<"_;\n";
|
||||||
$$<<" return defaultValue;\n";
|
$$<<" return defaultValue;\n";
|
||||||
@ -983,7 +984,7 @@ void [[className]]::updateByJson(const Json::Value &pJson) noexcept(false)
|
|||||||
{
|
{
|
||||||
$$<<"std::string "<<className<<"::getValueOf"<<col.colTypeName_<<"AsString() const noexcept\n";
|
$$<<"std::string "<<className<<"::getValueOf"<<col.colTypeName_<<"AsString() const noexcept\n";
|
||||||
$$<<"{\n";
|
$$<<"{\n";
|
||||||
$$<<" const static std::string defaultValue = std::string();\n";
|
$$<<" static const std::string defaultValue = std::string();\n";
|
||||||
$$<<" if("<<col.colValName_<<"_)\n";
|
$$<<" if("<<col.colValName_<<"_)\n";
|
||||||
$$<<" return std::string("<<col.colValName_<<"_->data(),"<<col.colValName_<<"_->size());\n";
|
$$<<" return std::string("<<col.colValName_<<"_->data(),"<<col.colValName_<<"_->size());\n";
|
||||||
$$<<" return defaultValue;\n";
|
$$<<" return defaultValue;\n";
|
||||||
@ -993,7 +994,7 @@ void [[className]]::updateByJson(const Json::Value &pJson) noexcept(false)
|
|||||||
$$<<"{\n";
|
$$<<"{\n";
|
||||||
$$<<" return "<<col.colValName_<<"_;\n";
|
$$<<" return "<<col.colValName_<<"_;\n";
|
||||||
$$<<"}\n";
|
$$<<"}\n";
|
||||||
|
|
||||||
$$<<"void "<<className<<"::set"<<col.colTypeName_<<"(const "<<col.colType_<<" &p"<<col.colTypeName_<<") noexcept\n";
|
$$<<"void "<<className<<"::set"<<col.colTypeName_<<"(const "<<col.colType_<<" &p"<<col.colTypeName_<<") noexcept\n";
|
||||||
$$<<"{\n";
|
$$<<"{\n";
|
||||||
if(col.colDatabaseType_=="date")
|
if(col.colDatabaseType_=="date")
|
||||||
@ -1006,7 +1007,7 @@ void [[className]]::updateByJson(const Json::Value &pJson) noexcept(false)
|
|||||||
}
|
}
|
||||||
$$<<" dirtyFlag_["<<i<<"] = true;\n";
|
$$<<" dirtyFlag_["<<i<<"] = true;\n";
|
||||||
$$<<"}\n";
|
$$<<"}\n";
|
||||||
|
|
||||||
if(col.colType_=="std::string")
|
if(col.colType_=="std::string")
|
||||||
{
|
{
|
||||||
$$<<"void "<<className<<"::set"<<col.colTypeName_<<"("<<col.colType_<<" &&p"<<col.colTypeName_<<") noexcept\n";
|
$$<<"void "<<className<<"::set"<<col.colTypeName_<<"("<<col.colType_<<" &&p"<<col.colTypeName_<<") noexcept\n";
|
||||||
@ -1043,7 +1044,7 @@ void [[className]]::updateByJson(const Json::Value &pJson) noexcept(false)
|
|||||||
$$<<"}\n";
|
$$<<"}\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$$<<"\n";
|
$$<<"\n";
|
||||||
}
|
}
|
||||||
if(@@.get<std::string>("rdbms")=="postgresql"||@@.get<int>("hasPrimaryKey")!=1)
|
if(@@.get<std::string>("rdbms")=="postgresql"||@@.get<int>("hasPrimaryKey")!=1)
|
||||||
{
|
{
|
||||||
@ -1328,7 +1329,7 @@ bool [[className]]::validateMasqueradedJsonForCreation(const Json::Value &pJson,
|
|||||||
}
|
}
|
||||||
<%c++}%>
|
<%c++}%>
|
||||||
}
|
}
|
||||||
catch(const Json::LogicError &e)
|
catch(const Json::LogicError &e)
|
||||||
{
|
{
|
||||||
err = e.what();
|
err = e.what();
|
||||||
return false;
|
return false;
|
||||||
@ -1358,7 +1359,7 @@ bool [[className]]::validateJsonForUpdate(const Json::Value &pJson, std::string
|
|||||||
err = "The value of primary key must be set in the json object for update";
|
err = "The value of primary key must be set in the json object for update";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
<%c++
|
<%c++
|
||||||
}
|
}
|
||||||
}%>
|
}%>
|
||||||
return true;
|
return true;
|
||||||
@ -1385,7 +1386,7 @@ bool [[className]]::validateMasqueradedJsonForUpdate(const Json::Value &pJson,
|
|||||||
if(!validJsonOfField({%i%}, pMasqueradingVector[{%i%}], pJson[pMasqueradingVector[{%i%}]], err, false))
|
if(!validJsonOfField({%i%}, pMasqueradingVector[{%i%}], pJson[pMasqueradingVector[{%i%}]], err, false))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
<%c++
|
<%c++
|
||||||
if(col.isPrimaryKey_)
|
if(col.isPrimaryKey_)
|
||||||
{
|
{
|
||||||
%>
|
%>
|
||||||
@ -1394,11 +1395,11 @@ bool [[className]]::validateMasqueradedJsonForUpdate(const Json::Value &pJson,
|
|||||||
err = "The value of primary key must be set in the json object for update";
|
err = "The value of primary key must be set in the json object for update";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
<%c++
|
<%c++
|
||||||
}
|
}
|
||||||
}%>
|
}%>
|
||||||
}
|
}
|
||||||
catch(const Json::LogicError &e)
|
catch(const Json::LogicError &e)
|
||||||
{
|
{
|
||||||
err = e.what();
|
err = e.what();
|
||||||
return false;
|
return false;
|
||||||
@ -1407,8 +1408,8 @@ bool [[className]]::validateMasqueradedJsonForUpdate(const Json::Value &pJson,
|
|||||||
}
|
}
|
||||||
bool [[className]]::validJsonOfField(size_t index,
|
bool [[className]]::validJsonOfField(size_t index,
|
||||||
{%indentStr%} const std::string &fieldName,
|
{%indentStr%} const std::string &fieldName,
|
||||||
{%indentStr%} const Json::Value &pJson,
|
{%indentStr%} const Json::Value &pJson,
|
||||||
{%indentStr%} std::string &err,
|
{%indentStr%} std::string &err,
|
||||||
{%indentStr%} bool isForCreation)
|
{%indentStr%} bool isForCreation)
|
||||||
{
|
{
|
||||||
switch(index)
|
switch(index)
|
||||||
@ -1429,7 +1430,7 @@ bool [[className]]::validJsonOfField(size_t index,
|
|||||||
}
|
}
|
||||||
<%c++}
|
<%c++}
|
||||||
if(col.isAutoVal_)
|
if(col.isAutoVal_)
|
||||||
{
|
{
|
||||||
if(col.isPrimaryKey_)
|
if(col.isPrimaryKey_)
|
||||||
{
|
{
|
||||||
%>
|
%>
|
||||||
@ -1437,8 +1438,8 @@ bool [[className]]::validJsonOfField(size_t index,
|
|||||||
{
|
{
|
||||||
err="The automatic primary key cannot be set";
|
err="The automatic primary key cannot be set";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
<%c++
|
<%c++
|
||||||
}else
|
}else
|
||||||
{
|
{
|
||||||
%>
|
%>
|
||||||
@ -1452,15 +1453,15 @@ bool [[className]]::validJsonOfField(size_t index,
|
|||||||
err="The automatic primary key cannot be update";
|
err="The automatic primary key cannot be update";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
<%c++
|
<%c++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!col.notNull_){%>
|
if(!col.notNull_){%>
|
||||||
if(pJson.isNull())
|
if(pJson.isNull())
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
<%c++}
|
<%c++}
|
||||||
if(col.colType_ == "uint64_t")
|
if(col.colType_ == "uint64_t")
|
||||||
{
|
{
|
||||||
%>
|
%>
|
||||||
@ -1491,7 +1492,7 @@ if(!col.notNull_){%>
|
|||||||
}
|
}
|
||||||
<%c++
|
<%c++
|
||||||
}
|
}
|
||||||
else if(col.colType_.find("int") == 0)
|
else if(col.colType_.find("int") == 0 || col.colType_ == "short")
|
||||||
{
|
{
|
||||||
%>
|
%>
|
||||||
if(!pJson.isInt())
|
if(!pJson.isInt())
|
||||||
@ -1519,7 +1520,7 @@ if(!col.notNull_){%>
|
|||||||
err="Type error in the "+fieldName+" field";
|
err="Type error in the "+fieldName+" field";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
<%c++
|
<%c++
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1527,19 +1528,18 @@ if(!col.notNull_){%>
|
|||||||
if(!pJson.isString())
|
if(!pJson.isString())
|
||||||
{
|
{
|
||||||
err="Type error in the "+fieldName+" field";
|
err="Type error in the "+fieldName+" field";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
<%c++
|
<%c++
|
||||||
if(col.colType_ == "std::string" && col.colLength_>0)
|
if(col.colType_ == "std::string" && col.colLength_>0)
|
||||||
{
|
{
|
||||||
%>
|
%>
|
||||||
// asString().length() creates a string object, is there any better way to validate the length?
|
if(pJson.isString() && std::strlen(pJson.asCString()) > {%col.colLength_%})
|
||||||
if(pJson.isString() && pJson.asString().length() > {%col.colLength_%})
|
|
||||||
{
|
{
|
||||||
err="String length exceeds limit for the " +
|
err="String length exceeds limit for the " +
|
||||||
fieldName +
|
fieldName +
|
||||||
" field (the maximum value is {%col.colLength_%})";
|
" field (the maximum value is {%col.colLength_%})";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
<%c++
|
<%c++
|
||||||
@ -1548,11 +1548,10 @@ if(!col.notNull_){%>
|
|||||||
%>
|
%>
|
||||||
break;
|
break;
|
||||||
<%c++
|
<%c++
|
||||||
}%>
|
}%>
|
||||||
default:
|
default:
|
||||||
err="Internal error in the server";
|
err="Internal error in the server";
|
||||||
return false;
|
return false;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1568,33 +1567,54 @@ for(auto &relationship : relationships)
|
|||||||
auto relationshipValName=nameTransform(name, false);
|
auto relationshipValName=nameTransform(name, false);
|
||||||
auto alias=relationship.targetTableAlias();
|
auto alias=relationship.targetTableAlias();
|
||||||
auto aliasValName=nameTransform(alias, false);
|
auto aliasValName=nameTransform(alias, false);
|
||||||
|
if(!alias.empty())
|
||||||
|
{
|
||||||
|
if(alias[0] <= 'z' && alias[0] >= 'a')
|
||||||
|
{
|
||||||
|
alias[0] += ('A' - 'a');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
alias = relationshipClassName;
|
||||||
|
}
|
||||||
|
std::string alind(alias.length(), ' ');
|
||||||
if(relationship.type() == Relationship::Type::HasOne)
|
if(relationship.type() == Relationship::Type::HasOne)
|
||||||
{
|
{
|
||||||
if(!alias.empty())
|
|
||||||
{
|
|
||||||
if(alias[0] <= 'z' && alias[0] >= 'a')
|
|
||||||
{
|
|
||||||
alias[0] += ('A' - 'a');
|
|
||||||
}
|
|
||||||
std::string alind(alias.length(), ' ');
|
|
||||||
%>
|
%>
|
||||||
void [[className]]::get{%alias%}(const DbClientPtr &clientPtr,
|
{%relationshipClassName%} [[className]]::get{%alias%}(const DbClientPtr &clientPtr) const {
|
||||||
{%indentStr%} {%alind%} const std::function<void({%relationshipClassName%})> &rcb,
|
static const std::string sql = "select * from {%name%} where {%relationship.targetKey()%} = <%c++
|
||||||
{%indentStr%} {%alind%} const ExceptionCallback &ecb) const
|
if(rdbms=="postgresql")
|
||||||
<%c++
|
{
|
||||||
|
$$<<"$1";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::string relationshipClassInde(relationshipClassName.length(), ' ');
|
$$<<"?";
|
||||||
%>
|
}%>";
|
||||||
void [[className]]::get{%relationshipClassName%}(const DbClientPtr &clientPtr,
|
Result r(nullptr);
|
||||||
{%indentStr%} {%relationshipClassInde%} const std::function<void({%relationshipClassName%})> &rcb,
|
{
|
||||||
{%indentStr%} {%relationshipClassInde%} const ExceptionCallback &ecb) const
|
auto binder = *clientPtr << sql;
|
||||||
<%c++
|
binder << *{%nameTransform(relationship.originalKey(), false)%}_ << Mode::Blocking >>
|
||||||
}
|
[&r](const Result &result) { r = result; };
|
||||||
%>
|
binder.exec();
|
||||||
|
}
|
||||||
|
if (r.size() == 0)
|
||||||
|
{
|
||||||
|
throw UnexpectedRows("0 rows found");
|
||||||
|
}
|
||||||
|
else if (r.size() > 1)
|
||||||
|
{
|
||||||
|
throw UnexpectedRows("Found more than one row");
|
||||||
|
}
|
||||||
|
return {%relationshipClassName%}(r[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void [[className]]::get{%alias%}(const DbClientPtr &clientPtr,
|
||||||
|
{%indentStr%} {%alind%} const std::function<void({%relationshipClassName%})> &rcb,
|
||||||
|
{%indentStr%} {%alind%} const ExceptionCallback &ecb) const
|
||||||
{
|
{
|
||||||
const static std::string sql = "select * from {%name%} where {%relationship.targetKey()%} = <%c++
|
static const std::string sql = "select * from {%name%} where {%relationship.targetKey()%} = <%c++
|
||||||
if(rdbms=="postgresql")
|
if(rdbms=="postgresql")
|
||||||
{
|
{
|
||||||
$$<<"$1";
|
$$<<"$1";
|
||||||
@ -1604,7 +1624,7 @@ void [[className]]::get{%relationshipClassName%}(const DbClientPtr &clientPtr,
|
|||||||
$$<<"?";
|
$$<<"?";
|
||||||
}%>";
|
}%>";
|
||||||
*clientPtr << sql
|
*clientPtr << sql
|
||||||
<< *{%nameTransform(relationship.originalKey(), false)%}_
|
<< *{%nameTransform(relationship.originalKey(), false)%}_
|
||||||
>> [rcb = std::move(rcb), ecb](const Result &r){
|
>> [rcb = std::move(rcb), ecb](const Result &r){
|
||||||
if (r.size() == 0)
|
if (r.size() == 0)
|
||||||
{
|
{
|
||||||
@ -1625,31 +1645,38 @@ void [[className]]::get{%relationshipClassName%}(const DbClientPtr &clientPtr,
|
|||||||
}
|
}
|
||||||
else if(relationship.type() == Relationship::Type::HasMany)
|
else if(relationship.type() == Relationship::Type::HasMany)
|
||||||
{
|
{
|
||||||
if(!alias.empty())
|
|
||||||
{
|
|
||||||
if(alias[0] <= 'z' && alias[0] >= 'a')
|
|
||||||
{
|
|
||||||
alias[0] += ('A' - 'a');
|
|
||||||
}
|
|
||||||
std::string alind(alias.length(), ' ');
|
|
||||||
%>
|
%>
|
||||||
void [[className]]::get{%alias%}(const DbClientPtr &clientPtr,
|
std::vector<{%relationshipClassName%}> [[className]]::get{%alias%}(const DbClientPtr &clientPtr) const {
|
||||||
{%indentStr%} {%alind%} const std::function<void(std::vector<{%relationshipClassName%}>)> &rcb,
|
static const std::string sql = "select * from {%name%} where {%relationship.targetKey()%} = <%c++
|
||||||
{%indentStr%} {%alind%} const ExceptionCallback &ecb) const
|
if(rdbms=="postgresql")
|
||||||
<%c++
|
{
|
||||||
|
$$<<"$1";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::string relationshipClassInde(relationshipClassName.length(), ' ');
|
$$<<"?";
|
||||||
%>
|
}%>";
|
||||||
void [[className]]::get{%relationshipClassName%}(const DbClientPtr &clientPtr,
|
Result r(nullptr);
|
||||||
{%indentStr%} {%relationshipClassInde%} const std::function<void(std::vector<{%relationshipClassName%}>)> &rcb,
|
{
|
||||||
{%indentStr%} {%relationshipClassInde%} const ExceptionCallback &ecb) const
|
auto binder = *clientPtr << sql;
|
||||||
<%c++
|
binder << *{%nameTransform(relationship.originalKey(), false)%}_ << Mode::Blocking >>
|
||||||
}
|
[&r](const Result &result) { r = result; };
|
||||||
%>
|
binder.exec();
|
||||||
|
}
|
||||||
|
std::vector<{%relationshipClassName%}> ret;
|
||||||
|
ret.reserve(r.size());
|
||||||
|
for (auto const &row : r)
|
||||||
|
{
|
||||||
|
ret.emplace_back({%relationshipClassName%}(row));
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void [[className]]::get{%alias%}(const DbClientPtr &clientPtr,
|
||||||
|
{%indentStr%} {%alind%} const std::function<void(std::vector<{%relationshipClassName%}>)> &rcb,
|
||||||
|
{%indentStr%} {%alind%} const ExceptionCallback &ecb) const
|
||||||
{
|
{
|
||||||
const static std::string sql = "select * from {%name%} where {%relationship.targetKey()%} = <%c++
|
static const std::string sql = "select * from {%name%} where {%relationship.targetKey()%} = <%c++
|
||||||
if(rdbms=="postgresql")
|
if(rdbms=="postgresql")
|
||||||
{
|
{
|
||||||
$$<<"$1";
|
$$<<"$1";
|
||||||
@ -1659,10 +1686,10 @@ void [[className]]::get{%relationshipClassName%}(const DbClientPtr &clientPtr,
|
|||||||
$$<<"?";
|
$$<<"?";
|
||||||
}%>";
|
}%>";
|
||||||
*clientPtr << sql
|
*clientPtr << sql
|
||||||
<< *{%nameTransform(relationship.originalKey(), false)%}_
|
<< *{%nameTransform(relationship.originalKey(), false)%}_
|
||||||
>> [rcb = std::move(rcb)](const Result &r){
|
>> [rcb = std::move(rcb)](const Result &r){
|
||||||
std::vector<{%relationshipClassName%}> ret;
|
std::vector<{%relationshipClassName%}> ret;
|
||||||
ret.reserve(ret.size());
|
ret.reserve(r.size());
|
||||||
for (auto const &row : r)
|
for (auto const &row : r)
|
||||||
{
|
{
|
||||||
ret.emplace_back({%relationshipClassName%}(row));
|
ret.emplace_back({%relationshipClassName%}(row));
|
||||||
@ -1679,31 +1706,39 @@ void [[className]]::get{%relationshipClassName%}(const DbClientPtr &clientPtr,
|
|||||||
auto pivotTableClassName=nameTransform(pivotTableName, true);
|
auto pivotTableClassName=nameTransform(pivotTableName, true);
|
||||||
auto &pivotOriginalKey=relationship.pivotTable().originalKey();
|
auto &pivotOriginalKey=relationship.pivotTable().originalKey();
|
||||||
auto &pivotTargetKey=relationship.pivotTable().targetKey();
|
auto &pivotTargetKey=relationship.pivotTable().targetKey();
|
||||||
if(!alias.empty())
|
|
||||||
{
|
|
||||||
if(alias[0] <= 'z' && alias[0] >= 'a')
|
|
||||||
{
|
|
||||||
alias[0] += ('A' - 'a');
|
|
||||||
}
|
|
||||||
std::string alind(alias.length(), ' ');
|
|
||||||
%>
|
%>
|
||||||
void [[className]]::get{%alias%}(const DbClientPtr &clientPtr,
|
std::vector<std::pair<{%relationshipClassName%},{%pivotTableClassName%}>> [[className]]::get{%alias%}(const DbClientPtr &clientPtr) const {
|
||||||
{%indentStr%} {%alind%} const std::function<void(std::vector<std::pair<{%relationshipClassName%},{%pivotTableClassName%}>>)> &rcb,
|
static const std::string sql = "select * from {%name%},{%pivotTableName%} where {%pivotTableName%}.{%pivotOriginalKey%} = <%c++
|
||||||
{%indentStr%} {%alind%} const ExceptionCallback &ecb) const
|
if(rdbms=="postgresql")
|
||||||
<%c++
|
{
|
||||||
|
$$<<"$1";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::string relationshipClassInde(relationshipClassName.length(), ' ');
|
$$<<"?";
|
||||||
%>
|
}%> and {%pivotTableName%}.{%pivotTargetKey%} = {%name%}.{%relationship.targetKey()%}";
|
||||||
void [[className]]::get{%relationshipClassName%}(const DbClientPtr &clientPtr,
|
Result r(nullptr);
|
||||||
{%indentStr%} {%relationshipClassInde%} const std::function<void(std::vector<std::pair<{%relationshipClassName%},{%pivotTableClassName%}>>)> &rcb,
|
{
|
||||||
{%indentStr%} {%relationshipClassInde%} const ExceptionCallback &ecb) const
|
auto binder = *clientPtr << sql;
|
||||||
<%c++
|
binder << *{%nameTransform(relationship.originalKey(), false)%}_ << Mode::Blocking >>
|
||||||
}
|
[&r](const Result &result) { r = result; };
|
||||||
%>
|
binder.exec();
|
||||||
|
}
|
||||||
|
std::vector<std::pair<{%relationshipClassName%},{%pivotTableClassName%}>> ret;
|
||||||
|
ret.reserve(r.size());
|
||||||
|
for (auto const &row : r)
|
||||||
|
{
|
||||||
|
ret.emplace_back(std::pair<{%relationshipClassName%},{%pivotTableClassName%}>(
|
||||||
|
{%relationshipClassName%}(row),{%pivotTableClassName%}(row,{%relationshipClassName%}::getColumnNumber())));
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void [[className]]::get{%alias%}(const DbClientPtr &clientPtr,
|
||||||
|
{%indentStr%} {%alind%} const std::function<void(std::vector<std::pair<{%relationshipClassName%},{%pivotTableClassName%}>>)> &rcb,
|
||||||
|
{%indentStr%} {%alind%} const ExceptionCallback &ecb) const
|
||||||
{
|
{
|
||||||
const static std::string sql = "select * from {%name%},{%pivotTableName%} where {%pivotTableName%}.{%pivotOriginalKey%} = <%c++
|
static const std::string sql = "select * from {%name%},{%pivotTableName%} where {%pivotTableName%}.{%pivotOriginalKey%} = <%c++
|
||||||
if(rdbms=="postgresql")
|
if(rdbms=="postgresql")
|
||||||
{
|
{
|
||||||
$$<<"$1";
|
$$<<"$1";
|
||||||
@ -1713,10 +1748,10 @@ void [[className]]::get{%relationshipClassName%}(const DbClientPtr &clientPtr,
|
|||||||
$$<<"?";
|
$$<<"?";
|
||||||
}%> and {%pivotTableName%}.{%pivotTargetKey%} = {%name%}.{%relationship.targetKey()%}";
|
}%> and {%pivotTableName%}.{%pivotTargetKey%} = {%name%}.{%relationship.targetKey()%}";
|
||||||
*clientPtr << sql
|
*clientPtr << sql
|
||||||
<< *{%nameTransform(relationship.originalKey(), false)%}_
|
<< *{%nameTransform(relationship.originalKey(), false)%}_
|
||||||
>> [rcb = std::move(rcb)](const Result &r){
|
>> [rcb = std::move(rcb)](const Result &r){
|
||||||
std::vector<std::pair<{%relationshipClassName%},{%pivotTableClassName%}>> ret;
|
std::vector<std::pair<{%relationshipClassName%},{%pivotTableClassName%}>> ret;
|
||||||
ret.reserve(ret.size());
|
ret.reserve(r.size());
|
||||||
for (auto const &row : r)
|
for (auto const &row : r)
|
||||||
{
|
{
|
||||||
ret.emplace_back(std::pair<{%relationshipClassName%},{%pivotTableClassName%}>(
|
ret.emplace_back(std::pair<{%relationshipClassName%},{%pivotTableClassName%}>(
|
||||||
|
@ -14,6 +14,7 @@ using namespace drogon_ctl;
|
|||||||
#include <drogon/orm/Field.h>
|
#include <drogon/orm/Field.h>
|
||||||
#include <drogon/orm/SqlBinder.h>
|
#include <drogon/orm/SqlBinder.h>
|
||||||
#include <drogon/orm/Mapper.h>
|
#include <drogon/orm/Mapper.h>
|
||||||
|
#include <drogon/orm/BaseBuilder.h>
|
||||||
#ifdef __cpp_impl_coroutine
|
#ifdef __cpp_impl_coroutine
|
||||||
#include <drogon/orm/CoroMapper.h>
|
#include <drogon/orm/CoroMapper.h>
|
||||||
#endif
|
#endif
|
||||||
@ -21,13 +22,13 @@ using namespace drogon_ctl;
|
|||||||
#include <trantor/utils/Logger.h>
|
#include <trantor/utils/Logger.h>
|
||||||
#include <json/json.h>
|
#include <json/json.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
using namespace drogon::orm;
|
|
||||||
namespace drogon
|
namespace drogon
|
||||||
{
|
{
|
||||||
namespace orm
|
namespace orm
|
||||||
@ -38,7 +39,7 @@ using DbClientPtr = std::shared_ptr<DbClient>;
|
|||||||
}
|
}
|
||||||
namespace drogon_model
|
namespace drogon_model
|
||||||
{
|
{
|
||||||
namespace [[dbName]]
|
namespace [[dbName]]
|
||||||
{
|
{
|
||||||
<%c++
|
<%c++
|
||||||
auto &schema=@@.get<std::string>("schema");
|
auto &schema=@@.get<std::string>("schema");
|
||||||
@ -85,11 +86,11 @@ auto cols=@@.get<std::vector<ColumnInfo>>("columns");
|
|||||||
%>
|
%>
|
||||||
};
|
};
|
||||||
|
|
||||||
const static int primaryKeyNumber;
|
static const int primaryKeyNumber;
|
||||||
const static std::string tableName;
|
static const std::string tableName;
|
||||||
const static bool hasPrimaryKey;
|
static const bool hasPrimaryKey;
|
||||||
<%c++if(@@.get<int>("hasPrimaryKey")<=1){%>
|
<%c++if(@@.get<int>("hasPrimaryKey")<=1){%>
|
||||||
const static std::string primaryKeyName;
|
static const std::string primaryKeyName;
|
||||||
<%c++if(!@@.get<std::string>("primaryKeyType").empty()){%>
|
<%c++if(!@@.get<std::string>("primaryKeyType").empty()){%>
|
||||||
using PrimaryKeyType = [[primaryKeyType]];
|
using PrimaryKeyType = [[primaryKeyType]];
|
||||||
const PrimaryKeyType &getPrimaryKey() const;
|
const PrimaryKeyType &getPrimaryKey() const;
|
||||||
@ -98,7 +99,7 @@ auto cols=@@.get<std::vector<ColumnInfo>>("columns");
|
|||||||
int getPrimaryKey() const { assert(false); return 0; }
|
int getPrimaryKey() const { assert(false); return 0; }
|
||||||
<%c++}%>
|
<%c++}%>
|
||||||
<%c++}else{
|
<%c++}else{
|
||||||
auto pkTypes=@@.get<std::vector<std::string>>("primaryKeyType");
|
auto pkTypes=@@.get<std::vector<std::string>>("primaryKeyType");
|
||||||
std::string typelist;
|
std::string typelist;
|
||||||
for(size_t i=0;i<pkTypes.size();i++)
|
for(size_t i=0;i<pkTypes.size();i++)
|
||||||
{
|
{
|
||||||
@ -107,7 +108,7 @@ auto cols=@@.get<std::vector<ColumnInfo>>("columns");
|
|||||||
typelist += ",";
|
typelist += ",";
|
||||||
}
|
}
|
||||||
%>
|
%>
|
||||||
const static std::vector<std::string> primaryKeyName;
|
static const std::vector<std::string> primaryKeyName;
|
||||||
using PrimaryKeyType = std::tuple<{%typelist%}>;//<%c++
|
using PrimaryKeyType = std::tuple<{%typelist%}>;//<%c++
|
||||||
auto pkName=@@.get<std::vector<std::string>>("primaryKeyName");
|
auto pkName=@@.get<std::vector<std::string>>("primaryKeyName");
|
||||||
for(size_t i=0;i<pkName.size();i++)
|
for(size_t i=0;i<pkName.size();i++)
|
||||||
@ -118,18 +119,18 @@ auto cols=@@.get<std::vector<ColumnInfo>>("columns");
|
|||||||
}
|
}
|
||||||
%>
|
%>
|
||||||
|
|
||||||
PrimaryKeyType getPrimaryKey() const;
|
PrimaryKeyType getPrimaryKey() const;
|
||||||
<%c++}%>
|
<%c++}%>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief constructor
|
* @brief constructor
|
||||||
* @param r One row of records in the SQL query result.
|
* @param r One row of records in the SQL query result.
|
||||||
* @param indexOffset Set the offset to -1 to access all columns by column names,
|
* @param indexOffset Set the offset to -1 to access all columns by column names,
|
||||||
* otherwise access all columns by offsets.
|
* otherwise access all columns by offsets.
|
||||||
* @note If the SQL is not a style of 'select * from table_name ...' (select all
|
* @note If the SQL is not a style of 'select * from table_name ...' (select all
|
||||||
* columns by an asterisk), please set the offset to -1.
|
* columns by an asterisk), please set the offset to -1.
|
||||||
*/
|
*/
|
||||||
explicit [[className]](const Row &r, const ssize_t indexOffset = 0) noexcept;
|
explicit [[className]](const drogon::orm::Row &r, const ssize_t indexOffset = 0) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief constructor
|
* @brief constructor
|
||||||
@ -145,7 +146,7 @@ auto cols=@@.get<std::vector<ColumnInfo>>("columns");
|
|||||||
[[className]](const Json::Value &pJson, const std::vector<std::string> &pMasqueradingVector) noexcept(false);
|
[[className]](const Json::Value &pJson, const std::vector<std::string> &pMasqueradingVector) noexcept(false);
|
||||||
|
|
||||||
[[className]]() = default;
|
[[className]]() = default;
|
||||||
|
|
||||||
void updateByJson(const Json::Value &pJson) noexcept(false);
|
void updateByJson(const Json::Value &pJson) noexcept(false);
|
||||||
void updateByMasqueradedJson(const Json::Value &pJson,
|
void updateByMasqueradedJson(const Json::Value &pJson,
|
||||||
const std::vector<std::string> &pMasqueradingVector) noexcept(false);
|
const std::vector<std::string> &pMasqueradingVector) noexcept(false);
|
||||||
@ -159,8 +160,8 @@ auto cols=@@.get<std::vector<ColumnInfo>>("columns");
|
|||||||
std::string &err);
|
std::string &err);
|
||||||
static bool validJsonOfField(size_t index,
|
static bool validJsonOfField(size_t index,
|
||||||
const std::string &fieldName,
|
const std::string &fieldName,
|
||||||
const Json::Value &pJson,
|
const Json::Value &pJson,
|
||||||
std::string &err,
|
std::string &err,
|
||||||
bool isForCreation);
|
bool isForCreation);
|
||||||
|
|
||||||
<%c++
|
<%c++
|
||||||
@ -195,7 +196,7 @@ auto cols=@@.get<std::vector<ColumnInfo>>("columns");
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
$$<<" //FIXME!!"<<" getValueOf"<<col.colTypeName_<<"() const noexcept;\n";
|
$$<<" //FIXME!!"<<" getValueOf"<<col.colTypeName_<<"() const noexcept;\n";
|
||||||
$$<<"\n";
|
$$<<"\n";
|
||||||
}
|
}
|
||||||
%>
|
%>
|
||||||
|
|
||||||
@ -205,7 +206,7 @@ auto cols=@@.get<std::vector<ColumnInfo>>("columns");
|
|||||||
Json::Value toJson() const;
|
Json::Value toJson() const;
|
||||||
Json::Value toMasqueradedJson(const std::vector<std::string> &pMasqueradingVector) const;
|
Json::Value toMasqueradedJson(const std::vector<std::string> &pMasqueradingVector) const;
|
||||||
/// Relationship interfaces
|
/// Relationship interfaces
|
||||||
<%c++
|
<%c++
|
||||||
for(auto &relationship : relationships)
|
for(auto &relationship : relationships)
|
||||||
{
|
{
|
||||||
if(relationship.targetKey().empty() || relationship.originalKey().empty())
|
if(relationship.targetKey().empty() || relationship.originalKey().empty())
|
||||||
@ -227,18 +228,20 @@ auto cols=@@.get<std::vector<ColumnInfo>>("columns");
|
|||||||
}
|
}
|
||||||
std::string alind(alias.length(), ' ');
|
std::string alind(alias.length(), ' ');
|
||||||
%>
|
%>
|
||||||
void get{%alias%}(const DbClientPtr &clientPtr,
|
{%relationshipClassName%} get{%alias%}(const drogon::orm::DbClientPtr &clientPtr) const;
|
||||||
|
void get{%alias%}(const drogon::orm::DbClientPtr &clientPtr,
|
||||||
{%alind%} const std::function<void({%relationshipClassName%})> &rcb,
|
{%alind%} const std::function<void({%relationshipClassName%})> &rcb,
|
||||||
{%alind%} const ExceptionCallback &ecb) const;
|
{%alind%} const drogon::orm::ExceptionCallback &ecb) const;
|
||||||
<%c++
|
<%c++
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::string relationshipClassInde(relationshipClassName.length(), ' ');
|
std::string relationshipClassInde(relationshipClassName.length(), ' ');
|
||||||
%>
|
%>
|
||||||
void get{%relationshipClassName%}(const DbClientPtr &clientPtr,
|
{%relationshipClassName%} get{%relationshipClassName%}(const drogon::orm::DbClientPtr &clientPtr) const;
|
||||||
|
void get{%relationshipClassName%}(const drogon::orm::DbClientPtr &clientPtr,
|
||||||
{%relationshipClassInde%} const std::function<void({%relationshipClassName%})> &rcb,
|
{%relationshipClassInde%} const std::function<void({%relationshipClassName%})> &rcb,
|
||||||
{%relationshipClassInde%} const ExceptionCallback &ecb) const;
|
{%relationshipClassInde%} const drogon::orm::ExceptionCallback &ecb) const;
|
||||||
<%c++
|
<%c++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -252,18 +255,20 @@ auto cols=@@.get<std::vector<ColumnInfo>>("columns");
|
|||||||
}
|
}
|
||||||
std::string alind(alias.length(), ' ');
|
std::string alind(alias.length(), ' ');
|
||||||
%>
|
%>
|
||||||
void get{%alias%}(const DbClientPtr &clientPtr,
|
std::vector<{%relationshipClassName%}> get{%alias%}(const drogon::orm::DbClientPtr &clientPtr) const;
|
||||||
|
void get{%alias%}(const drogon::orm::DbClientPtr &clientPtr,
|
||||||
{%alind%} const std::function<void(std::vector<{%relationshipClassName%}>)> &rcb,
|
{%alind%} const std::function<void(std::vector<{%relationshipClassName%}>)> &rcb,
|
||||||
{%alind%} const ExceptionCallback &ecb) const;
|
{%alind%} const drogon::orm::ExceptionCallback &ecb) const;
|
||||||
<%c++
|
<%c++
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::string relationshipClassInde(relationshipClassName.length(), ' ');
|
std::string relationshipClassInde(relationshipClassName.length(), ' ');
|
||||||
%>
|
%>
|
||||||
void get{%relationshipClassName%}(const DbClientPtr &clientPtr,
|
std::vector<{%relationshipClassName%}> get{%relationshipClassName%}(const drogon::orm::DbClientPtr &clientPtr) const;
|
||||||
|
void get{%relationshipClassName%}(const drogon::orm::DbClientPtr &clientPtr,
|
||||||
{%relationshipClassInde%} const std::function<void(std::vector<{%relationshipClassName%}>)> &rcb,
|
{%relationshipClassInde%} const std::function<void(std::vector<{%relationshipClassName%}>)> &rcb,
|
||||||
{%relationshipClassInde%} const ExceptionCallback &ecb) const;
|
{%relationshipClassInde%} const drogon::orm::ExceptionCallback &ecb) const;
|
||||||
<%c++
|
<%c++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -279,27 +284,33 @@ auto cols=@@.get<std::vector<ColumnInfo>>("columns");
|
|||||||
}
|
}
|
||||||
std::string alind(alias.length(), ' ');
|
std::string alind(alias.length(), ' ');
|
||||||
%>
|
%>
|
||||||
void get{%alias%}(const DbClientPtr &clientPtr,
|
std::vector<std::pair<{%relationshipClassName%},{%pivotTableClassName%}>> get{%alias%}(const drogon::orm::DbClientPtr &clientPtr) const;
|
||||||
|
void get{%alias%}(const drogon::orm::DbClientPtr &clientPtr,
|
||||||
{%alind%} const std::function<void(std::vector<std::pair<{%relationshipClassName%},{%pivotTableClassName%}>>)> &rcb,
|
{%alind%} const std::function<void(std::vector<std::pair<{%relationshipClassName%},{%pivotTableClassName%}>>)> &rcb,
|
||||||
{%alind%} const ExceptionCallback &ecb) const;
|
{%alind%} const drogon::orm::ExceptionCallback &ecb) const;
|
||||||
<%c++
|
<%c++
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::string relationshipClassInde(relationshipClassName.length(), ' ');
|
std::string relationshipClassInde(relationshipClassName.length(), ' ');
|
||||||
%>
|
%>
|
||||||
void get{%relationshipClassName%}(const DbClientPtr &clientPtr,
|
std::vector<std::pair<{%relationshipClassName%},{%pivotTableClassName%}>> get{%relationshipClassName%}(const drogon::orm::DbClientPtr &clientPtr) const;
|
||||||
|
void get{%relationshipClassName%}(const drogon::orm::DbClientPtr &clientPtr,
|
||||||
{%relationshipClassInde%} const std::function<void(std::vector<std::pair<{%relationshipClassName%},{%pivotTableClassName%}>>)> &rcb,
|
{%relationshipClassInde%} const std::function<void(std::vector<std::pair<{%relationshipClassName%},{%pivotTableClassName%}>>)> &rcb,
|
||||||
{%relationshipClassInde%} const ExceptionCallback &ecb) const;
|
{%relationshipClassInde%} const drogon::orm::ExceptionCallback &ecb) const;
|
||||||
<%c++
|
<%c++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
%>
|
%>
|
||||||
private:
|
private:
|
||||||
friend Mapper<[[className]]>;
|
friend drogon::orm::Mapper<[[className]]>;
|
||||||
|
friend drogon::orm::BaseBuilder<[[className]], true, true>;
|
||||||
|
friend drogon::orm::BaseBuilder<[[className]], true, false>;
|
||||||
|
friend drogon::orm::BaseBuilder<[[className]], false, true>;
|
||||||
|
friend drogon::orm::BaseBuilder<[[className]], false, false>;
|
||||||
#ifdef __cpp_impl_coroutine
|
#ifdef __cpp_impl_coroutine
|
||||||
friend CoroMapper<[[className]]>;
|
friend drogon::orm::CoroMapper<[[className]]>;
|
||||||
#endif
|
#endif
|
||||||
static const std::vector<std::string> &insertColumns() noexcept;
|
static const std::vector<std::string> &insertColumns() noexcept;
|
||||||
void outputArgs(drogon::orm::internal::SqlBinder &binder) const;
|
void outputArgs(drogon::orm::internal::SqlBinder &binder) const;
|
||||||
@ -357,7 +368,7 @@ if(@@.get<int>("hasPrimaryKey")<=1){
|
|||||||
$$<<"\";\n";
|
$$<<"\";\n";
|
||||||
}
|
}
|
||||||
%>
|
%>
|
||||||
return sql;
|
return sql;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const std::string &sqlForDeletingByPrimaryKey()
|
static const std::string &sqlForDeletingByPrimaryKey()
|
||||||
@ -389,7 +400,7 @@ if(@@.get<int>("hasPrimaryKey")<=1){
|
|||||||
$$<<"\";\n";
|
$$<<"\";\n";
|
||||||
}
|
}
|
||||||
%>
|
%>
|
||||||
return sql;
|
return sql;
|
||||||
}
|
}
|
||||||
std::string sqlForInserting(bool &needSelection) const
|
std::string sqlForInserting(bool &needSelection) const
|
||||||
{
|
{
|
||||||
@ -413,7 +424,7 @@ if(@@.get<int>("hasPrimaryKey")<=1){
|
|||||||
$$<<" sql += \""<<cols[i].colName_<<",\";\n";
|
$$<<" sql += \""<<cols[i].colName_<<",\";\n";
|
||||||
$$<<" ++parametersCount;\n";
|
$$<<" ++parametersCount;\n";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(cols[i].colType_.empty())
|
if(cols[i].colType_.empty())
|
||||||
continue;
|
continue;
|
||||||
if(cols[i].hasDefaultVal_)
|
if(cols[i].hasDefaultVal_)
|
||||||
@ -434,13 +445,13 @@ if(@@.get<int>("hasPrimaryKey")<=1){
|
|||||||
<%c++
|
<%c++
|
||||||
}
|
}
|
||||||
if(@@.get<int>("hasPrimaryKey")>0||@@.get<std::string>("rdbms")=="postgresql")
|
if(@@.get<int>("hasPrimaryKey")>0||@@.get<std::string>("rdbms")=="postgresql")
|
||||||
{
|
{
|
||||||
%>
|
%>
|
||||||
if(!dirtyFlag_[{%i%}])
|
if(!dirtyFlag_[{%i%}])
|
||||||
{
|
{
|
||||||
needSelection=true;
|
needSelection=true;
|
||||||
}
|
}
|
||||||
<%c++
|
<%c++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -451,7 +462,7 @@ if(@@.get<int>("hasPrimaryKey")<=1){
|
|||||||
sql += "{%cols[i].colName_%},";
|
sql += "{%cols[i].colName_%},";
|
||||||
++parametersCount;
|
++parametersCount;
|
||||||
}
|
}
|
||||||
<%c++
|
<%c++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(selFlag)
|
if(selFlag)
|
||||||
@ -466,7 +477,7 @@ if(@@.get<int>("hasPrimaryKey")<=1){
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
sql += ") values (";
|
sql += ") values (";
|
||||||
|
|
||||||
<%c++
|
<%c++
|
||||||
if(@@.get<std::string>("rdbms")=="postgresql")
|
if(@@.get<std::string>("rdbms")=="postgresql")
|
||||||
{
|
{
|
||||||
@ -474,8 +485,8 @@ if(@@.get<std::string>("rdbms")=="postgresql")
|
|||||||
int placeholder=1;
|
int placeholder=1;
|
||||||
char placeholderStr[64];
|
char placeholderStr[64];
|
||||||
size_t n=0;
|
size_t n=0;
|
||||||
<%c++
|
<%c++
|
||||||
}
|
}
|
||||||
for(size_t i=0;i<cols.size();i++)
|
for(size_t i=0;i<cols.size();i++)
|
||||||
{
|
{
|
||||||
if(cols[i].isAutoVal_)
|
if(cols[i].isAutoVal_)
|
||||||
@ -487,7 +498,7 @@ if(@@.get<std::string>("rdbms")=="postgresql")
|
|||||||
<%c++
|
<%c++
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(cols[i].colType_.empty())
|
if(cols[i].colType_.empty())
|
||||||
continue;
|
continue;
|
||||||
%>
|
%>
|
||||||
@ -497,7 +508,7 @@ if(@@.get<std::string>("rdbms")=="postgresql")
|
|||||||
if(@@.get<std::string>("rdbms")=="postgresql")
|
if(@@.get<std::string>("rdbms")=="postgresql")
|
||||||
{
|
{
|
||||||
%>
|
%>
|
||||||
n = sprintf(placeholderStr,"$%d,",placeholder++);
|
n = snprintf(placeholderStr,sizeof(placeholderStr),"$%d,",placeholder++);
|
||||||
sql.append(placeholderStr, n);
|
sql.append(placeholderStr, n);
|
||||||
<%c++
|
<%c++
|
||||||
}else
|
}else
|
||||||
@ -508,7 +519,7 @@ if(@@.get<std::string>("rdbms")=="postgresql")
|
|||||||
<%c++
|
<%c++
|
||||||
}
|
}
|
||||||
%>
|
%>
|
||||||
}
|
}
|
||||||
<%c++
|
<%c++
|
||||||
if(cols[i].hasDefaultVal_&&@@.get<std::string>("rdbms")!="sqlite3")
|
if(cols[i].hasDefaultVal_&&@@.get<std::string>("rdbms")!="sqlite3")
|
||||||
{
|
{
|
||||||
@ -545,7 +556,7 @@ if(cols[i].hasDefaultVal_&&@@.get<std::string>("rdbms")!="sqlite3")
|
|||||||
}
|
}
|
||||||
%>
|
%>
|
||||||
LOG_TRACE << sql;
|
LOG_TRACE << sql;
|
||||||
return sql;
|
return sql;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
<%c++
|
<%c++
|
||||||
|
@ -23,11 +23,11 @@ class [[className]] : public drogon::Plugin<[[className]]>
|
|||||||
[[className]]() {}
|
[[className]]() {}
|
||||||
/// This method must be called by drogon to initialize and start the plugin.
|
/// This method must be called by drogon to initialize and start the plugin.
|
||||||
/// It must be implemented by the user.
|
/// It must be implemented by the user.
|
||||||
virtual void initAndStart(const Json::Value &config) override;
|
void initAndStart(const Json::Value &config) override;
|
||||||
|
|
||||||
/// This method must be called by drogon to shutdown the plugin.
|
/// This method must be called by drogon to shutdown the plugin.
|
||||||
/// It must be implemented by the user.
|
/// It must be implemented by the user.
|
||||||
virtual void shutdown() override;
|
void shutdown() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
<%c++for(size_t i=0;i<namespaceVector.size();i++){%>
|
<%c++for(size_t i=0;i<namespaceVector.size();i++){%>
|
||||||
|
@ -19,6 +19,7 @@ auto modelName = tableInfo.get<std::string>("className");
|
|||||||
$$<<"#include \""<<modelName<<".h\"\n";
|
$$<<"#include \""<<modelName<<".h\"\n";
|
||||||
bool hasPrimaryKey = (tableInfo.get<int>("hasPrimaryKey")==1);
|
bool hasPrimaryKey = (tableInfo.get<int>("hasPrimaryKey")==1);
|
||||||
$$<<"using namespace drogon;\n";
|
$$<<"using namespace drogon;\n";
|
||||||
|
$$<<"using namespace drogon::orm;\n";
|
||||||
|
|
||||||
$$<<"using namespace drogon_model::"<<tableInfo.get<std::string>("dbName");
|
$$<<"using namespace drogon_model::"<<tableInfo.get<std::string>("dbName");
|
||||||
auto &schema=tableInfo.get<std::string>("schema");
|
auto &schema=tableInfo.get<std::string>("schema");
|
||||||
@ -83,4 +84,4 @@ class [[className]]Base : public RestfulController
|
|||||||
{
|
{
|
||||||
$$<<"}\n";
|
$$<<"}\n";
|
||||||
}
|
}
|
||||||
%>
|
%>
|
||||||
|
@ -6,9 +6,9 @@ add_executable(${PROJECT_NAME} test_main.cc)
|
|||||||
# ##############################################################################
|
# ##############################################################################
|
||||||
# If you include the drogon source code locally in your project, use this method
|
# If you include the drogon source code locally in your project, use this method
|
||||||
# to add drogon
|
# to add drogon
|
||||||
# target_link_libraries(${PROJECT_NAME}_test PRIVATE drogon)
|
# target_link_libraries(${PROJECT_NAME} PRIVATE drogon)
|
||||||
#
|
#
|
||||||
# and comment out the following lines
|
# and comment out the following lines
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE Drogon::Drogon)
|
target_link_libraries(${PROJECT_NAME} PRIVATE Drogon::Drogon)
|
||||||
|
|
||||||
ParseAndAddDrogonTests(${PROJECT_NAME})
|
ParseAndAddDrogonTests(${PROJECT_NAME})
|
||||||
|
@ -15,20 +15,25 @@
|
|||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include <drogon/config.h>
|
#include <drogon/config.h>
|
||||||
#include <drogon/version.h>
|
#include <drogon/version.h>
|
||||||
|
#include <drogon/utils/Utilities.h>
|
||||||
#include <trantor/net/Resolver.h>
|
#include <trantor/net/Resolver.h>
|
||||||
|
#include <trantor/utils/Utilities.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
using namespace drogon_ctl;
|
using namespace drogon_ctl;
|
||||||
static const char banner[] =
|
static const char banner[] =
|
||||||
" _ \n"
|
R"( _
|
||||||
" __| |_ __ ___ __ _ ___ _ __ \n"
|
__| |_ __ ___ __ _ ___ _ __
|
||||||
" / _` | '__/ _ \\ / _` |/ _ \\| '_ \\ \n"
|
/ _` | '__/ _ \ / _` |/ _ \| '_ \
|
||||||
"| (_| | | | (_) | (_| | (_) | | | |\n"
|
| (_| | | | (_) | (_| | (_) | | | |
|
||||||
" \\__,_|_| \\___/ \\__, |\\___/|_| |_|\n"
|
\__,_|_| \___/ \__, |\___/|_| |_|
|
||||||
" |___/ \n";
|
|___/
|
||||||
|
)";
|
||||||
|
|
||||||
void version::handleCommand(std::vector<std::string> ¶meters)
|
void version::handleCommand(std::vector<std::string> ¶meters)
|
||||||
{
|
{
|
||||||
|
const auto tlsBackend = trantor::utils::tlsBackend();
|
||||||
|
const bool tlsSupported = drogon::utils::supportsTls();
|
||||||
std::cout << banner << std::endl;
|
std::cout << banner << std::endl;
|
||||||
std::cout << "A utility for drogon" << std::endl;
|
std::cout << "A utility for drogon" << std::endl;
|
||||||
std::cout << "Version: " << DROGON_VERSION << std::endl;
|
std::cout << "Version: " << DROGON_VERSION << std::endl;
|
||||||
@ -38,25 +43,16 @@ void version::handleCommand(std::vector<std::string> ¶meters)
|
|||||||
<< "\n Compilation flags: " << COMPILATION_FLAGS
|
<< "\n Compilation flags: " << COMPILATION_FLAGS
|
||||||
<< INCLUDING_DIRS << std::endl;
|
<< INCLUDING_DIRS << std::endl;
|
||||||
std::cout << "Libraries: \n postgresql: "
|
std::cout << "Libraries: \n postgresql: "
|
||||||
<< (USE_POSTGRESQL ? "yes" : "no") << " (batch mode: "
|
<< (USE_POSTGRESQL ? "yes" : "no") << " (pipeline mode: "
|
||||||
<< (LIBPQ_SUPPORTS_BATCH_MODE ? "yes)\n" : "no)\n")
|
<< (LIBPQ_SUPPORTS_BATCH_MODE ? "yes)\n" : "no)\n")
|
||||||
<< " mariadb: " << (USE_MYSQL ? "yes\n" : "no\n")
|
<< " mariadb: " << (USE_MYSQL ? "yes\n" : "no\n")
|
||||||
<< " sqlite3: " << (USE_SQLITE3 ? "yes\n" : "no\n");
|
<< " sqlite3: " << (USE_SQLITE3 ? "yes\n" : "no\n");
|
||||||
#ifdef OpenSSL_FOUND
|
std::cout << " ssl/tls backend: " << tlsBackend << "\n";
|
||||||
std::cout << " openssl: yes\n";
|
|
||||||
#else
|
|
||||||
std::cout << " openssl: no\n";
|
|
||||||
#endif
|
|
||||||
#ifdef USE_BROTLI
|
#ifdef USE_BROTLI
|
||||||
std::cout << " brotli: yes\n";
|
std::cout << " brotli: yes\n";
|
||||||
#else
|
#else
|
||||||
std::cout << " brotli: no\n";
|
std::cout << " brotli: no\n";
|
||||||
#endif
|
#endif
|
||||||
#ifdef Boost_FOUND
|
|
||||||
std::cout << " boost: yes\n";
|
|
||||||
#else
|
|
||||||
std::cout << " boost: no\n";
|
|
||||||
#endif
|
|
||||||
#ifdef USE_REDIS
|
#ifdef USE_REDIS
|
||||||
std::cout << " hiredis: yes\n";
|
std::cout << " hiredis: yes\n";
|
||||||
#else
|
#else
|
||||||
@ -64,4 +60,9 @@ void version::handleCommand(std::vector<std::string> ¶meters)
|
|||||||
#endif
|
#endif
|
||||||
std::cout << " c-ares: "
|
std::cout << " c-ares: "
|
||||||
<< (trantor::Resolver::isCAresUsed() ? "yes\n" : "no\n");
|
<< (trantor::Resolver::isCAresUsed() ? "yes\n" : "no\n");
|
||||||
|
#ifdef HAS_YAML_CPP
|
||||||
|
std::cout << " yaml-cpp: yes\n";
|
||||||
|
#else
|
||||||
|
std::cout << " yaml-cpp: no\n";
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -17,20 +17,24 @@
|
|||||||
#include <drogon/DrObject.h>
|
#include <drogon/DrObject.h>
|
||||||
#include "CommandHandler.h"
|
#include "CommandHandler.h"
|
||||||
using namespace drogon;
|
using namespace drogon;
|
||||||
|
|
||||||
namespace drogon_ctl
|
namespace drogon_ctl
|
||||||
{
|
{
|
||||||
class version : public DrObject<version>, public CommandHandler
|
class version : public DrObject<version>, public CommandHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void handleCommand(std::vector<std::string> ¶meters) override;
|
void handleCommand(std::vector<std::string> ¶meters) override;
|
||||||
virtual std::string script() override
|
|
||||||
|
std::string script() override
|
||||||
{
|
{
|
||||||
return "display version of this tool";
|
return "display version of this tool";
|
||||||
}
|
}
|
||||||
virtual bool isTopCommand() override
|
|
||||||
|
bool isTopCommand() override
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
version()
|
version()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,18 @@ drogon_create_views(login_session
|
|||||||
|
|
||||||
add_executable(jsonstore jsonstore/main.cc)
|
add_executable(jsonstore jsonstore/main.cc)
|
||||||
|
|
||||||
|
add_executable(redis_simple redis/main.cc
|
||||||
|
redis/controllers/Client.cc
|
||||||
|
redis/controllers/WsClient.cc)
|
||||||
|
|
||||||
|
add_executable(redis_chat redis_chat/main.cc
|
||||||
|
redis_chat/controllers/Chat.cc)
|
||||||
|
|
||||||
|
add_executable(async_stream async_stream/main.cc
|
||||||
|
async_stream/RequestStreamExampleCtrl.cc)
|
||||||
|
|
||||||
|
add_executable(cors cors/main.cc)
|
||||||
|
|
||||||
set(example_targets
|
set(example_targets
|
||||||
benchmark
|
benchmark
|
||||||
client
|
client
|
||||||
@ -32,11 +44,15 @@ set(example_targets
|
|||||||
helloworld
|
helloworld
|
||||||
file_upload
|
file_upload
|
||||||
login_session
|
login_session
|
||||||
jsonstore)
|
jsonstore
|
||||||
|
redis_simple
|
||||||
|
redis_chat
|
||||||
|
async_stream
|
||||||
|
cors)
|
||||||
|
|
||||||
# Add warnings for our example targets--some warnings (such as -Wunused-parameter) only appear
|
# Add warnings for our example targets--some warnings (such as -Wunused-parameter) only appear
|
||||||
# when the templated functions are instantiated at their point of use.
|
# when the templated functions are instantiated at their point of use.
|
||||||
if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
|
if(NOT ${CMAKE_PLATFORM_NAME} STREQUAL "Windows" AND CMAKE_CXX_COMPILER_ID MATCHES GNU)
|
||||||
foreach(target ${example_targets})
|
foreach(target ${example_targets})
|
||||||
target_compile_options(${target} PRIVATE -Wall -Wextra -Werror)
|
target_compile_options(${target} PRIVATE -Wall -Wextra -Werror)
|
||||||
endforeach()
|
endforeach()
|
||||||
|
@ -2,18 +2,21 @@
|
|||||||
|
|
||||||
The following examples can help you understand how to use Drogon:
|
The following examples can help you understand how to use Drogon:
|
||||||
|
|
||||||
1. [helloworld](https://github.com/an-tao/drogon/tree/master/examples/helloworld) - The multiple ways of "Hello, World!"
|
1. [helloworld](https://github.com/drogonframework/drogon/tree/master/examples/helloworld) - The multiple ways of "Hello, World!"
|
||||||
2. [client_example](https://github.com/an-tao/drogon/tree/master/examples/client_example/main.cc) - A client example.
|
2. [client_example](https://github.com/drogonframework/drogon/tree/master/examples/client_example/main.cc) - A client example
|
||||||
3. [websocket_client](https://github.com/an-tao/drogon/tree/master/examples/websocket_client/WebSocketClient.cc) - An example on how to use the WebSocket client
|
3. [websocket_client](https://github.com/drogonframework/drogon/tree/master/examples/websocket_client/WebSocketClient.cc) - An example on how to use the WebSocket client
|
||||||
4. [login_session](https://github.com/an-tao/drogon/tree/master/examples/login_session) - How to use the built-in session system to handle login and out
|
4. [login_session](https://github.com/drogonframework/drogon/tree/master/examples/login_session) - How to use the built-in session system to handle login and out
|
||||||
5. [file_upload](https://github.com/an-tao/drogon/tree/master/examples/file_upload) - How to handle file uploads in Drogon
|
5. [file_upload](https://github.com/drogonframework/drogon/tree/master/examples/file_upload) - How to handle file uploads in Drogon
|
||||||
6. [simple_reverse_proxy](https://github.com/an-tao/drogon/tree/master/examples/simple_reverse_proxy) - A Example showing how to use drogon as a http reverse
|
6. [simple_reverse_proxy](https://github.com/drogonframework/drogon/tree/master/examples/simple_reverse_proxy) - An example showing how to use Drogon as a HTTP reverse
|
||||||
proxy with a simple round robin.
|
proxy with a simple round robin
|
||||||
7. [benchmark](https://github.com/an-tao/drogon/tree/master/examples/benchmark) - Basic benchmark example. see [wiki benchmarks](https://github.com/an-tao/drogon/wiki/13-Benchmarks)
|
7. [benchmark](https://github.com/drogonframework/drogon/tree/master/examples/benchmark) - Basic benchmark(https://github.com/drogonframework/drogon/wiki/13-Benchmarks) example
|
||||||
8. [jsonstore](https://github.com/an-tao/drogon/tree/master/examples/jsonstore) - Implementation of a [jsonstore](https://github.com/bluzi/jsonstore)-like storage service that is concurrent and stores in memory. Serving as a showcase on how to build a minimally useful RESTful APIs in Drogon.
|
8. [jsonstore](https://github.com/drogonframework/drogon/tree/master/examples/jsonstore) - Implementation of a [jsonstore](https://github.com/bluzi/jsonstore)-like storage service that is concurrent and stores in memory. Serving as a showcase on how to build a minimally useful RESTful APIs in Drogon
|
||||||
9. [redis](https://github.com/an-tao/drogon/tree/master/examples/redis) - A simple example of Redis
|
9. [redis](https://github.com/drogonframework/drogon/tree/master/examples/redis) - A simple example of Redis
|
||||||
10. [websocket_server](https://github.com/drogonframework/drogon/tree/master/examples/websocket_server) - Example WebSocker chat room server
|
10. [websocket_server](https://github.com/drogonframework/drogon/tree/master/examples/websocket_server) - A example websocket chat room server
|
||||||
|
11. [redis_cache](https://github.com/drogonframework/drogon/tree/master/examples/redis_cache) - An example for using coroutines of Redis clients
|
||||||
|
12. [redis_chat](https://github.com/drogonframework/drogon/tree/master/examples/redis_chat) - A chatroom server built with websocket and Redis pub/sub service
|
||||||
|
13. [prometheus_example](https://github.com/drogonframework/drogon/tree/master/examples/prometheus_example) - An example of how to use the Prometheus exporter in Drogon
|
||||||
|
14. [cors](https://github.com/drogonframework/drogon/tree/master/examples/cors) - An example demonstrating how to implement CORS (Cross-Origin Resource Sharing) support in Drogon
|
||||||
|
|
||||||
### [TechEmpower Framework Benchmarks](https://github.com/TechEmpower/FrameworkBenchmarks) test suite
|
### [TechEmpower Framework Benchmarks](https://github.com/TechEmpower/FrameworkBenchmarks) test suite
|
||||||
|
|
||||||
@ -21,4 +24,4 @@ I created a benchmark suite for the `tfb`, see [here](https://github.com/TechEmp
|
|||||||
|
|
||||||
### Another test suite
|
### Another test suite
|
||||||
|
|
||||||
I also created a test suite for another web frameworks benchmark repository, see [here](https://github.com/the-benchmarker/web-frameworks/tree/master/cpp/drogon), in this project, drogon is used as a sub-module (locally include in the project).
|
I also created a test suite for another web frameworks benchmark repository, see [here](https://github.com/the-benchmarker/web-frameworks/tree/master/cpp/drogon). In this project, Drogon is used as a sub-module (locally include in the project).
|
||||||
|
167
examples/async_stream/RequestStreamExampleCtrl.cc
Normal file
167
examples/async_stream/RequestStreamExampleCtrl.cc
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
#include <drogon/drogon.h>
|
||||||
|
#include <drogon/HttpController.h>
|
||||||
|
#include <drogon/HttpRequest.h>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
using namespace drogon;
|
||||||
|
|
||||||
|
class StreamEchoReader : public RequestStreamReader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
StreamEchoReader(ResponseStreamPtr respStream)
|
||||||
|
: respStream_(std::move(respStream))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void onStreamData(const char *data, size_t length) override
|
||||||
|
{
|
||||||
|
LOG_INFO << "onStreamData[" << length << "]";
|
||||||
|
respStream_->send({data, length});
|
||||||
|
}
|
||||||
|
|
||||||
|
void onStreamFinish(std::exception_ptr ptr) override
|
||||||
|
{
|
||||||
|
if (ptr)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
std::rethrow_exception(ptr);
|
||||||
|
}
|
||||||
|
catch (const std::exception &e)
|
||||||
|
{
|
||||||
|
LOG_ERROR << "onStreamError: " << e.what();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_INFO << "onStreamFinish";
|
||||||
|
}
|
||||||
|
respStream_->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
ResponseStreamPtr respStream_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class RequestStreamExampleCtrl : public HttpController<RequestStreamExampleCtrl>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
METHOD_LIST_BEGIN
|
||||||
|
ADD_METHOD_TO(RequestStreamExampleCtrl::stream_echo, "/stream_echo", Post);
|
||||||
|
ADD_METHOD_TO(RequestStreamExampleCtrl::stream_upload,
|
||||||
|
"/stream_upload",
|
||||||
|
Post);
|
||||||
|
METHOD_LIST_END
|
||||||
|
|
||||||
|
void stream_echo(
|
||||||
|
const HttpRequestPtr &,
|
||||||
|
RequestStreamPtr &&stream,
|
||||||
|
std::function<void(const HttpResponsePtr &)> &&callback) const
|
||||||
|
{
|
||||||
|
auto resp = drogon::HttpResponse::newAsyncStreamResponse(
|
||||||
|
[stream](ResponseStreamPtr respStream) {
|
||||||
|
stream->setStreamReader(
|
||||||
|
std::make_shared<StreamEchoReader>(std::move(respStream)));
|
||||||
|
});
|
||||||
|
callback(resp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void stream_upload(
|
||||||
|
const HttpRequestPtr &req,
|
||||||
|
RequestStreamPtr &&stream,
|
||||||
|
std::function<void(const HttpResponsePtr &)> &&callback) const
|
||||||
|
{
|
||||||
|
struct Entry
|
||||||
|
{
|
||||||
|
MultipartHeader header;
|
||||||
|
std::string tmpName;
|
||||||
|
std::ofstream file;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto files = std::make_shared<std::vector<Entry>>();
|
||||||
|
auto reader = RequestStreamReader::newMultipartReader(
|
||||||
|
req,
|
||||||
|
[files](MultipartHeader &&header) {
|
||||||
|
LOG_INFO << "Multipart name: " << header.name
|
||||||
|
<< ", filename:" << header.filename
|
||||||
|
<< ", contentType:" << header.contentType;
|
||||||
|
|
||||||
|
files->push_back({std::move(header)});
|
||||||
|
auto tmpName = drogon::utils::genRandomString(40);
|
||||||
|
if (!files->back().header.filename.empty())
|
||||||
|
{
|
||||||
|
files->back().tmpName = tmpName;
|
||||||
|
files->back().file.open("uploads/" + tmpName,
|
||||||
|
std::ios::trunc);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[files](const char *data, size_t length) {
|
||||||
|
if (files->back().tmpName.empty())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto ¤tFile = files->back().file;
|
||||||
|
if (length == 0)
|
||||||
|
{
|
||||||
|
LOG_INFO << "file finish";
|
||||||
|
if (currentFile.is_open())
|
||||||
|
{
|
||||||
|
currentFile.flush();
|
||||||
|
currentFile.close();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LOG_INFO << "data[" << length << "]: ";
|
||||||
|
if (currentFile.is_open())
|
||||||
|
{
|
||||||
|
LOG_INFO << "write file";
|
||||||
|
currentFile.write(data, length);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_ERROR << "file not open";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[files, callback = std::move(callback)](std::exception_ptr ex) {
|
||||||
|
if (ex)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
std::rethrow_exception(std::move(ex));
|
||||||
|
}
|
||||||
|
catch (const StreamError &e)
|
||||||
|
{
|
||||||
|
LOG_ERROR << "stream error: " << e.what();
|
||||||
|
}
|
||||||
|
catch (const std::exception &e)
|
||||||
|
{
|
||||||
|
LOG_ERROR << "multipart error: " << e.what();
|
||||||
|
}
|
||||||
|
auto resp = HttpResponse::newHttpResponse();
|
||||||
|
resp->setStatusCode(k400BadRequest);
|
||||||
|
resp->setBody("error\n");
|
||||||
|
callback(resp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_INFO << "stream finish, received " << files->size()
|
||||||
|
<< " files";
|
||||||
|
Json::Value respJson;
|
||||||
|
for (const auto &item : *files)
|
||||||
|
{
|
||||||
|
if (item.tmpName.empty())
|
||||||
|
continue;
|
||||||
|
Json::Value entry;
|
||||||
|
entry["name"] = item.header.name;
|
||||||
|
entry["filename"] = item.header.filename;
|
||||||
|
entry["tmpName"] = item.tmpName;
|
||||||
|
respJson.append(entry);
|
||||||
|
}
|
||||||
|
auto resp = HttpResponse::newHttpJsonResponse(respJson);
|
||||||
|
callback(resp);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
stream->setStreamReader(std::move(reader));
|
||||||
|
}
|
||||||
|
};
|
113
examples/async_stream/main.cc
Normal file
113
examples/async_stream/main.cc
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
#include <drogon/drogon.h>
|
||||||
|
#include <chrono>
|
||||||
|
#include <functional>
|
||||||
|
#include <mutex>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <trantor/utils/Logger.h>
|
||||||
|
#include <trantor/net/callbacks.h>
|
||||||
|
#include <trantor/net/TcpConnection.h>
|
||||||
|
|
||||||
|
using namespace drogon;
|
||||||
|
using namespace std::chrono_literals;
|
||||||
|
|
||||||
|
std::mutex mutex;
|
||||||
|
std::unordered_map<trantor::TcpConnectionPtr, std::function<void()>>
|
||||||
|
connMapping;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
app().registerHandler(
|
||||||
|
"/stream",
|
||||||
|
[](const HttpRequestPtr &req,
|
||||||
|
std::function<void(const HttpResponsePtr &)> &&callback) {
|
||||||
|
const auto &weakConnPtr = req->getConnectionPtr();
|
||||||
|
if (auto connPtr = weakConnPtr.lock())
|
||||||
|
{
|
||||||
|
std::lock_guard lk(mutex);
|
||||||
|
connMapping.emplace(std::move(connPtr), [] {
|
||||||
|
LOG_INFO << "call stop or other options!!!!";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
auto resp = drogon::HttpResponse::newAsyncStreamResponse(
|
||||||
|
[](drogon::ResponseStreamPtr stream) {
|
||||||
|
std::thread([stream =
|
||||||
|
std::shared_ptr<drogon::ResponseStream>{
|
||||||
|
std::move(stream)}]() mutable {
|
||||||
|
std::cout << std::boolalpha << stream->send("hello ")
|
||||||
|
<< std::endl;
|
||||||
|
std::this_thread::sleep_for(std::chrono::seconds(2));
|
||||||
|
std::cout << std::boolalpha << stream->send("world");
|
||||||
|
std::this_thread::sleep_for(std::chrono::seconds(2));
|
||||||
|
stream->close();
|
||||||
|
}).detach();
|
||||||
|
});
|
||||||
|
resp->setContentTypeCodeAndCustomString(
|
||||||
|
ContentType::CT_APPLICATION_JSON, "application/json");
|
||||||
|
callback(resp);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Example: register a stream-mode function handler
|
||||||
|
app().registerHandler(
|
||||||
|
"/stream_req",
|
||||||
|
[](const HttpRequestPtr &req,
|
||||||
|
RequestStreamPtr &&stream,
|
||||||
|
std::function<void(const HttpResponsePtr &)> &&callback) {
|
||||||
|
if (!stream)
|
||||||
|
{
|
||||||
|
LOG_INFO << "stream mode is not enabled";
|
||||||
|
auto resp = HttpResponse::newHttpResponse();
|
||||||
|
resp->setStatusCode(k400BadRequest);
|
||||||
|
resp->setBody("no stream");
|
||||||
|
callback(resp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto reader = RequestStreamReader::newReader(
|
||||||
|
[](const char *data, size_t length) {
|
||||||
|
LOG_INFO << "piece[" << length
|
||||||
|
<< "]: " << std::string_view{data, length};
|
||||||
|
},
|
||||||
|
[callback = std::move(callback)](std::exception_ptr ex) {
|
||||||
|
auto resp = HttpResponse::newHttpResponse();
|
||||||
|
if (ex)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
std::rethrow_exception(std::move(ex));
|
||||||
|
}
|
||||||
|
catch (const std::exception &e)
|
||||||
|
{
|
||||||
|
LOG_ERROR << "stream error: " << e.what();
|
||||||
|
}
|
||||||
|
resp->setStatusCode(k400BadRequest);
|
||||||
|
resp->setBody("error\n");
|
||||||
|
callback(resp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_INFO << "stream finish";
|
||||||
|
resp->setBody("success\n");
|
||||||
|
callback(resp);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
stream->setStreamReader(std::move(reader));
|
||||||
|
},
|
||||||
|
{Post});
|
||||||
|
|
||||||
|
LOG_INFO << "Server running on 127.0.0.1:8848";
|
||||||
|
app().enableRequestStream(); // This is for request stream.
|
||||||
|
app().setConnectionCallback([](const trantor::TcpConnectionPtr &conn) {
|
||||||
|
if (conn->disconnected())
|
||||||
|
{
|
||||||
|
std::lock_guard lk(mutex);
|
||||||
|
if (auto it = connMapping.find(conn); it != connMapping.end())
|
||||||
|
{
|
||||||
|
LOG_INFO << "disconnect";
|
||||||
|
connMapping[conn]();
|
||||||
|
connMapping.erase(conn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
app().addListener("127.0.0.1", 8848).run();
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
#include "BenchmarkCtrl.h"
|
#include "BenchmarkCtrl.h"
|
||||||
|
|
||||||
void BenchmarkCtrl::asyncHandleHttpRequest(
|
void BenchmarkCtrl::asyncHandleHttpRequest(
|
||||||
const HttpRequestPtr &,
|
const HttpRequestPtr &,
|
||||||
std::function<void(const HttpResponsePtr &)> &&callback)
|
std::function<void(const HttpResponsePtr &)> &&callback)
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <drogon/HttpSimpleController.h>
|
#include <drogon/HttpSimpleController.h>
|
||||||
using namespace drogon;
|
using namespace drogon;
|
||||||
|
|
||||||
class BenchmarkCtrl : public drogon::HttpSimpleController<BenchmarkCtrl>
|
class BenchmarkCtrl : public drogon::HttpSimpleController<BenchmarkCtrl>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void asyncHandleHttpRequest(
|
void asyncHandleHttpRequest(
|
||||||
const HttpRequestPtr &req,
|
const HttpRequestPtr &req,
|
||||||
std::function<void(const HttpResponsePtr &)> &&callback) override;
|
std::function<void(const HttpResponsePtr &)> &&callback) override;
|
||||||
PATH_LIST_BEGIN
|
PATH_LIST_BEGIN
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
#include "JsonCtrl.h"
|
#include "JsonCtrl.h"
|
||||||
|
|
||||||
void JsonCtrl::asyncHandleHttpRequest(
|
void JsonCtrl::asyncHandleHttpRequest(
|
||||||
const HttpRequestPtr &,
|
const HttpRequestPtr &,
|
||||||
std::function<void(const HttpResponsePtr &)> &&callback)
|
std::function<void(const HttpResponsePtr &)> &&callback)
|
||||||
{
|
{
|
||||||
Json::Value ret;
|
Json::Value ret;
|
||||||
ret["message"] = "Hello, World!";
|
ret["message"] = "Hello, World!";
|
||||||
auto resp = HttpResponse::newHttpJsonResponse(ret);
|
auto resp = HttpResponse::newHttpJsonResponse(std::move(ret));
|
||||||
callback(resp);
|
callback(resp);
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <drogon/HttpSimpleController.h>
|
#include <drogon/HttpSimpleController.h>
|
||||||
using namespace drogon;
|
using namespace drogon;
|
||||||
|
|
||||||
class JsonCtrl : public drogon::HttpSimpleController<JsonCtrl>
|
class JsonCtrl : public drogon::HttpSimpleController<JsonCtrl>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void asyncHandleHttpRequest(
|
void asyncHandleHttpRequest(
|
||||||
const HttpRequestPtr &req,
|
const HttpRequestPtr &req,
|
||||||
std::function<void(const HttpResponsePtr &)> &&callback) override;
|
std::function<void(const HttpResponsePtr &)> &&callback) override;
|
||||||
PATH_LIST_BEGIN
|
PATH_LIST_BEGIN
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include <drogon/drogon.h>
|
#include <drogon/drogon.h>
|
||||||
|
|
||||||
using namespace drogon;
|
using namespace drogon;
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
app()
|
app()
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
#include <drogon/drogon.h>
|
#include <drogon/drogon.h>
|
||||||
#include <iostream>
|
|
||||||
#include <future>
|
#include <future>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/tcp.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace drogon;
|
using namespace drogon;
|
||||||
|
|
||||||
@ -11,6 +17,28 @@ int main()
|
|||||||
trantor::Logger::setLogLevel(trantor::Logger::kTrace);
|
trantor::Logger::setLogLevel(trantor::Logger::kTrace);
|
||||||
{
|
{
|
||||||
auto client = HttpClient::newHttpClient("http://www.baidu.com");
|
auto client = HttpClient::newHttpClient("http://www.baidu.com");
|
||||||
|
client->setSockOptCallback([](int fd) {
|
||||||
|
std::cout << "setSockOptCallback:" << fd << std::endl;
|
||||||
|
#ifdef __linux__
|
||||||
|
int optval = 10;
|
||||||
|
::setsockopt(fd,
|
||||||
|
SOL_TCP,
|
||||||
|
TCP_KEEPCNT,
|
||||||
|
&optval,
|
||||||
|
static_cast<socklen_t>(sizeof optval));
|
||||||
|
::setsockopt(fd,
|
||||||
|
SOL_TCP,
|
||||||
|
TCP_KEEPIDLE,
|
||||||
|
&optval,
|
||||||
|
static_cast<socklen_t>(sizeof optval));
|
||||||
|
::setsockopt(fd,
|
||||||
|
SOL_TCP,
|
||||||
|
TCP_KEEPINTVL,
|
||||||
|
&optval,
|
||||||
|
static_cast<socklen_t>(sizeof optval));
|
||||||
|
#endif
|
||||||
|
});
|
||||||
|
|
||||||
auto req = HttpRequest::newHttpRequest();
|
auto req = HttpRequest::newHttpRequest();
|
||||||
req->setMethod(drogon::Get);
|
req->setMethod(drogon::Get);
|
||||||
req->setPath("/s");
|
req->setPath("/s");
|
||||||
@ -20,7 +48,15 @@ int main()
|
|||||||
for (int i = 0; i < 10; ++i)
|
for (int i = 0; i < 10; ++i)
|
||||||
{
|
{
|
||||||
client->sendRequest(
|
client->sendRequest(
|
||||||
req, [](ReqResult, const HttpResponsePtr &response) {
|
req, [](ReqResult result, const HttpResponsePtr &response) {
|
||||||
|
if (result != ReqResult::Ok)
|
||||||
|
{
|
||||||
|
std::cout
|
||||||
|
<< "error while sending request to server! result: "
|
||||||
|
<< result << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
std::cout << "receive response!" << std::endl;
|
std::cout << "receive response!" << std::endl;
|
||||||
// auto headers=response.
|
// auto headers=response.
|
||||||
++nth_resp;
|
++nth_resp;
|
||||||
@ -36,6 +72,8 @@ int main()
|
|||||||
std::cout << "count=" << nth_resp << std::endl;
|
std::cout << "count=" << nth_resp << std::endl;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
std::cout << "requestsBufferSize:" << client->requestsBufferSize()
|
||||||
|
<< std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
app().run();
|
app().run();
|
||||||
|
153
examples/cors/main.cc
Normal file
153
examples/cors/main.cc
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
#include <drogon/HttpAppFramework.h>
|
||||||
|
#include <drogon/HttpResponse.h>
|
||||||
|
#include <drogon/drogon.h>
|
||||||
|
#include "trantor/utils/Logger.h"
|
||||||
|
|
||||||
|
using namespace drogon;
|
||||||
|
|
||||||
|
/// Configure Cross-Origin Resource Sharing (CORS) support.
|
||||||
|
///
|
||||||
|
/// This function registers both synchronous pre-processing advice for handling
|
||||||
|
/// OPTIONS preflight requests and post-handling advice to inject CORS headers
|
||||||
|
/// into all responses dynamically based on the incoming request headers.
|
||||||
|
void setupCors()
|
||||||
|
{
|
||||||
|
// Register sync advice to handle CORS preflight (OPTIONS) requests
|
||||||
|
drogon::app().registerSyncAdvice([](const drogon::HttpRequestPtr &req)
|
||||||
|
-> drogon::HttpResponsePtr {
|
||||||
|
if (req->method() == drogon::HttpMethod::Options)
|
||||||
|
{
|
||||||
|
auto resp = drogon::HttpResponse::newHttpResponse();
|
||||||
|
|
||||||
|
// Set Access-Control-Allow-Origin header based on the Origin
|
||||||
|
// request header
|
||||||
|
const auto &origin = req->getHeader("Origin");
|
||||||
|
if (!origin.empty())
|
||||||
|
{
|
||||||
|
resp->addHeader("Access-Control-Allow-Origin", origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set Access-Control-Allow-Methods based on the requested method
|
||||||
|
const auto &requestMethod =
|
||||||
|
req->getHeader("Access-Control-Request-Method");
|
||||||
|
if (!requestMethod.empty())
|
||||||
|
{
|
||||||
|
resp->addHeader("Access-Control-Allow-Methods", requestMethod);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow credentials to be included in cross-origin requests
|
||||||
|
resp->addHeader("Access-Control-Allow-Credentials", "true");
|
||||||
|
|
||||||
|
// Set allowed headers from the Access-Control-Request-Headers
|
||||||
|
// header
|
||||||
|
const auto &requestHeaders =
|
||||||
|
req->getHeader("Access-Control-Request-Headers");
|
||||||
|
if (!requestHeaders.empty())
|
||||||
|
{
|
||||||
|
resp->addHeader("Access-Control-Allow-Headers", requestHeaders);
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::move(resp);
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
});
|
||||||
|
|
||||||
|
// Register post-handling advice to add CORS headers to all responses
|
||||||
|
drogon::app().registerPostHandlingAdvice(
|
||||||
|
[](const drogon::HttpRequestPtr &req,
|
||||||
|
const drogon::HttpResponsePtr &resp) -> void {
|
||||||
|
// Set Access-Control-Allow-Origin based on the Origin request
|
||||||
|
// header
|
||||||
|
const auto &origin = req->getHeader("Origin");
|
||||||
|
if (!origin.empty())
|
||||||
|
{
|
||||||
|
resp->addHeader("Access-Control-Allow-Origin", origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reflect the requested Access-Control-Request-Method back in the
|
||||||
|
// response
|
||||||
|
const auto &requestMethod =
|
||||||
|
req->getHeader("Access-Control-Request-Method");
|
||||||
|
if (!requestMethod.empty())
|
||||||
|
{
|
||||||
|
resp->addHeader("Access-Control-Allow-Methods", requestMethod);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow credentials to be included in cross-origin requests
|
||||||
|
resp->addHeader("Access-Control-Allow-Credentials", "true");
|
||||||
|
|
||||||
|
// Reflect the requested Access-Control-Request-Headers back
|
||||||
|
const auto &requestHeaders =
|
||||||
|
req->getHeader("Access-Control-Request-Headers");
|
||||||
|
if (!requestHeaders.empty())
|
||||||
|
{
|
||||||
|
resp->addHeader("Access-Control-Allow-Headers", requestHeaders);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main function to start the Drogon application with CORS-enabled routes.
|
||||||
|
* This example includes:
|
||||||
|
* - A simple GET endpoint `/hello` that returns a greeting message.
|
||||||
|
* - A POST endpoint `/echo` that echoes back the request body.
|
||||||
|
* You can test with curl to test the CORS support:
|
||||||
|
*
|
||||||
|
```
|
||||||
|
curl -i -X OPTIONS http://localhost:8000/echo \
|
||||||
|
-H "Origin: http://localhost:3000" \
|
||||||
|
-H "Access-Control-Request-Method: POST" \
|
||||||
|
-H "Access-Control-Request-Headers: Content-Type"
|
||||||
|
```
|
||||||
|
or
|
||||||
|
```
|
||||||
|
curl -i -X POST http://localhost:8000/echo \
|
||||||
|
-H "Origin: http://localhost:3000" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"key":"value"}'
|
||||||
|
```
|
||||||
|
*/
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
// Listen on port 8000 for all interfaces
|
||||||
|
app().addListener("0.0.0.0", 8000);
|
||||||
|
|
||||||
|
// Setup CORS support
|
||||||
|
setupCors();
|
||||||
|
|
||||||
|
// Register /hello route for GET and OPTIONS methods
|
||||||
|
app().registerHandler(
|
||||||
|
"/hello",
|
||||||
|
[](const HttpRequestPtr &req,
|
||||||
|
std::function<void(const HttpResponsePtr &)> &&callback) {
|
||||||
|
auto resp = HttpResponse::newHttpResponse();
|
||||||
|
resp->setBody("Hello from Drogon!");
|
||||||
|
|
||||||
|
// Log client IP address
|
||||||
|
LOG_INFO << "Request to /hello from " << req->getPeerAddr().toIp();
|
||||||
|
|
||||||
|
callback(resp);
|
||||||
|
},
|
||||||
|
{Get, Options});
|
||||||
|
|
||||||
|
// Register /echo route for POST and OPTIONS methods
|
||||||
|
app().registerHandler(
|
||||||
|
"/echo",
|
||||||
|
[](const HttpRequestPtr &req,
|
||||||
|
std::function<void(const HttpResponsePtr &)> &&callback) {
|
||||||
|
auto resp = HttpResponse::newHttpResponse();
|
||||||
|
resp->setBody(std::string("Echo: ").append(req->getBody()));
|
||||||
|
|
||||||
|
// Log client IP and request body
|
||||||
|
LOG_INFO << "Request to /echo from " << req->getPeerAddr().toIp();
|
||||||
|
LOG_INFO << "Echo content: " << req->getBody();
|
||||||
|
|
||||||
|
callback(resp);
|
||||||
|
},
|
||||||
|
{Post, Options});
|
||||||
|
|
||||||
|
// Start the application main loop
|
||||||
|
app().run();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -43,4 +43,4 @@ int main()
|
|||||||
.setUploadPath("./uploads")
|
.setUploadPath("./uploads")
|
||||||
.addListener("127.0.0.1", 8848)
|
.addListener("127.0.0.1", 8848)
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
@ -37,4 +37,4 @@ class SayHello : public HttpController<SayHello>
|
|||||||
"Hi there, this is another hello from the SayHello Controller");
|
"Hi there, this is another hello from the SayHello Controller");
|
||||||
callback(resp);
|
callback(resp);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -14,7 +14,7 @@ class HelloViewController : public HttpSimpleController<HelloViewController>
|
|||||||
// Also unlike HttpContoller, HttpSimpleController does not automatically
|
// Also unlike HttpContoller, HttpSimpleController does not automatically
|
||||||
// prepend the namespace and class name to the path. Thus the path of this
|
// prepend the namespace and class name to the path. Thus the path of this
|
||||||
// controller is at "/view".
|
// controller is at "/view".
|
||||||
PATH_ADD("/view")
|
PATH_ADD("/view");
|
||||||
PATH_LIST_END
|
PATH_LIST_END
|
||||||
|
|
||||||
void asyncHandleHttpRequest(
|
void asyncHandleHttpRequest(
|
||||||
@ -26,4 +26,4 @@ class HelloViewController : public HttpSimpleController<HelloViewController>
|
|||||||
auto resp = HttpResponse::newHttpViewResponse("HelloView", data);
|
auto resp = HttpResponse::newHttpViewResponse("HelloView", data);
|
||||||
callback(resp);
|
callback(resp);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,3 +1,11 @@
|
|||||||
|
#include <trantor/utils/Logger.h>
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <ws2tcpip.h>
|
||||||
|
#else
|
||||||
|
#include <netinet/tcp.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <drogon/drogon.h>
|
#include <drogon/drogon.h>
|
||||||
using namespace drogon;
|
using namespace drogon;
|
||||||
|
|
||||||
@ -8,8 +16,10 @@ int main()
|
|||||||
// sent to Drogon
|
// sent to Drogon
|
||||||
app().registerHandler(
|
app().registerHandler(
|
||||||
"/",
|
"/",
|
||||||
[](const HttpRequestPtr &,
|
[](const HttpRequestPtr &request,
|
||||||
std::function<void(const HttpResponsePtr &)> &&callback) {
|
std::function<void(const HttpResponsePtr &)> &&callback) {
|
||||||
|
LOG_INFO << "connected:"
|
||||||
|
<< (request->connected() ? "true" : "false");
|
||||||
auto resp = HttpResponse::newHttpResponse();
|
auto resp = HttpResponse::newHttpResponse();
|
||||||
resp->setBody("Hello, World!");
|
resp->setBody("Hello, World!");
|
||||||
callback(resp);
|
callback(resp);
|
||||||
@ -52,15 +62,32 @@ int main()
|
|||||||
[](const HttpRequestPtr &req,
|
[](const HttpRequestPtr &req,
|
||||||
std::function<void(const HttpResponsePtr &)> &&callback) {
|
std::function<void(const HttpResponsePtr &)> &&callback) {
|
||||||
auto resp = HttpResponse::newHttpResponse();
|
auto resp = HttpResponse::newHttpResponse();
|
||||||
std::string name = req->getParameter("user");
|
auto name = req->getOptionalParameter<std::string>("user");
|
||||||
if (name == "")
|
if (!name)
|
||||||
resp->setBody("Please tell me your name");
|
resp->setBody("Please tell me your name");
|
||||||
else
|
else
|
||||||
resp->setBody("Hello, " + name + "!");
|
resp->setBody("Hello, " + name.value() + "!");
|
||||||
callback(resp);
|
callback(resp);
|
||||||
},
|
},
|
||||||
{Get});
|
{Get});
|
||||||
|
|
||||||
|
app()
|
||||||
|
.setBeforeListenSockOptCallback([](int fd) {
|
||||||
|
LOG_INFO << "setBeforeListenSockOptCallback:" << fd;
|
||||||
|
#ifdef _WIN32
|
||||||
|
#elif __linux__
|
||||||
|
int enable = 1;
|
||||||
|
if (setsockopt(
|
||||||
|
fd, IPPROTO_TCP, TCP_FASTOPEN, &enable, sizeof(enable)) ==
|
||||||
|
-1)
|
||||||
|
{
|
||||||
|
LOG_INFO << "setsockopt TCP_FASTOPEN failed";
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#endif
|
||||||
|
})
|
||||||
|
.setAfterAcceptSockOptCallback([](int) {});
|
||||||
|
|
||||||
// Ask Drogon to listen on 127.0.0.1 port 8848. Drogon supports listening
|
// Ask Drogon to listen on 127.0.0.1 port 8848. Drogon supports listening
|
||||||
// on multiple IP addresses by adding multiple listeners. For example, if
|
// on multiple IP addresses by adding multiple listeners. For example, if
|
||||||
// you want the server also listen on 127.0.0.1 port 5555. Just add another
|
// you want the server also listen on 127.0.0.1 port 5555. Just add another
|
||||||
|
@ -24,7 +24,7 @@ Create a new JSON object associated with the token
|
|||||||
|
|
||||||
* **method**: POST
|
* **method**: POST
|
||||||
* **URL params**: None
|
* **URL params**: None
|
||||||
* **Body**: The inital JSON object to store
|
* **Body**: The initial JSON object to store
|
||||||
* **Success response**
|
* **Success response**
|
||||||
* **Code**: 200
|
* **Code**: 200
|
||||||
* **Content**: `{"ok":true}`
|
* **Content**: `{"ok":true}`
|
||||||
@ -121,7 +121,7 @@ Creating new data
|
|||||||
> {"ok":true}
|
> {"ok":true}
|
||||||
Retrieving value of data["foo"]["bar"]
|
Retrieving value of data["foo"]["bar"]
|
||||||
> 42
|
> 42
|
||||||
Modifing data
|
Modifying data
|
||||||
> {"ok":true}
|
> {"ok":true}
|
||||||
Now data["foo"]["bar"] no longer exists
|
Now data["foo"]["bar"] no longer exists
|
||||||
> {"ok":false}
|
> {"ok":false}
|
||||||
|
@ -50,8 +50,8 @@ class JsonStore : public HttpController<JsonStore>
|
|||||||
ADD_METHOD_VIA_REGEX(JsonStore::updateItem, "/([a-f0-9]{64})/(.*)", Put);
|
ADD_METHOD_VIA_REGEX(JsonStore::updateItem, "/([a-f0-9]{64})/(.*)", Put);
|
||||||
METHOD_LIST_END
|
METHOD_LIST_END
|
||||||
|
|
||||||
void getToken(const HttpRequestPtr&,
|
void getToken(const HttpRequestPtr &,
|
||||||
std::function<void(const HttpResponsePtr&)>&& callback)
|
std::function<void(const HttpResponsePtr &)> &&callback)
|
||||||
{
|
{
|
||||||
std::string randomString = getRandomString(64);
|
std::string randomString = getRandomString(64);
|
||||||
Json::Value res;
|
Json::Value res;
|
||||||
@ -60,10 +60,10 @@ class JsonStore : public HttpController<JsonStore>
|
|||||||
callback(HttpResponse::newHttpJsonResponse(std::move(res)));
|
callback(HttpResponse::newHttpJsonResponse(std::move(res)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void getItem(const HttpRequestPtr&,
|
void getItem(const HttpRequestPtr &,
|
||||||
std::function<void(const HttpResponsePtr&)>&& callback,
|
std::function<void(const HttpResponsePtr &)> &&callback,
|
||||||
const std::string& token,
|
const std::string &token,
|
||||||
const std::string& path)
|
const std::string &path)
|
||||||
{
|
{
|
||||||
auto itemPtr = [this, &token]() -> std::shared_ptr<DataItem> {
|
auto itemPtr = [this, &token]() -> std::shared_ptr<DataItem> {
|
||||||
// It is possible that the item is being removed while another
|
// It is possible that the item is being removed while another
|
||||||
@ -81,12 +81,12 @@ class JsonStore : public HttpController<JsonStore>
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& item = *itemPtr;
|
auto &item = *itemPtr;
|
||||||
// Prevents another thread from writing to the same item while this
|
// Prevents another thread from writing to the same item while this
|
||||||
// thread reads. Could cause blockage if multiple clients are asking to
|
// thread reads. Could cause blockage if multiple clients are asking to
|
||||||
// read the same object. But that should be rare.
|
// read the same object. But that should be rare.
|
||||||
std::lock_guard<std::mutex> lock(item.mtx);
|
std::lock_guard<std::mutex> lock(item.mtx);
|
||||||
Json::Value* valuePtr = walkJson(item.item, path);
|
Json::Value *valuePtr = walkJson(item.item, path);
|
||||||
|
|
||||||
if (valuePtr == nullptr)
|
if (valuePtr == nullptr)
|
||||||
{
|
{
|
||||||
@ -98,10 +98,10 @@ class JsonStore : public HttpController<JsonStore>
|
|||||||
callback(resp);
|
callback(resp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateItem(const HttpRequestPtr& req,
|
void updateItem(const HttpRequestPtr &req,
|
||||||
std::function<void(const HttpResponsePtr&)>&& callback,
|
std::function<void(const HttpResponsePtr &)> &&callback,
|
||||||
const std::string& token,
|
const std::string &token,
|
||||||
const std::string& path)
|
const std::string &path)
|
||||||
{
|
{
|
||||||
auto jsonPtr = req->jsonObject();
|
auto jsonPtr = req->jsonObject();
|
||||||
auto itemPtr = [this, &token]() -> std::shared_ptr<DataItem> {
|
auto itemPtr = [this, &token]() -> std::shared_ptr<DataItem> {
|
||||||
@ -121,9 +121,9 @@ class JsonStore : public HttpController<JsonStore>
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& item = *itemPtr;
|
auto &item = *itemPtr;
|
||||||
std::lock_guard<std::mutex> lock(item.mtx);
|
std::lock_guard<std::mutex> lock(item.mtx);
|
||||||
Json::Value* valuePtr = walkJson(item.item, path, 1);
|
Json::Value *valuePtr = walkJson(item.item, path, 1);
|
||||||
|
|
||||||
if (valuePtr == nullptr)
|
if (valuePtr == nullptr)
|
||||||
{
|
{
|
||||||
@ -137,9 +137,9 @@ class JsonStore : public HttpController<JsonStore>
|
|||||||
callback(makeSuccessResponse());
|
callback(makeSuccessResponse());
|
||||||
}
|
}
|
||||||
|
|
||||||
void createItem(const HttpRequestPtr& req,
|
void createItem(const HttpRequestPtr &req,
|
||||||
std::function<void(const HttpResponsePtr&)>&& callback,
|
std::function<void(const HttpResponsePtr &)> &&callback,
|
||||||
const std::string& token)
|
const std::string &token)
|
||||||
{
|
{
|
||||||
auto jsonPtr = req->jsonObject();
|
auto jsonPtr = req->jsonObject();
|
||||||
if (jsonPtr == nullptr)
|
if (jsonPtr == nullptr)
|
||||||
@ -163,9 +163,9 @@ class JsonStore : public HttpController<JsonStore>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void deleteItem(const HttpRequestPtr&,
|
void deleteItem(const HttpRequestPtr &,
|
||||||
std::function<void(const HttpResponsePtr&)>&& callback,
|
std::function<void(const HttpResponsePtr &)> &&callback,
|
||||||
const std::string& token)
|
const std::string &token)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(storageMtx_);
|
std::lock_guard<std::mutex> lock(storageMtx_);
|
||||||
dataStore_.erase(token);
|
dataStore_.erase(token);
|
||||||
@ -174,19 +174,19 @@ class JsonStore : public HttpController<JsonStore>
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static Json::Value* walkJson(Json::Value& json,
|
static Json::Value *walkJson(Json::Value &json,
|
||||||
const std::string& path,
|
const std::string &path,
|
||||||
size_t ignore_back = 0)
|
size_t ignore_back = 0)
|
||||||
{
|
{
|
||||||
auto pathElem = utils::splitString(path, "/", false);
|
auto pathElem = utils::splitString(path, "/", false);
|
||||||
if (pathElem.size() >= ignore_back)
|
if (pathElem.size() >= ignore_back)
|
||||||
pathElem.resize(pathElem.size() - ignore_back);
|
pathElem.resize(pathElem.size() - ignore_back);
|
||||||
Json::Value* valuePtr = &json;
|
Json::Value *valuePtr = &json;
|
||||||
for (const auto& elem : pathElem)
|
for (const auto &elem : pathElem)
|
||||||
{
|
{
|
||||||
if (valuePtr->isArray())
|
if (valuePtr->isArray())
|
||||||
{
|
{
|
||||||
Json::Value& value = (*valuePtr)[std::stoi(elem)];
|
Json::Value &value = (*valuePtr)[std::stoi(elem)];
|
||||||
if (value.isNull())
|
if (value.isNull())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
@ -194,7 +194,7 @@ class JsonStore : public HttpController<JsonStore>
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Json::Value& value = (*valuePtr)[elem];
|
Json::Value &value = (*valuePtr)[elem];
|
||||||
if (value.isNull())
|
if (value.isNull())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
@ -211,4 +211,4 @@ class JsonStore : public HttpController<JsonStore>
|
|||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
app().addListener("127.0.0.1", 8848).run();
|
app().addListener("127.0.0.1", 8848).run();
|
||||||
}
|
}
|
||||||
|
@ -65,4 +65,4 @@ int main()
|
|||||||
.enableSession(24h)
|
.enableSession(24h)
|
||||||
.addListener("127.0.0.1", 8848)
|
.addListener("127.0.0.1", 8848)
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
561
examples/prometheus_example/.gitignore
vendored
Normal file
561
examples/prometheus_example/.gitignore
vendored
Normal file
@ -0,0 +1,561 @@
|
|||||||
|
# Created by https://www.toptal.com/developers/gitignore/api/intellij+all,visualstudio,visualstudiocode,cmake,c,c++
|
||||||
|
# Edit at https://www.toptal.com/developers/gitignore?templates=intellij+all,visualstudio,visualstudiocode,cmake,c,c++
|
||||||
|
|
||||||
|
### C ###
|
||||||
|
# Prerequisites
|
||||||
|
*.d
|
||||||
|
|
||||||
|
# Object files
|
||||||
|
*.o
|
||||||
|
*.ko
|
||||||
|
*.obj
|
||||||
|
*.elf
|
||||||
|
|
||||||
|
# Linker output
|
||||||
|
*.ilk
|
||||||
|
*.map
|
||||||
|
*.exp
|
||||||
|
|
||||||
|
# Precompiled Headers
|
||||||
|
*.gch
|
||||||
|
*.pch
|
||||||
|
|
||||||
|
# Libraries
|
||||||
|
*.lib
|
||||||
|
*.a
|
||||||
|
*.la
|
||||||
|
*.lo
|
||||||
|
|
||||||
|
# Shared objects (inc. Windows DLLs)
|
||||||
|
*.dll
|
||||||
|
*.so
|
||||||
|
*.so.*
|
||||||
|
*.dylib
|
||||||
|
|
||||||
|
# Executables
|
||||||
|
*.exe
|
||||||
|
*.out
|
||||||
|
*.app
|
||||||
|
*.i*86
|
||||||
|
*.x86_64
|
||||||
|
*.hex
|
||||||
|
|
||||||
|
# Debug files
|
||||||
|
*.dSYM/
|
||||||
|
*.su
|
||||||
|
*.idb
|
||||||
|
*.pdb
|
||||||
|
|
||||||
|
# Kernel Module Compile Results
|
||||||
|
*.mod*
|
||||||
|
*.cmd
|
||||||
|
.tmp_versions/
|
||||||
|
modules.order
|
||||||
|
Module.symvers
|
||||||
|
Mkfile.old
|
||||||
|
dkms.conf
|
||||||
|
|
||||||
|
### C++ ###
|
||||||
|
# Prerequisites
|
||||||
|
|
||||||
|
# Compiled Object files
|
||||||
|
*.slo
|
||||||
|
|
||||||
|
# Precompiled Headers
|
||||||
|
|
||||||
|
# Linker files
|
||||||
|
|
||||||
|
# Debugger Files
|
||||||
|
|
||||||
|
# Compiled Dynamic libraries
|
||||||
|
|
||||||
|
# Fortran module files
|
||||||
|
*.mod
|
||||||
|
*.smod
|
||||||
|
|
||||||
|
# Compiled Static libraries
|
||||||
|
*.lai
|
||||||
|
|
||||||
|
# Executables
|
||||||
|
|
||||||
|
### CMake ###
|
||||||
|
CMakeLists.txt.user
|
||||||
|
CMakeCache.txt
|
||||||
|
CMakeFiles
|
||||||
|
CMakeScripts
|
||||||
|
Testing
|
||||||
|
Makefile
|
||||||
|
cmake_install.cmake
|
||||||
|
install_manifest.txt
|
||||||
|
compile_commands.json
|
||||||
|
CTestTestfile.cmake
|
||||||
|
_deps
|
||||||
|
CMakeUserPresets.json
|
||||||
|
|
||||||
|
### CMake Patch ###
|
||||||
|
# External projects
|
||||||
|
*-prefix/
|
||||||
|
|
||||||
|
### Intellij+all ###
|
||||||
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||||
|
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||||
|
|
||||||
|
# User-specific stuff
|
||||||
|
.idea/**/workspace.xml
|
||||||
|
.idea/**/tasks.xml
|
||||||
|
.idea/**/usage.statistics.xml
|
||||||
|
.idea/**/dictionaries
|
||||||
|
.idea/**/shelf
|
||||||
|
|
||||||
|
# Generated files
|
||||||
|
.idea/**/contentModel.xml
|
||||||
|
|
||||||
|
# Sensitive or high-churn files
|
||||||
|
.idea/**/dataSources/
|
||||||
|
.idea/**/dataSources.ids
|
||||||
|
.idea/**/dataSources.local.xml
|
||||||
|
.idea/**/sqlDataSources.xml
|
||||||
|
.idea/**/dynamic.xml
|
||||||
|
.idea/**/uiDesigner.xml
|
||||||
|
.idea/**/dbnavigator.xml
|
||||||
|
|
||||||
|
# Gradle
|
||||||
|
.idea/**/gradle.xml
|
||||||
|
.idea/**/libraries
|
||||||
|
|
||||||
|
# Gradle and Maven with auto-import
|
||||||
|
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||||
|
# since they will be recreated, and may cause churn. Uncomment if using
|
||||||
|
# auto-import.
|
||||||
|
# .idea/artifacts
|
||||||
|
# .idea/compiler.xml
|
||||||
|
# .idea/jarRepositories.xml
|
||||||
|
# .idea/modules.xml
|
||||||
|
# .idea/*.iml
|
||||||
|
# .idea/modules
|
||||||
|
# *.iml
|
||||||
|
# *.ipr
|
||||||
|
|
||||||
|
# CMake
|
||||||
|
cmake-build-*/
|
||||||
|
|
||||||
|
# Mongo Explorer plugin
|
||||||
|
.idea/**/mongoSettings.xml
|
||||||
|
|
||||||
|
# File-based project format
|
||||||
|
*.iws
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
out/
|
||||||
|
|
||||||
|
# mpeltonen/sbt-idea plugin
|
||||||
|
.idea_modules/
|
||||||
|
|
||||||
|
# JIRA plugin
|
||||||
|
atlassian-ide-plugin.xml
|
||||||
|
|
||||||
|
# Cursive Clojure plugin
|
||||||
|
.idea/replstate.xml
|
||||||
|
|
||||||
|
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||||
|
com_crashlytics_export_strings.xml
|
||||||
|
crashlytics.properties
|
||||||
|
crashlytics-build.properties
|
||||||
|
fabric.properties
|
||||||
|
|
||||||
|
# Editor-based Rest Client
|
||||||
|
.idea/httpRequests
|
||||||
|
|
||||||
|
# Android studio 3.1+ serialized cache file
|
||||||
|
.idea/caches/build_file_checksums.ser
|
||||||
|
|
||||||
|
### Intellij+all Patch ###
|
||||||
|
# Ignores the whole .idea folder and all .iml files
|
||||||
|
# See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360
|
||||||
|
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023
|
||||||
|
|
||||||
|
*.iml
|
||||||
|
modules.xml
|
||||||
|
.idea/misc.xml
|
||||||
|
*.ipr
|
||||||
|
|
||||||
|
# Sonarlint plugin
|
||||||
|
.idea/sonarlint
|
||||||
|
|
||||||
|
### VisualStudioCode ###
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/tasks.json
|
||||||
|
!.vscode/launch.json
|
||||||
|
*.code-workspace
|
||||||
|
|
||||||
|
### VisualStudioCode Patch ###
|
||||||
|
# Ignore all local history of files
|
||||||
|
.history
|
||||||
|
.ionide
|
||||||
|
|
||||||
|
### VisualStudio ###
|
||||||
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
|
## files generated by popular Visual Studio add-ons.
|
||||||
|
##
|
||||||
|
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||||
|
|
||||||
|
# User-specific files
|
||||||
|
*.rsuser
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.userosscache
|
||||||
|
*.sln.docstates
|
||||||
|
|
||||||
|
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||||
|
*.userprefs
|
||||||
|
|
||||||
|
# Mono auto generated files
|
||||||
|
mono_crash.*
|
||||||
|
|
||||||
|
# Build results
|
||||||
|
[Dd]ebug/
|
||||||
|
[Dd]ebugPublic/
|
||||||
|
[Rr]elease/
|
||||||
|
[Rr]eleases/
|
||||||
|
x64/
|
||||||
|
x86/
|
||||||
|
[Ww][Ii][Nn]32/
|
||||||
|
[Aa][Rr][Mm]/
|
||||||
|
[Aa][Rr][Mm]64/
|
||||||
|
bld/
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
[Ll]og/
|
||||||
|
[Ll]ogs/
|
||||||
|
|
||||||
|
# Visual Studio 2015/2017 cache/options directory
|
||||||
|
.vs/
|
||||||
|
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||||
|
#wwwroot/
|
||||||
|
|
||||||
|
# Visual Studio 2017 auto generated files
|
||||||
|
Generated\ Files/
|
||||||
|
|
||||||
|
# MSTest test Results
|
||||||
|
[Tt]est[Rr]esult*/
|
||||||
|
[Bb]uild[Ll]og.*
|
||||||
|
|
||||||
|
# NUnit
|
||||||
|
*.VisualState.xml
|
||||||
|
TestResult.xml
|
||||||
|
nunit-*.xml
|
||||||
|
|
||||||
|
# Build Results of an ATL Project
|
||||||
|
[Dd]ebugPS/
|
||||||
|
[Rr]eleasePS/
|
||||||
|
dlldata.c
|
||||||
|
|
||||||
|
# Benchmark Results
|
||||||
|
BenchmarkDotNet.Artifacts/
|
||||||
|
|
||||||
|
# .NET Core
|
||||||
|
project.lock.json
|
||||||
|
project.fragment.lock.json
|
||||||
|
artifacts/
|
||||||
|
|
||||||
|
# ASP.NET Scaffolding
|
||||||
|
ScaffoldingReadMe.txt
|
||||||
|
|
||||||
|
# StyleCop
|
||||||
|
StyleCopReport.xml
|
||||||
|
|
||||||
|
# Files built by Visual Studio
|
||||||
|
*_i.c
|
||||||
|
*_p.c
|
||||||
|
*_h.h
|
||||||
|
*.meta
|
||||||
|
*.iobj
|
||||||
|
*.ipdb
|
||||||
|
*.pgc
|
||||||
|
*.pgd
|
||||||
|
*.rsp
|
||||||
|
*.sbr
|
||||||
|
*.tlb
|
||||||
|
*.tli
|
||||||
|
*.tlh
|
||||||
|
*.tmp
|
||||||
|
*.tmp_proj
|
||||||
|
*_wpftmp.csproj
|
||||||
|
*.log
|
||||||
|
*.vspscc
|
||||||
|
*.vssscc
|
||||||
|
.builds
|
||||||
|
*.pidb
|
||||||
|
*.svclog
|
||||||
|
*.scc
|
||||||
|
|
||||||
|
# Chutzpah Test files
|
||||||
|
_Chutzpah*
|
||||||
|
|
||||||
|
# Visual C++ cache files
|
||||||
|
ipch/
|
||||||
|
*.aps
|
||||||
|
*.ncb
|
||||||
|
*.opendb
|
||||||
|
*.opensdf
|
||||||
|
*.sdf
|
||||||
|
*.cachefile
|
||||||
|
*.VC.db
|
||||||
|
*.VC.VC.opendb
|
||||||
|
|
||||||
|
# Visual Studio profiler
|
||||||
|
*.psess
|
||||||
|
*.vsp
|
||||||
|
*.vspx
|
||||||
|
*.sap
|
||||||
|
|
||||||
|
# Visual Studio Trace Files
|
||||||
|
*.e2e
|
||||||
|
|
||||||
|
# TFS 2012 Local Workspace
|
||||||
|
$tf/
|
||||||
|
|
||||||
|
# Guidance Automation Toolkit
|
||||||
|
*.gpState
|
||||||
|
|
||||||
|
# ReSharper is a .NET coding add-in
|
||||||
|
_ReSharper*/
|
||||||
|
*.[Rr]e[Ss]harper
|
||||||
|
*.DotSettings.user
|
||||||
|
|
||||||
|
# TeamCity is a build add-in
|
||||||
|
_TeamCity*
|
||||||
|
|
||||||
|
# DotCover is a Code Coverage Tool
|
||||||
|
*.dotCover
|
||||||
|
|
||||||
|
# AxoCover is a Code Coverage Tool
|
||||||
|
.axoCover/*
|
||||||
|
!.axoCover/settings.json
|
||||||
|
|
||||||
|
# Coverlet is a free, cross platform Code Coverage Tool
|
||||||
|
coverage*[.json, .xml, .info]
|
||||||
|
|
||||||
|
# Visual Studio code coverage results
|
||||||
|
*.coverage
|
||||||
|
*.coveragexml
|
||||||
|
|
||||||
|
# NCrunch
|
||||||
|
_NCrunch_*
|
||||||
|
.*crunch*.local.xml
|
||||||
|
nCrunchTemp_*
|
||||||
|
|
||||||
|
# MightyMoose
|
||||||
|
*.mm.*
|
||||||
|
AutoTest.Net/
|
||||||
|
|
||||||
|
# Web workbench (sass)
|
||||||
|
.sass-cache/
|
||||||
|
|
||||||
|
# Installshield output folder
|
||||||
|
[Ee]xpress/
|
||||||
|
|
||||||
|
# DocProject is a documentation generator add-in
|
||||||
|
DocProject/buildhelp/
|
||||||
|
DocProject/Help/*.HxT
|
||||||
|
DocProject/Help/*.HxC
|
||||||
|
DocProject/Help/*.hhc
|
||||||
|
DocProject/Help/*.hhk
|
||||||
|
DocProject/Help/*.hhp
|
||||||
|
DocProject/Help/Html2
|
||||||
|
DocProject/Help/html
|
||||||
|
|
||||||
|
# Click-Once directory
|
||||||
|
publish/
|
||||||
|
|
||||||
|
# Publish Web Output
|
||||||
|
*.[Pp]ublish.xml
|
||||||
|
*.azurePubxml
|
||||||
|
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||||
|
# but database connection strings (with potential passwords) will be unencrypted
|
||||||
|
*.pubxml
|
||||||
|
*.publishproj
|
||||||
|
|
||||||
|
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||||
|
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||||
|
# in these scripts will be unencrypted
|
||||||
|
PublishScripts/
|
||||||
|
|
||||||
|
# NuGet Packages
|
||||||
|
*.nupkg
|
||||||
|
# NuGet Symbol Packages
|
||||||
|
*.snupkg
|
||||||
|
# The packages folder can be ignored because of Package Restore
|
||||||
|
**/[Pp]ackages/*
|
||||||
|
# except build/, which is used as an MSBuild target.
|
||||||
|
!**/[Pp]ackages/build/
|
||||||
|
# Uncomment if necessary however generally it will be regenerated when needed
|
||||||
|
#!**/[Pp]ackages/repositories.config
|
||||||
|
# NuGet v3's project.json files produces more ignorable files
|
||||||
|
*.nuget.props
|
||||||
|
*.nuget.targets
|
||||||
|
|
||||||
|
# Microsoft Azure Build Output
|
||||||
|
csx/
|
||||||
|
*.build.csdef
|
||||||
|
|
||||||
|
# Microsoft Azure Emulator
|
||||||
|
ecf/
|
||||||
|
rcf/
|
||||||
|
|
||||||
|
# Windows Store app package directories and files
|
||||||
|
AppPackages/
|
||||||
|
BundleArtifacts/
|
||||||
|
Package.StoreAssociation.xml
|
||||||
|
_pkginfo.txt
|
||||||
|
*.appx
|
||||||
|
*.appxbundle
|
||||||
|
*.appxupload
|
||||||
|
|
||||||
|
# Visual Studio cache files
|
||||||
|
# files ending in .cache can be ignored
|
||||||
|
*.[Cc]ache
|
||||||
|
# but keep track of directories ending in .cache
|
||||||
|
!?*.[Cc]ache/
|
||||||
|
|
||||||
|
# Others
|
||||||
|
ClientBin/
|
||||||
|
~$*
|
||||||
|
*~
|
||||||
|
*.dbmdl
|
||||||
|
*.dbproj.schemaview
|
||||||
|
*.jfm
|
||||||
|
*.pfx
|
||||||
|
*.publishsettings
|
||||||
|
orleans.codegen.cs
|
||||||
|
|
||||||
|
# Including strong name files can present a security risk
|
||||||
|
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||||
|
#*.snk
|
||||||
|
|
||||||
|
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||||
|
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||||
|
#bower_components/
|
||||||
|
|
||||||
|
# RIA/Silverlight projects
|
||||||
|
Generated_Code/
|
||||||
|
|
||||||
|
# Backup & report files from converting an old project file
|
||||||
|
# to a newer Visual Studio version. Backup files are not needed,
|
||||||
|
# because we have git ;-)
|
||||||
|
_UpgradeReport_Files/
|
||||||
|
Backup*/
|
||||||
|
UpgradeLog*.XML
|
||||||
|
UpgradeLog*.htm
|
||||||
|
ServiceFabricBackup/
|
||||||
|
*.rptproj.bak
|
||||||
|
|
||||||
|
# SQL Server files
|
||||||
|
*.mdf
|
||||||
|
*.ldf
|
||||||
|
*.ndf
|
||||||
|
|
||||||
|
# Business Intelligence projects
|
||||||
|
*.rdl.data
|
||||||
|
*.bim.layout
|
||||||
|
*.bim_*.settings
|
||||||
|
*.rptproj.rsuser
|
||||||
|
*- [Bb]ackup.rdl
|
||||||
|
*- [Bb]ackup ([0-9]).rdl
|
||||||
|
*- [Bb]ackup ([0-9][0-9]).rdl
|
||||||
|
|
||||||
|
# Microsoft Fakes
|
||||||
|
FakesAssemblies/
|
||||||
|
|
||||||
|
# GhostDoc plugin setting file
|
||||||
|
*.GhostDoc.xml
|
||||||
|
|
||||||
|
# Node.js Tools for Visual Studio
|
||||||
|
.ntvs_analysis.dat
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# Visual Studio 6 build log
|
||||||
|
*.plg
|
||||||
|
|
||||||
|
# Visual Studio 6 workspace options file
|
||||||
|
*.opt
|
||||||
|
|
||||||
|
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||||
|
*.vbw
|
||||||
|
|
||||||
|
# Visual Studio LightSwitch build output
|
||||||
|
**/*.HTMLClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/ModelManifest.xml
|
||||||
|
**/*.Server/GeneratedArtifacts
|
||||||
|
**/*.Server/ModelManifest.xml
|
||||||
|
_Pvt_Extensions
|
||||||
|
|
||||||
|
# Paket dependency manager
|
||||||
|
.paket/paket.exe
|
||||||
|
paket-files/
|
||||||
|
|
||||||
|
# FAKE - F# Make
|
||||||
|
.fake/
|
||||||
|
|
||||||
|
# CodeRush personal settings
|
||||||
|
.cr/personal
|
||||||
|
|
||||||
|
# Python Tools for Visual Studio (PTVS)
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
|
||||||
|
# Cake - Uncomment if you are using it
|
||||||
|
# tools/**
|
||||||
|
# !tools/packages.config
|
||||||
|
|
||||||
|
# Tabs Studio
|
||||||
|
*.tss
|
||||||
|
|
||||||
|
# Telerik's JustMock configuration file
|
||||||
|
*.jmconfig
|
||||||
|
|
||||||
|
# BizTalk build output
|
||||||
|
*.btp.cs
|
||||||
|
*.btm.cs
|
||||||
|
*.odx.cs
|
||||||
|
*.xsd.cs
|
||||||
|
|
||||||
|
# OpenCover UI analysis results
|
||||||
|
OpenCover/
|
||||||
|
|
||||||
|
# Azure Stream Analytics local run output
|
||||||
|
ASALocalRun/
|
||||||
|
|
||||||
|
# MSBuild Binary and Structured Log
|
||||||
|
*.binlog
|
||||||
|
|
||||||
|
# NVidia Nsight GPU debugger configuration file
|
||||||
|
*.nvuser
|
||||||
|
|
||||||
|
# MFractors (Xamarin productivity tool) working folder
|
||||||
|
.mfractor/
|
||||||
|
|
||||||
|
# Local History for Visual Studio
|
||||||
|
.localhistory/
|
||||||
|
|
||||||
|
# BeatPulse healthcheck temp database
|
||||||
|
healthchecksdb
|
||||||
|
|
||||||
|
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
||||||
|
MigrationBackup/
|
||||||
|
|
||||||
|
# Ionide (cross platform F# VS Code tools) working folder
|
||||||
|
.ionide/
|
||||||
|
|
||||||
|
# Fody - auto-generated XML schema
|
||||||
|
FodyWeavers.xsd
|
||||||
|
|
||||||
|
### VisualStudio Patch ###
|
||||||
|
# Additional files built by Visual Studio
|
||||||
|
*.tlog
|
||||||
|
|
||||||
|
# End of https://www.toptal.com/developers/gitignore/api/intellij+all,visualstudio,visualstudiocode,cmake,c,c++
|
75
examples/prometheus_example/CMakeLists.txt
Normal file
75
examples/prometheus_example/CMakeLists.txt
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.5)
|
||||||
|
project(prometheus_example CXX)
|
||||||
|
|
||||||
|
include(CheckIncludeFileCXX)
|
||||||
|
|
||||||
|
check_include_file_cxx(any HAS_ANY)
|
||||||
|
check_include_file_cxx(string_view HAS_STRING_VIEW)
|
||||||
|
check_include_file_cxx(coroutine HAS_COROUTINE)
|
||||||
|
if (NOT "${CMAKE_CXX_STANDARD}" STREQUAL "")
|
||||||
|
# Do nothing
|
||||||
|
elseif (HAS_ANY AND HAS_STRING_VIEW AND HAS_COROUTINE)
|
||||||
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
|
elseif (HAS_ANY AND HAS_STRING_VIEW)
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
else ()
|
||||||
|
set(CMAKE_CXX_STANDARD 14)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
|
|
||||||
|
add_executable(${PROJECT_NAME} main.cc)
|
||||||
|
|
||||||
|
# ##############################################################################
|
||||||
|
# If you include the drogon source code locally in your project, use this method
|
||||||
|
# to add drogon
|
||||||
|
# add_subdirectory(drogon)
|
||||||
|
# target_link_libraries(${PROJECT_NAME} PRIVATE drogon)
|
||||||
|
#
|
||||||
|
# and comment out the following lines
|
||||||
|
find_package(Drogon CONFIG REQUIRED)
|
||||||
|
target_link_libraries(${PROJECT_NAME} PRIVATE Drogon::Drogon)
|
||||||
|
|
||||||
|
# ##############################################################################
|
||||||
|
|
||||||
|
if (CMAKE_CXX_STANDARD LESS 17)
|
||||||
|
message(FATAL_ERROR "c++17 or higher is required")
|
||||||
|
elseif (CMAKE_CXX_STANDARD LESS 20)
|
||||||
|
message(STATUS "use c++17")
|
||||||
|
else ()
|
||||||
|
message(STATUS "use c++20")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
aux_source_directory(controllers CTL_SRC)
|
||||||
|
aux_source_directory(filters FILTER_SRC)
|
||||||
|
aux_source_directory(plugins PLUGIN_SRC)
|
||||||
|
aux_source_directory(models MODEL_SRC)
|
||||||
|
|
||||||
|
drogon_create_views(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/views
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
# use the following line to create views with namespaces.
|
||||||
|
# drogon_create_views(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/views
|
||||||
|
# ${CMAKE_CURRENT_BINARY_DIR} TRUE)
|
||||||
|
# use the following line to create views with namespace CHANGE_ME prefixed
|
||||||
|
# and path namespaces.
|
||||||
|
# drogon_create_views(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/views
|
||||||
|
# ${CMAKE_CURRENT_BINARY_DIR} TRUE CHANGE_ME)
|
||||||
|
|
||||||
|
target_include_directories(${PROJECT_NAME}
|
||||||
|
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/models)
|
||||||
|
target_sources(${PROJECT_NAME}
|
||||||
|
PRIVATE
|
||||||
|
${SRC_DIR}
|
||||||
|
${CTL_SRC}
|
||||||
|
${FILTER_SRC}
|
||||||
|
${PLUGIN_SRC}
|
||||||
|
${MODEL_SRC})
|
||||||
|
# ##############################################################################
|
||||||
|
# uncomment the following line for dynamically loading views
|
||||||
|
# set_property(TARGET ${PROJECT_NAME} PROPERTY ENABLE_EXPORTS ON)
|
||||||
|
|
||||||
|
# ##############################################################################
|
||||||
|
|
||||||
|
add_subdirectory(test)
|
33
examples/prometheus_example/config.json
Normal file
33
examples/prometheus_example/config.json
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
|
||||||
|
"listeners": [
|
||||||
|
{
|
||||||
|
"address": "0.0.0.0",
|
||||||
|
"port": 5555,
|
||||||
|
"https": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"plugins": [
|
||||||
|
{
|
||||||
|
"name": "drogon::plugin::PromExporter",
|
||||||
|
"dependencies": [],
|
||||||
|
"config": {
|
||||||
|
"path": "/metrics",
|
||||||
|
"collectors":[
|
||||||
|
{
|
||||||
|
"name": "http_requests_total",
|
||||||
|
"help": "The total number of http requests",
|
||||||
|
"type": "counter",
|
||||||
|
"labels": ["method", "path"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "http_request_duration_seconds",
|
||||||
|
"help": "The processing time of http requests, in seconds",
|
||||||
|
"type": "histogram",
|
||||||
|
"labels": ["method", "path"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
27
examples/prometheus_example/controllers/PromTestCtrl.cc
Normal file
27
examples/prometheus_example/controllers/PromTestCtrl.cc
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#include "PromTestCtrl.h"
|
||||||
|
|
||||||
|
using namespace drogon;
|
||||||
|
|
||||||
|
void PromTestCtrl::fast(const HttpRequestPtr &req,
|
||||||
|
std::function<void(const HttpResponsePtr &)> &&callback)
|
||||||
|
{
|
||||||
|
auto resp = HttpResponse::newHttpResponse();
|
||||||
|
resp->setBody("Hello, world!");
|
||||||
|
callback(resp);
|
||||||
|
}
|
||||||
|
|
||||||
|
drogon::AsyncTask PromTestCtrl::slow(
|
||||||
|
const HttpRequestPtr req,
|
||||||
|
std::function<void(const HttpResponsePtr &)> callback)
|
||||||
|
{
|
||||||
|
// sleep for a random time between 1 and 3 seconds
|
||||||
|
static std::once_flag flag;
|
||||||
|
std::call_once(flag, []() { srand(time(nullptr)); });
|
||||||
|
auto duration = 1 + (rand() % 3);
|
||||||
|
auto loop = trantor::EventLoop::getEventLoopOfCurrentThread();
|
||||||
|
co_await drogon::sleepCoro(loop, std::chrono::seconds(duration));
|
||||||
|
auto resp = HttpResponse::newHttpResponse();
|
||||||
|
resp->setBody("Hello, world!");
|
||||||
|
callback(resp);
|
||||||
|
co_return;
|
||||||
|
}
|
21
examples/prometheus_example/controllers/PromTestCtrl.h
Normal file
21
examples/prometheus_example/controllers/PromTestCtrl.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <drogon/HttpController.h>
|
||||||
|
#include <drogon/utils/coroutine.h>
|
||||||
|
|
||||||
|
using namespace drogon;
|
||||||
|
|
||||||
|
class PromTestCtrl : public drogon::HttpController<PromTestCtrl>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
METHOD_LIST_BEGIN
|
||||||
|
ADD_METHOD_TO(PromTestCtrl::fast, "/fast", "PromStat");
|
||||||
|
ADD_METHOD_TO(PromTestCtrl::slow, "/slow", "PromStat");
|
||||||
|
METHOD_LIST_END
|
||||||
|
|
||||||
|
void fast(const HttpRequestPtr &req,
|
||||||
|
std::function<void(const HttpResponsePtr &)> &&callback);
|
||||||
|
drogon::AsyncTask slow(
|
||||||
|
const HttpRequestPtr req,
|
||||||
|
std::function<void(const HttpResponsePtr &)> callback);
|
||||||
|
};
|
52
examples/prometheus_example/filters/PromStat.cc
Normal file
52
examples/prometheus_example/filters/PromStat.cc
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* PromStat.cc
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "PromStat.h"
|
||||||
|
#include <drogon/plugins/PromExporter.h>
|
||||||
|
#include <drogon/utils/monitoring/Counter.h>
|
||||||
|
#include <drogon/utils/monitoring/Histogram.h>
|
||||||
|
#include <drogon/HttpAppFramework.h>
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
using namespace std::literals::chrono_literals;
|
||||||
|
using namespace drogon;
|
||||||
|
|
||||||
|
Task<HttpResponsePtr> PromStat::invoke(const HttpRequestPtr &req,
|
||||||
|
MiddlewareNextAwaiter &&next)
|
||||||
|
{
|
||||||
|
std::string path{req->matchedPathPattern()};
|
||||||
|
auto method = req->methodString();
|
||||||
|
auto promExporter = app().getPlugin<drogon::plugin::PromExporter>();
|
||||||
|
if (promExporter)
|
||||||
|
{
|
||||||
|
auto collector =
|
||||||
|
promExporter->getCollector<drogon::monitoring::Counter>(
|
||||||
|
"http_requests_total");
|
||||||
|
if (collector)
|
||||||
|
{
|
||||||
|
collector->metric({method, path})->increment();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto start = trantor::Date::date();
|
||||||
|
auto resp = co_await next;
|
||||||
|
if (promExporter)
|
||||||
|
{
|
||||||
|
auto collector =
|
||||||
|
promExporter->getCollector<drogon::monitoring::Histogram>(
|
||||||
|
"http_request_duration_seconds");
|
||||||
|
if (collector)
|
||||||
|
{
|
||||||
|
static const std::vector<double> boundaries{
|
||||||
|
0.0001, 0.001, 0.01, 0.1, 0.5, 1, 2, 3};
|
||||||
|
auto end = trantor::Date::date();
|
||||||
|
auto duration =
|
||||||
|
end.microSecondsSinceEpoch() - start.microSecondsSinceEpoch();
|
||||||
|
collector->metric({method, path}, boundaries, 1h, 6)
|
||||||
|
->observe((double)duration / 1000000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
co_return resp;
|
||||||
|
}
|
27
examples/prometheus_example/filters/PromStat.h
Normal file
27
examples/prometheus_example/filters/PromStat.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* PromStat.h
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <drogon/HttpMiddleware.h>
|
||||||
|
|
||||||
|
using namespace drogon;
|
||||||
|
|
||||||
|
class PromStat : public HttpCoroMiddleware<PromStat>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PromStat()
|
||||||
|
{
|
||||||
|
void(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~PromStat()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Task<HttpResponsePtr> invoke(const HttpRequestPtr &req,
|
||||||
|
MiddlewareNextAwaiter &&next) override;
|
||||||
|
};
|
7
examples/prometheus_example/main.cc
Normal file
7
examples/prometheus_example/main.cc
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#include <drogon/drogon.h>
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
drogon::app().loadConfigFile("../config.json").run();
|
||||||
|
return 0;
|
||||||
|
}
|
14
examples/prometheus_example/test/CMakeLists.txt
Normal file
14
examples/prometheus_example/test/CMakeLists.txt
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.5)
|
||||||
|
project(prometheus_example_test CXX)
|
||||||
|
|
||||||
|
add_executable(${PROJECT_NAME} test_main.cc)
|
||||||
|
|
||||||
|
# ##############################################################################
|
||||||
|
# If you include the drogon source code locally in your project, use this method
|
||||||
|
# to add drogon
|
||||||
|
# target_link_libraries(${PROJECT_NAME} PRIVATE drogon)
|
||||||
|
#
|
||||||
|
# and comment out the following lines
|
||||||
|
target_link_libraries(${PROJECT_NAME} PRIVATE Drogon::Drogon)
|
||||||
|
|
||||||
|
ParseAndAddDrogonTests(${PROJECT_NAME})
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user