mirror of
https://github.com/CrowCpp/Crow.git
synced 2024-06-07 21:10:44 +00:00
Merge branch '#421-Websockets-should-support-a-maximum-payload' of https://github.com/DeuSCaNoN/Crow into #421-Websockets-should-support-a-maximum-payload
This commit is contained in:
commit
45dc03cfa5
5
Doxyfile
5
Doxyfile
@ -2129,7 +2129,10 @@ INCLUDE_FILE_PATTERNS =
|
||||
# recursively expanded use the := operator instead of the = operator.
|
||||
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
||||
|
||||
PREDEFINED =
|
||||
PREDEFINED = CROW_ENABLE_SSL \
|
||||
CROW_ENABLE_COMPRESSION \
|
||||
CROW_ENABLE_DEBUG \
|
||||
CROW_ENABLE_LOGGING
|
||||
|
||||
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
|
||||
# tag can be used to specify a list of macro names that should be expanded. The
|
||||
|
90
docs/assets/crowlogo_main_light_color.svg
Normal file
90
docs/assets/crowlogo_main_light_color.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 15 KiB |
105
docs/assets/fast_light_icon.svg
Normal file
105
docs/assets/fast_light_icon.svg
Normal file
@ -0,0 +1,105 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="150mm"
|
||||
height="150mm"
|
||||
viewBox="0 0 150 150"
|
||||
version="1.1"
|
||||
id="svg2098"
|
||||
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04, custom)"
|
||||
sodipodi:docname="fast_light_icon.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview2100"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:document-units="mm"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.73673542"
|
||||
inkscape:cx="-200.88623"
|
||||
inkscape:cy="257.89448"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1051"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1"
|
||||
width="150mm" />
|
||||
<defs
|
||||
id="defs2095" />
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-31.274158,-78.140537)">
|
||||
<circle
|
||||
style="fill:none;fill-opacity:1;stroke:#e5f2f8;stroke-width:6.46499;stroke-linecap:round;stroke-opacity:1"
|
||||
id="path7742"
|
||||
cx="106.62331"
|
||||
cy="153.48967"
|
||||
r="70" />
|
||||
<circle
|
||||
style="fill:#515b60;fill-opacity:1;stroke:none;stroke-width:6.46499;stroke-linecap:round;stroke-opacity:1"
|
||||
id="path7840"
|
||||
cx="106.80286"
|
||||
cy="151.15532"
|
||||
r="10" />
|
||||
<path
|
||||
id="rect7980"
|
||||
style="fill:#515b60;fill-opacity:1;stroke-width:6.46499;stroke-linecap:round"
|
||||
d="m 156.9346,153.30987 -50.40574,1.47566 -0.0786,-6.1047 z"
|
||||
sodipodi:nodetypes="cccc"
|
||||
inkscape:transform-center-x="-24.979325"
|
||||
inkscape:transform-center-y="-0.23024" />
|
||||
<circle
|
||||
style="fill:#e5f2f8;fill-opacity:1;stroke:none;stroke-width:4.99999;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path9189"
|
||||
cx="56.373787"
|
||||
cy="185.78271"
|
||||
r="3" />
|
||||
<circle
|
||||
style="fill:#e5f2f8;fill-opacity:1;stroke:none;stroke-width:4.99999;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="circle9271"
|
||||
cx="46.658237"
|
||||
cy="154.20793"
|
||||
r="3" />
|
||||
<circle
|
||||
style="fill:#e5f2f8;fill-opacity:1;stroke:none;stroke-width:4.99999;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="circle9273"
|
||||
cx="53.132095"
|
||||
cy="125.30756"
|
||||
r="3" />
|
||||
<circle
|
||||
style="fill:#e5f2f8;fill-opacity:1;stroke:none;stroke-width:4.99999;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="circle9275"
|
||||
cx="73.13047"
|
||||
cy="102.3995"
|
||||
r="3" />
|
||||
<circle
|
||||
style="fill:#e5f2f8;fill-opacity:1;stroke:none;stroke-width:4.99999;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="circle9277"
|
||||
cx="106.98246"
|
||||
cy="92.060951"
|
||||
r="3" />
|
||||
<circle
|
||||
style="fill:#e5f2f8;fill-opacity:1;stroke:none;stroke-width:4.99999;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="circle9279"
|
||||
cx="-73.287689"
|
||||
cy="-160.29289"
|
||||
r="3"
|
||||
transform="rotate(150.48856)" />
|
||||
<path
|
||||
id="circle12049"
|
||||
style="fill:none;stroke:#ff4141;stroke-width:5.66447;stroke-linecap:round;stroke-opacity:1"
|
||||
d="m 163.0663,127.86979 c 3.88122,8.04831 5.15863,16.53521 5.15863,26.06886 0,12.05511 -3.478,23.2979 -9.48531,32.77966"
|
||||
sodipodi:nodetypes="csc" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.8 KiB |
67
docs/assets/header_light_icon.svg
Normal file
67
docs/assets/header_light_icon.svg
Normal file
@ -0,0 +1,67 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="130mm"
|
||||
height="130mm"
|
||||
viewBox="0 0 130 130"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04, custom)"
|
||||
sodipodi:docname="header_light_icon.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview7"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:document-units="mm"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.73673541"
|
||||
inkscape:cx="-122.16055"
|
||||
inkscape:cy="249.75045"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1051"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1"
|
||||
height="130mm" />
|
||||
<defs
|
||||
id="defs2">
|
||||
<rect
|
||||
x="286.39862"
|
||||
y="431.63394"
|
||||
width="213.10229"
|
||||
height="276.89725"
|
||||
id="rect12469" />
|
||||
<rect
|
||||
x="308.11603"
|
||||
y="465.56741"
|
||||
width="176.45412"
|
||||
height="267.39587"
|
||||
id="rect3773" />
|
||||
</defs>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-55.42222,-82.637121)">
|
||||
<path
|
||||
id="path1009"
|
||||
style="fill:#e5f2f8;fill-opacity:1;stroke-width:8.47412"
|
||||
d="M 62 0 L 62 244.93359 L 62 489.86719 L 249.05273 489.86719 L 436.10547 489.86719 L 436.10547 302.15625 L 436.10547 114.44531 L 378.94141 57.222656 L 321.7793 0 L 191.88867 0 L 62 0 z M 228.81055 227.10352 L 246.87695 227.10352 L 246.87695 286.67383 C 251.17383 280.09831 256.2194 275.18294 262.01367 271.92773 C 267.87305 268.67253 274.61133 267.04492 282.22852 267.04492 C 294.79362 267.04492 304.29883 270.95117 310.74414 278.76367 C 317.18945 286.51107 320.41211 297.93685 320.41211 313.04102 L 320.41211 379.05664 L 302.44336 379.05664 L 302.44336 313.62695 C 302.44336 303.27539 300.42513 295.52799 296.38867 290.38477 C 292.35221 285.24154 286.29753 282.66992 278.22461 282.66992 C 268.52409 282.66992 260.87435 285.76237 255.27539 291.94727 C 249.67643 298.13216 246.87695 306.56315 246.87695 317.24023 L 246.87695 379.05664 L 228.81055 379.05664 L 228.81055 227.10352 z M 168.45898 354.25195 L 189.06445 354.25195 L 189.06445 379.05664 L 168.45898 379.05664 L 168.45898 354.25195 z "
|
||||
transform="matrix(0.26458333,0,0,0.26458333,55.42222,82.637121)" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
transform="scale(0.26458333)"
|
||||
id="text3771"
|
||||
style="font-style:normal;font-weight:normal;font-size:200px;line-height:1.25;font-family:sans-serif;white-space:pre;shape-inside:url(#rect3773);fill:#ffffff;fill-opacity:1;stroke:none" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.9 KiB |
67
docs/assets/typesafe_light_icon.svg
Normal file
67
docs/assets/typesafe_light_icon.svg
Normal file
@ -0,0 +1,67 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="128mm"
|
||||
height="128mm"
|
||||
viewBox="0 0 128 128"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04, custom)"
|
||||
sodipodi:docname="typesafe_light_icon.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview7"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:document-units="mm"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1.0419012"
|
||||
inkscape:cx="114.21428"
|
||||
inkscape:cy="204.43397"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1051"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1"
|
||||
height="128mm" />
|
||||
<defs
|
||||
id="defs2">
|
||||
<inkscape:path-effect
|
||||
effect="mirror_symmetry"
|
||||
start_point="83.49758,103.2497"
|
||||
end_point="83.677144,216.55502"
|
||||
center_point="83.587362,159.90236"
|
||||
id="path-effect1148"
|
||||
is_visible="true"
|
||||
lpeversion="1.1"
|
||||
mode="free"
|
||||
discard_orig_path="false"
|
||||
fuse_paths="true"
|
||||
oposite_fuse="false"
|
||||
split_items="false"
|
||||
split_open="false" />
|
||||
</defs>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-35.610134,-93.0589)">
|
||||
<path
|
||||
style="fill:none;fill-opacity:1;stroke:#e5f2f8;stroke-width:6.465;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 83.489092,97.893689 C 61.657927,122.25262 42.116054,116.87646 39.272073,119.55834 c -2.61289,2.46396 6.066946,69.88504 44.404869,96.86893 38.252208,-27.10527 46.718298,-94.55352 44.097618,-97.00919 -2.85247,-2.67285 -22.37721,2.76522 -44.285468,-21.524391 z"
|
||||
id="path857"
|
||||
sodipodi:nodetypes="csc"
|
||||
inkscape:original-d="m 83.677144,97.68319 c -21.906891,24.60036 -41.552926,19.18557 -44.405071,21.87515 -2.615268,2.4662 6.082752,70.00779 44.5096,96.94249"
|
||||
inkscape:path-effect="#path-effect1148"
|
||||
transform="translate(16.150228,0.25394282)" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.4 KiB |
48
docs/assets/websocket_light_icon.svg
Normal file
48
docs/assets/websocket_light_icon.svg
Normal file
@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="202mm"
|
||||
height="202mm"
|
||||
viewBox="0 0 202 202"
|
||||
version="1.1"
|
||||
id="svg13908"
|
||||
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04, custom)"
|
||||
sodipodi:docname="websocket_light_icon.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview13910"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:document-units="mm"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.73673541"
|
||||
inkscape:cx="160.16605"
|
||||
inkscape:cy="343.40687"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1051"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1"
|
||||
width="201.77914mm" />
|
||||
<defs
|
||||
id="defs13905" />
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-4.4986958,-69.044219)">
|
||||
<path
|
||||
style="fill:#e5f2f8;stroke-width:0.0841212;fill-opacity:1"
|
||||
d="m 69.265523,230.77706 -14.111288,-14.11148 8.832818,-8.83251 8.832808,-8.83251 L 51.116516,177.2971 29.41317,155.59363 v -12.26062 -12.26062 h 12.534076 12.534076 v 7.08736 7.08737 l 9.169279,9.16899 9.169279,9.16899 13.396176,-13.39618 13.396175,-13.39617 -9.168982,-9.16928 -9.169,-9.16932 H 55.360589 29.44692 L 16.972808,105.92001 4.4986958,93.385901 H 48.103109 91.707532 l 3.746995,3.764422 c 2.060862,2.070436 11.842143,11.897187 21.736193,21.837197 l 17.9892,18.0727 -4.40824,4.40884 -4.40823,4.40882 8.60118,8.60149 8.60117,8.60148 v 17.74937 17.74937 l -17.49722,-17.49708 -17.49722,-17.49705 -4.45581,4.45833 -4.455823,4.45834 17.460153,17.51827 17.46015,17.51826 H 116.84371 99.107375 l -8.622061,-8.62237 -8.622051,-8.62235 -4.43771,4.43711 -4.437711,4.43712 10.452037,10.45228 10.452028,10.45229 h 43.721543 43.72154 l 10.28448,10.23153 c 5.65645,5.62734 11.2686,11.2109 12.47142,12.4079 l 2.18695,2.17636 H 144.82733 83.376811 Z M 156.184,182.57579 v -24.87875 l -10.45194,-10.4522 -10.45193,-10.45218 8.83245,-8.83275 c 4.85784,-4.85802 8.87197,-8.83278 8.92029,-8.83278 0.0483,0 6.41741,6.33451 14.15356,14.07664 l 14.06572,14.07661 v 30.08708 30.08708 H 168.71808 156.184 Z"
|
||||
id="path13999" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.5 KiB |
@ -1,7 +0,0 @@
|
||||
Crow Allows a developer to set CORS policies by using the `CORSHandler` middleware.<br><br>
|
||||
|
||||
This middleware can be added to the app simply by defining a `#!cpp crow::App<crow::CORSHandler>`. This will use the default CORS rules globally<br><br>
|
||||
|
||||
The CORS rules can be modified by first getting the middleware via `#!cpp auto& cors = app.get_middleware<crow::CORSHandler>();`. The rules can be set per URL prefix using `prefix()`, per blueprint using `blueprint()`, or globally via `global()`. These will return a `CORSRules` object which contains the actual rules for the prefix, blueprint, or application. For more details go [here](../../reference/structcrow_1_1_c_o_r_s_handler.html).
|
||||
|
||||
`CORSRules` can be modified using the methods `origin()`, `methods()`, `headers()`, `max_age()`, `allow_credentials()`, or `ignore()`. For more details on these methods and what default values they take go [here](../../reference/structcrow_1_1_c_o_r_s_rules.html).
|
@ -3,6 +3,7 @@
|
||||
Using `#!cpp crow::utility::base64encode(mystring, mystring.size())` will return a Base64 encoded string. For URL safe Base64 `#!cpp crow::utility::base64encode_urlsafe(mystring, mystring.size())` can be used. The key used in the encoding process can be changed, it is a string containing all 64 characters to be used.
|
||||
|
||||
## Decoding
|
||||
**Introduced in: `v1.0`**<br><br>
|
||||
<span class="tag">[:octicons-feed-tag-16: v1.0](https://github.com/CrowCpp/Crow/releases/v1.0)</span>
|
||||
|
||||
|
||||
Using `#!cpp crow::utility::base64decode(mystring, mystring.size())` with `mystring` being a Base64 encoded string will return a plain-text string. The function works with both normal and URL safe Base64. However it cannot decode a Base64 string encoded with a custom key.
|
||||
|
@ -1,5 +1,6 @@
|
||||
**Introduced in: `v1.0`**<br><br>
|
||||
|
||||
<span class="tag">[:octicons-feed-tag-16: v1.0](https://github.com/CrowCpp/Crow/releases/v1.0)</span>
|
||||
|
||||
|
||||
Crow supports flask style blueprints.<br>
|
||||
A blueprint is a limited app. It cannot handle networking. But it can handle routes.<br>
|
||||
Blueprints allow developers to compartmentalize their Crow applications, making them a lot more modular.<br><br>
|
||||
|
@ -1,4 +1,6 @@
|
||||
**Introduced in: `v0.3`**<br><br>
|
||||
<span class="tag">[:octicons-feed-tag-16: v0.3](https://github.com/CrowCpp/Crow/releases/v0.3)</span>
|
||||
|
||||
|
||||
Crow supports Zlib compression using Gzip or Deflate algorithms.
|
||||
|
||||
## HTTP Compression
|
||||
|
43
docs/guides/included-middleware.md
Normal file
43
docs/guides/included-middleware.md
Normal file
@ -0,0 +1,43 @@
|
||||
Crow contains some middlewares that are ready to be used in your application.
|
||||
<br>
|
||||
Make sure you understand how to enable and use [middleware](../middleware/).
|
||||
|
||||
## Cookies
|
||||
Include: `crow/middlewares/cookie_parser.h` <br>
|
||||
Examples: `examples/middlewars/example_cookies.cpp`
|
||||
|
||||
This middleware allows to read and write cookies by using `CookieParser`. Once enabled, it parses all incoming cookies.
|
||||
|
||||
Cookies can be read and written with the middleware context. All cookie attributes can be changed as well.
|
||||
|
||||
```cpp
|
||||
auto& ctx = app.get_context<crow::CookieParser>(request);
|
||||
std::string value = ctx.get_cookie("key");
|
||||
ctx.set_cookie("key", "value")
|
||||
.path("/")
|
||||
.max_age(120);
|
||||
```
|
||||
|
||||
!!! note
|
||||
|
||||
Make sure `CookieParser` is listed before any other middleware that relies on it.
|
||||
|
||||
## CORS
|
||||
Include: `crow/middlewares/cors.h` <br>
|
||||
Examples: `examples/middlewars/example_cors.cpp`
|
||||
|
||||
This middleware allows to set CORS policies by using `CORSHandler`. Once enabled, it will apply the default CORS rules globally.
|
||||
|
||||
The CORS rules can be modified by first getting the middleware via `#!cpp auto& cors = app.get_middleware<crow::CORSHandler>();`. The rules can be set per URL prefix using `prefix()`, per blueprint using `blueprint()`, or globally via `global()`. These will return a `CORSRules` object which contains the actual rules for the prefix, blueprint, or application. For more details go [here](../../reference/structcrow_1_1_c_o_r_s_handler.html).
|
||||
|
||||
`CORSRules` can be modified using the methods `origin()`, `methods()`, `headers()`, `max_age()`, `allow_credentials()`, or `ignore()`. For more details on these methods and what default values they take go [here](../../reference/structcrow_1_1_c_o_r_s_rules.html).
|
||||
|
||||
```cpp
|
||||
auto& cors = app.get_middleware<crow::CORSHandler>();
|
||||
cors
|
||||
.global()
|
||||
.headers("X-Custom-Header", "Upgrade-Insecure-Requests")
|
||||
.methods("POST"_method, "GET"_method)
|
||||
.prefix("/cors")
|
||||
.origin("example.com");
|
||||
```
|
@ -31,7 +31,8 @@ Writing a log is as simple as `#!cpp CROW_LOG_<LOG LEVEL> << "Hello";` (replace&
|
||||
Log times are reported in GMT timezone by default. This is because HTTP requires all reported times for requests and responses to be in GMT. This can be changed by using the macro `CROW_USE_LOCALTIMEZONE` which will set **only the log timezone** to the server's local timezone.
|
||||
|
||||
## Creating A custom logger
|
||||
**Introduced in: `v1.0`**<br><br>
|
||||
<span class="tag">[:octicons-feed-tag-16: v1.0](https://github.com/CrowCpp/Crow/releases/v1.0)</span>
|
||||
|
||||
|
||||
Assuming you have an existing logger or Crow's default format just doesn't work for you. Crow allows you to use a custom logger for any log made using the `CROW_LOG_<LOG LEVEL>` macro.<br>
|
||||
All you need is a class extending `#!cpp crow::ILogHandler` containing the method `#!cpp void log(std::string, crow::LogLevel)`.<br>
|
||||
|
@ -1,4 +1,5 @@
|
||||
**Introduced in: `v0.2`**<br><br>
|
||||
<span class="tag">[:octicons-feed-tag-16: v0.2](https://github.com/CrowCpp/Crow/releases/0.2)</span>
|
||||
|
||||
|
||||
Multipart is a way of forming HTTP requests or responses to contain multiple distinct parts.<br>
|
||||
|
||||
@ -21,7 +22,8 @@ A message can be created either by defining the headers, boundary, and individua
|
||||
|
||||
Once a multipart message has been made, the individual parts can be accessed throughout `msg.parts`, `parts` is an `std::vector`.<br><br>
|
||||
|
||||
**Introduced in: `v1.0`**<br><br>
|
||||
<span class="tag">[:octicons-feed-tag-16: v1.0](https://github.com/CrowCpp/Crow/releases/v1.0)</span>
|
||||
|
||||
|
||||
Part headers are organized in a similar way to request and response headers, and can be retrieved via `crow::multipart::get_header_object("header-key")`. This function returns a `crow::multipart::header` object.<br><br>
|
||||
|
||||
|
@ -5,7 +5,9 @@ Crow supports query strings through `crow::request::url_params`. The object is o
|
||||
## get(name)
|
||||
Returns the value (as char*) based on the given key (or name). Returns `nullptr` if the key is not found.
|
||||
## pop(name)
|
||||
**Introduced in: `v0.3`**<br><br>
|
||||
<span class="tag">[:octicons-feed-tag-16: v0.3](https://github.com/CrowCpp/Crow/releases/v0.3)</span>
|
||||
|
||||
|
||||
Works the same as `get`, but removes the returned value.
|
||||
!!! note
|
||||
|
||||
@ -16,13 +18,17 @@ A URL can be `http://example.com?key[]=value1&key[]=value2&key[]=value3`. Using
|
||||
|
||||
`#!cpp get_list("key", false)` can be used to parse `http://example.com?key=value1&key=value2&key=value3`
|
||||
## pop_list(name)
|
||||
**Introduced in: `v0.3`**<br><br>
|
||||
<span class="tag">[:octicons-feed-tag-16: v0.3](https://github.com/CrowCpp/Crow/releases/v0.3)</span>
|
||||
|
||||
|
||||
Works the same as `get_list` but removes all instances of values having the given key (`use_brackets` is also available here).
|
||||
## get_dict(name)
|
||||
Returns an `std::unordered_map<std::string, std::string>` from a query string such as `?key[sub_key1]=value1&key[sub_key2]=value2&key[sub_key3]=value3`.<br>
|
||||
The key in the map is what's in the brackets (`sub_key1` for example), and the value being what's after the `=` sign (`value1`). The name passed to the function is not part of the returned value.
|
||||
## pop_dict(name)
|
||||
**Introduced in: `v0.3`**<br><br>
|
||||
<span class="tag">[:octicons-feed-tag-16: v0.3](https://github.com/CrowCpp/Crow/releases/v0.3)</span>
|
||||
|
||||
|
||||
Works the same as `get_dict` but removing the values from the query string.
|
||||
!!! warning
|
||||
|
||||
|
@ -52,7 +52,9 @@ The main return type is `std::string`, although you could also return a `crow::j
|
||||
For more information on the specific constructors for a `crow::response` go [here](../../reference/structcrow_1_1response.html).
|
||||
|
||||
## Returning custom classes
|
||||
**Introduced in: `v0.3`**<br><br>
|
||||
<span class="tag">[:octicons-feed-tag-16: v0.3](https://github.com/CrowCpp/Crow/releases/v0.3)</span>
|
||||
|
||||
|
||||
If you have your own class you want to return (without converting it to string and returning that), you can use the `crow::returnable` class.<br>
|
||||
to use the returnable class, you only need your class to publicly extend `crow::returnable`, add a `dump()` method that returns your class as an `std::string`, and add a constructor that has a `Content-Type` header as a string argument.<br><br>
|
||||
|
||||
@ -75,12 +77,15 @@ class a : public crow::returnable
|
||||
<br><br>
|
||||
|
||||
## Response codes
|
||||
**Introduced in: `v1.0`**<br><br>
|
||||
<span class="tag">[:octicons-feed-tag-16: v1.0](https://github.com/CrowCpp/Crow/releases/v1.0)</span>
|
||||
|
||||
|
||||
Instead of assigning a response code, you can use the `crow::status` enum, for example you can replace `crow::response(200)` with `crow::response(crow::status::OK)`
|
||||
|
||||
## Catchall routes
|
||||
**Introduced in: `v0.3`**<br><br>
|
||||
<span class="tag">[:octicons-feed-tag-16: v0.3](https://github.com/CrowCpp/Crow/releases/v0.3)</span>
|
||||
|
||||
|
||||
By default, any request that Crow can't find a route for will return a simple 404 response. You can change that to return a default route using the `CROW_CATCHALL_ROUTE(app)` macro. Defining it is identical to a normal route, even when it comes to the `const crow::request&` and `crow::response&` parameters being optional.
|
||||
!!! note
|
||||
|
||||
|
@ -1,4 +1,6 @@
|
||||
**Introduced in: `v0.2`**<br><br>
|
||||
<span class="tag">[:octicons-feed-tag-16: v0.2](https://github.com/CrowCpp/Crow/releases/0.2)</span>
|
||||
|
||||
|
||||
A static file is any file that resides in the server's storage.
|
||||
|
||||
Crow supports returning Static files as responses in 2 ways.
|
||||
|
@ -7,10 +7,10 @@
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:description" content="A Fast and Easy to use microframework for the web."/>
|
||||
<meta name="description" content="Crow is a C++ microframework for running web services. It uses routing similar to Python's Flask which makes it easy to use. It is also extremely fast, beating multiple existing C++ frameworks as well as non C++ frameworks.">
|
||||
<meta property="og:image" content="/assets/og_img.png" />
|
||||
<meta property="og:image" content="assets/og_img.png" />
|
||||
<meta property="og:url" content="https://crowcpp.org">
|
||||
<meta property="twitter:card" content="summary_large_image">
|
||||
<meta property="twitter:image" content="/assets/og_img.png">
|
||||
<meta property="twitter:image" content="assets/og_img.png">
|
||||
{% endblock %}
|
||||
|
||||
<!-- Content -->
|
||||
@ -25,11 +25,11 @@
|
||||
.ccard{
|
||||
border-style: solid;
|
||||
border-width: .1rem;
|
||||
border-color: #00000080;
|
||||
border-color: var(--home-border-color);
|
||||
border-radius: 0.5rem;
|
||||
width: 10rem;
|
||||
height: 12rem;
|
||||
box-shadow: 2px 5px 5px #00000040;
|
||||
box-shadow: 2px 5px 5px var(--home-shadow-color);
|
||||
margin-inline: 1.5rem;
|
||||
margin-bottom: 1rem;
|
||||
display: inline-block;
|
||||
@ -51,7 +51,7 @@
|
||||
border-bottom: solid;
|
||||
border-width: 0.1rem;
|
||||
border-image-slice: 1;
|
||||
border-image-source: linear-gradient(90deg, rgba(0,0,0,0) 0%, rgb(0, 0, 0) 50%, rgba(0,0,0,0) 100%);
|
||||
border-image-source: var(--home-image-border);
|
||||
}
|
||||
|
||||
.ccard__text{
|
||||
@ -143,7 +143,8 @@ code{
|
||||
}
|
||||
|
||||
</style>
|
||||
<img class="clogo" alt="logo" src="/assets/crowlogo_main_color.svg">
|
||||
<img class="clogo" alt="logo" src="assets/crowlogo_main_color.svg#only-light">
|
||||
<img class="clogo" alt="logo" src="assets/crowlogo_main_light_color.svg#only-dark">
|
||||
|
||||
<h1 style="text-align:center;">A Fast and Easy to use microframework for the web.</h1>
|
||||
|
||||
@ -151,19 +152,23 @@ code{
|
||||
|
||||
<section class="csection">
|
||||
<div class="ccard">
|
||||
<img class="ccard__image" src= /assets/fast_icon.svg>
|
||||
<img class="ccard__image" src= assets/fast_icon.svg#only-light>
|
||||
<img class="ccard__image" src= assets/fast_light_icon.svg#only-dark>
|
||||
<p class="ccard__text">Blazingly Fast</p>
|
||||
</div>
|
||||
<div class="ccard">
|
||||
<img class="ccard__image" src= /assets/header_icon.svg>
|
||||
<img class="ccard__image" src= assets/header_icon.svg#only-light>
|
||||
<img class="ccard__image" src= assets/header_light_icon.svg#only-dark>
|
||||
<p class="ccard__text">Header Only</p>
|
||||
</div>
|
||||
<div class="ccard">
|
||||
<img class="ccard__image" src= /assets/typesafe_icon.svg>
|
||||
<img class="ccard__image" src= assets/typesafe_icon.svg#only-light>
|
||||
<img class="ccard__image" src= assets/typesafe_light_icon.svg#only-dark>
|
||||
<p class="ccard__text">Typesafe handlers</p>
|
||||
</div>
|
||||
<div class="ccard">
|
||||
<img class="ccard__image" src= /assets/websocket_icon.svg>
|
||||
<img class="ccard__image" src= assets/websocket_icon.svg#only-light>
|
||||
<img class="ccard__image" src= assets/websocket_light_icon.svg#only-dark>
|
||||
<p class="ccard__text">Websocket Support</p>
|
||||
</div>
|
||||
</section>
|
||||
@ -176,8 +181,7 @@ code{
|
||||
<h2 style="text-align: center;">Easy to get started</h3>
|
||||
</div>
|
||||
<div class="scontent">
|
||||
<div class="highlight"><pre id="__code_0"><span></span><button class="md-clipboard md-icon" title="Copy to clipboard" data-clipboard-target="#__code_0 > code"></button><code>
|
||||
<span class="cp">#include</span> <span class="cpf">"crow.h"</span><span class="cp"></span>
|
||||
<div class="highlight"><pre id="__code_0"><span></span><button class="md-clipboard md-icon" title="Copy to clipboard" data-clipboard-target="#__code_0 > code"></button><code><span class="cp">#include</span> <span class="cpf">"crow.h"</span><span class="cp"></span>
|
||||
|
||||
<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
|
||||
<span class="p">{</span>
|
||||
@ -244,7 +248,7 @@ code{
|
||||
|
||||
<div class="dcard">
|
||||
<a href="https://github.com/CrowCpp/Crow/releases/latest">
|
||||
<img class="dcard__image" src="/assets/pkg_logos/ubuntu.png">
|
||||
<img class="dcard__image" src="assets/pkg_logos/ubuntu.png">
|
||||
<p class="dcard__title">.deb file</p>
|
||||
<p class="dcard__description">for Ubuntu/Debian based systems</p>
|
||||
</a>
|
||||
@ -252,7 +256,7 @@ code{
|
||||
|
||||
<div class="dcard">
|
||||
<a href="https://aur.archlinux.org/packages/crow">
|
||||
<img class="dcard__image" src="/assets/pkg_logos/arch.png">
|
||||
<img class="dcard__image" src="assets/pkg_logos/arch.png">
|
||||
<p class="dcard__title">AUR</p>
|
||||
<p class="dcard__description">for Arch Linux based systems</p>
|
||||
</a>
|
||||
@ -260,7 +264,7 @@ code{
|
||||
|
||||
<div class="dcard">
|
||||
<a href="https://vcpkg.io">
|
||||
<img class="dcard__image" src="/assets/pkg_logos/vcpkg.png">
|
||||
<img class="dcard__image" src="assets/pkg_logos/vcpkg.png">
|
||||
<p class="dcard__title">VCPKG</p>
|
||||
<p class="dcard__description">for Windows systems</p>
|
||||
</a>
|
||||
@ -268,7 +272,7 @@ code{
|
||||
|
||||
<div class="dcard">
|
||||
<a href="https://conan.io/center/crowcpp-crow">
|
||||
<img class="dcard__image" src="/assets/pkg_logos/conan.png">
|
||||
<img class="dcard__image" src="assets/pkg_logos/conan.png">
|
||||
<p class="dcard__title">Conan Center</p>
|
||||
<p class="dcard__description">for developers using the conan package manager</p>
|
||||
</a>
|
||||
@ -276,7 +280,7 @@ code{
|
||||
|
||||
<div class="dcard">
|
||||
<a href="https://github.com/CrowCpp/Crow/releases/latest">
|
||||
<img class="dcard__image" src="/assets/pkg_logos/github.png">
|
||||
<img class="dcard__image" src="assets/pkg_logos/github.png">
|
||||
<p class="dcard__title">Header File</p>
|
||||
<p class="dcard__description">Download Crow directly from github</p>
|
||||
</a>
|
||||
@ -289,9 +293,9 @@ code{
|
||||
<h3 style="text-align:center;">The 1000 mile journey begins with a single step. Get started by installing Crow and building you first application. Or go through the guides if you're stuck somewhere.<h3>
|
||||
|
||||
<dev class="sbuttons">
|
||||
<a href="/getting_started/setup/" title="Get Started" class="md-button crow-button">Get Started</a>
|
||||
<a href="/guides/app/" title="Guides" class="md-button crow-button">Guides</a>
|
||||
<a href="/reference/index.html" title="API Reference" class="md-button crow-button">API Reference</a>
|
||||
<a href="getting_started/setup/" title="Get Started" class="md-button crow-button">Get Started</a>
|
||||
<a href="guides/app/" title="Guides" class="md-button crow-button">Guides</a>
|
||||
<a href="reference/index.html" title="API Reference" class="md-button crow-button">API Reference</a>
|
||||
</dev>
|
||||
|
||||
|
||||
@ -309,7 +313,7 @@ function makeCard(name, img_url, ref, size = 6)
|
||||
{
|
||||
img_url = AvatarImage(name);
|
||||
}
|
||||
return `<a title="${name}" href="${ref}" style=\"border-style: solid;border-width: .1rem;border-color: #00000080;border-radius: ${size/12}rem;width: ${size}rem;height: ${size}rem;box-shadow: 2px 5px 5px #00000040;margin-inline: ${size/12}rem;margin-bottom: ${size/12}rem;margin-top: ${size/12}rem;display: inline-block;\"><img style=\"width: ${size/2}rem;height: ${size/2}rem; border-radius: ${size/10}rem;margin-left: auto;margin-right: auto;display: block;margin-top: ${size/7.7}rem;\" src=\"${img_url}\"><p style=\"text-align: center;font-size: ${size/7.7}rem;\">${finalName}</p></a>`;
|
||||
return `<a title="${name}" href="${ref}" style=\"border-style: solid;border-width: .1rem;border-color: var(--home-border-color);border-radius: ${size/12}rem;width: ${size}rem;height: ${size}rem;box-shadow: 2px 5px 5px var(--home-shadow-color);margin-inline: ${size/12}rem;margin-bottom: ${size/12}rem;margin-top: ${size/12}rem;display: inline-block;\"><img style=\"width: ${size/2}rem;height: ${size/2}rem; border-radius: ${size/10}rem;margin-left: auto;margin-right: auto;display: block;margin-top: ${size/7.7}rem;\" src=\"${img_url}\"><p style=\"text-align: center;font-size: ${size/7.7}rem;\">${finalName}</p></a>`;
|
||||
}
|
||||
|
||||
function fixLong(name)
|
||||
@ -511,7 +515,7 @@ hidden
|
||||
<div class="md-footer-meta__inner md-grid">
|
||||
|
||||
<!-- Copyright and theme information -->
|
||||
<div class="md-footer-copyright">
|
||||
<div class="md-footer-copyright" style="flex: 1;display: flex;justify-content: left;">
|
||||
{% if config.copyright %}
|
||||
<div class="md-footer-copyright__highlight">
|
||||
{{ config.copyright }}
|
||||
@ -520,7 +524,7 @@ hidden
|
||||
{{ extracopyright }}
|
||||
</div>
|
||||
|
||||
<a style="margin: auto .6rem; font-size: .64rem;" href="/privacy_policy.html">Privacy Policy</a>
|
||||
<a style="margin: auto .6rem; font-size: .64rem;text-align: center;flex: 1;display: flex;justify-content: center;" href="privacy_policy.html">Privacy Policy</a>
|
||||
|
||||
<!-- Social links -->
|
||||
{% include "partials/social.html" %}
|
||||
|
@ -22,6 +22,15 @@
|
||||
|
||||
{% import "partials/language.html" as lang with context %}
|
||||
|
||||
<style>
|
||||
.md-footer-copyright {
|
||||
color: var(--md-footer-fg-color--light);
|
||||
font-size: .64rem;
|
||||
margin: auto .6rem;
|
||||
padding: .4rem 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="md-footer">
|
||||
|
||||
|
37
docs/overrides/partials/social.html
Normal file
37
docs/overrides/partials/social.html
Normal file
@ -0,0 +1,37 @@
|
||||
<!--
|
||||
Copyright (c) 2016-2022 Martin Donath <martin.donath@squidfunk.com>
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to
|
||||
deal in the Software without restriction, including without limitation the
|
||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
IN THE SOFTWARE.
|
||||
-->
|
||||
|
||||
<!-- Social links -->
|
||||
<div class="md-social" style="flex: 1;display: flex;justify-content: right;">
|
||||
{% for social in config.extra.social %}
|
||||
{% set title = social.name %}
|
||||
{% if not title and "//" in social.link %}
|
||||
{% set _, url = social.link.split("//") %}
|
||||
{% set title = url.split("/")[0] %}
|
||||
{% endif %}
|
||||
<a
|
||||
href="{{ social.link }}"
|
||||
target="_blank" rel="noopener"
|
||||
title="{{ title | e }}"
|
||||
class="md-social__link"
|
||||
>
|
||||
{% include ".icons/" ~ social.icon ~ ".svg" %}
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
@ -1,23 +1,67 @@
|
||||
|
||||
:root {
|
||||
[data-md-color-scheme="crow-light"]{
|
||||
|
||||
--md-primary-fg-color: #24404f;
|
||||
--md-accent-fg-color: #122027;
|
||||
--md-typeset-a-color: var(--md-accent-fg-color) !important;
|
||||
--md-accent-fg-color: #122027;
|
||||
--md-typeset-a-color: var(--md-accent-fg-color) !important;
|
||||
--md-default-bg-color: #e5f2f8;
|
||||
--md-code-bg-color: #cfcfcf !important;
|
||||
--md-code-hl-comment-color: var(--md-code-fg-color) !important;
|
||||
--md-code-hl-generic-color: var(--md-code-fg-color) !important;
|
||||
--md-code-hl-variable-color: var(--md-code-fg-color) !important;
|
||||
--md-code-fg-color: #fff !important;
|
||||
--md-code-hl-punctuation-color: #fff !important;
|
||||
--md-code-fg-color: #1d1d1d !important;
|
||||
--md-code-hl-punctuation-color: #1d1d1d !important;
|
||||
--home-border-color: #00000080;
|
||||
--home-shadow-color: #00000040;
|
||||
--home-image-border: linear-gradient(90deg, rgba(0,0,0,0) 0%, rgb(0, 0, 0) 50%, rgba(0,0,0,0) 100%);
|
||||
|
||||
}
|
||||
|
||||
[data-md-color-scheme="crow-dark"]{
|
||||
|
||||
--md-primary-fg-color: #24404f;
|
||||
--md-accent-fg-color: #445e6d;
|
||||
--md-default-fg-color: rgba(255, 255, 255, 0.87);
|
||||
--md-default-fg-color--light: rgba(255, 255, 255, 0.54);
|
||||
--md-default-fg-color--lighter: rgba(255, 255, 255, 0.32);
|
||||
--md-default-fg-color--lightest: rgba(255, 255, 255, 0.07);
|
||||
--md-typeset-a-color: var(--md-accent-fg-color) !important;
|
||||
--md-default-bg-color: #1a2124;
|
||||
--md-code-bg-color: #2f2f2f !important;
|
||||
--md-code-hl-comment-color: var(--md-code-fg-color) !important;
|
||||
--md-code-hl-generic-color: var(--md-code-fg-color) !important;
|
||||
--md-code-hl-variable-color: var(--md-code-fg-color) !important;
|
||||
--md-code-fg-color: #adadad !important;
|
||||
--md-code-hl-punctuation-color: #adadad !important;
|
||||
--home-border-color: #ffffff20;
|
||||
--home-shadow-color: #00000040;
|
||||
--home-image-border: linear-gradient(90deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.3) 50%, rgba(255, 255, 255, 0) 100%);
|
||||
|
||||
}
|
||||
|
||||
.md-typeset code {
|
||||
background-color: #cfcfcf;
|
||||
color: #1d1d1d;
|
||||
padding: 0.2rem;
|
||||
}
|
||||
|
||||
.md-typeset .md-button {
|
||||
color: var(--md-default-fg-color--light);
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
|
||||
/*
|
||||
:root{
|
||||
--md-default-fg-color: rgba(255, 255, 255, 0.87);
|
||||
--md-default-fg-color--light: rgba(255, 255, 255, 0.54);
|
||||
--md-default-fg-color--lighter: rgba(255, 255, 255, 0.32);
|
||||
--md-default-fg-color--lightest: rgba(255, 255, 255, 0.07);
|
||||
--md-default-bg-color: #1a2124;
|
||||
--md-typeset-a-color: var(--md-accent-fg-color) !important;
|
||||
}
|
||||
|
||||
.md-typeset code {
|
||||
background-color: #2f2f2f;
|
||||
}
|
||||
|
||||
|
||||
.highlight .c, .highlight .c1, .highlight .ch, .highlight .cm, .highlight .cs, .highlight .sd {
|
||||
color: #606060 !important;
|
||||
}
|
||||
@ -43,4 +87,3 @@
|
||||
.highlight .n {
|
||||
color: #1d1d1d;
|
||||
}
|
||||
|
||||
|
@ -6,3 +6,51 @@
|
||||
.code {
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.tag
|
||||
{
|
||||
background-color: var(--md-primary-fg-color);
|
||||
color: var(--md-default-bg-color);
|
||||
border-radius: 50px;
|
||||
padding-left: 0.15em;
|
||||
padding-right: 0.35em;
|
||||
padding-top: 0.45em;
|
||||
padding-bottom: 0.35em;
|
||||
}
|
||||
|
||||
.tag a
|
||||
{
|
||||
color: var(--md-default-bg-color);
|
||||
}
|
||||
|
||||
.tag a:hover
|
||||
{
|
||||
color: var(--md-default-bg-color);
|
||||
}
|
||||
|
||||
.md-typeset :is(.emojione, .twemoji, .gemoji)
|
||||
{
|
||||
vertical-align: text-bottom;
|
||||
}
|
||||
|
||||
.md-typeset :is(.emojione, .twemoji, .gemoji) svg
|
||||
{
|
||||
width: 1.25em;
|
||||
}
|
||||
|
||||
[data-md-color-scheme="crow-dark"] img[src$="#only-dark"]
|
||||
{
|
||||
display: block;
|
||||
}
|
||||
[data-md-color-scheme="crow-light"] img[src$="#only-light"]
|
||||
{
|
||||
display: block;
|
||||
}
|
||||
[data-md-color-scheme="crow-light"] img[src$="#only-dark"]
|
||||
{
|
||||
display: none;
|
||||
}
|
||||
[data-md-color-scheme="crow-dark"] img[src$="#only-light"]
|
||||
{
|
||||
display: none;
|
||||
}
|
||||
|
5
docs/versions.json
Normal file
5
docs/versions.json
Normal file
@ -0,0 +1,5 @@
|
||||
[
|
||||
{"version": "master", "title": "master", "aliases": []},
|
||||
{"version": "1.0", "title": "1.0+3", "aliases": []},
|
||||
{"version": "0.3", "title": "0.3+4", "aliases": []}
|
||||
]
|
@ -87,6 +87,10 @@ add_executable(example_cors middlewares/example_cors.cpp)
|
||||
add_warnings_optimizations(example_cors)
|
||||
target_link_libraries(example_cors PUBLIC Crow::Crow)
|
||||
|
||||
add_executable(example_cookies middlewares/example_cookies.cpp)
|
||||
add_warnings_optimizations(example_cookies)
|
||||
target_link_libraries(example_cookies PUBLIC Crow::Crow)
|
||||
|
||||
if(MSVC)
|
||||
add_executable(example_vs example_vs.cpp)
|
||||
add_warnings_optimizations(example_vs)
|
||||
|
@ -1,4 +1,4 @@
|
||||
//#define CROW_STATIC_DRIECTORY "alternative_directory/"
|
||||
//#define CROW_STATIC_DIRECTORY "alternative_directory/"
|
||||
//#define CROW_STATIC_ENDPOINT "/alternative_endpoint/<path>"
|
||||
//#define CROW_DISABLE_STATIC_DIR
|
||||
#include "crow.h"
|
||||
|
32
examples/middlewares/example_cookies.cpp
Normal file
32
examples/middlewares/example_cookies.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
#include "crow.h"
|
||||
#include "crow/middlewares/cookie_parser.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
// Include CookieParser middleware
|
||||
crow::App<crow::CookieParser> app;
|
||||
|
||||
CROW_ROUTE(app, "/read")
|
||||
([&](const crow::request& req) {
|
||||
auto& ctx = app.get_context<crow::CookieParser>(req);
|
||||
// Read cookies with get_cookie
|
||||
auto value = ctx.get_cookie("key");
|
||||
return "value: " + value;
|
||||
});
|
||||
|
||||
CROW_ROUTE(app, "/write")
|
||||
([&](const crow::request& req) {
|
||||
auto& ctx = app.get_context<crow::CookieParser>(req);
|
||||
// Store cookies with set_cookie
|
||||
ctx.set_cookie("key", "word")
|
||||
// configure additional parameters
|
||||
.path("/")
|
||||
.max_age(120)
|
||||
.httponly();
|
||||
return "ok!";
|
||||
});
|
||||
|
||||
app.port(18080).run();
|
||||
|
||||
return 0;
|
||||
}
|
@ -10,8 +10,7 @@ int main()
|
||||
std::mutex mtx;
|
||||
std::unordered_set<crow::websocket::connection*> users;
|
||||
|
||||
CROW_ROUTE(app, "/ws")
|
||||
.websocket()
|
||||
CROW_WEBSOCKET_ROUTE(app, "/ws")
|
||||
.onopen([&](crow::websocket::connection& conn) {
|
||||
CROW_LOG_INFO << "new websocket connection from " << conn.get_remote_ip();
|
||||
std::lock_guard<std::mutex> _(mtx);
|
||||
|
@ -29,6 +29,7 @@
|
||||
#else
|
||||
#define CROW_ROUTE(app, url) app.route<crow::black_magic::get_parameter_tag(url)>(url)
|
||||
#define CROW_BP_ROUTE(blueprint, url) blueprint.new_rule_tagged<crow::black_magic::get_parameter_tag(url)>(url)
|
||||
#define CROW_WEBSOCKET_ROUTE(app, url) app.route<crow::black_magic::get_parameter_tag(url)>(url).websocket<decltype(app)>(&app)
|
||||
#define CROW_MIDDLEWARES(app, ...) middlewares<std::remove_reference<decltype(app)>::type, __VA_ARGS__>()
|
||||
#endif
|
||||
#define CROW_CATCHALL_ROUTE(app) app.catchall_route()
|
||||
@ -61,7 +62,7 @@ namespace crow
|
||||
/// Process an Upgrade request
|
||||
|
||||
///
|
||||
/// Currently used to upgrrade an HTTP connection to a WebSocket connection
|
||||
/// Currently used to upgrade an HTTP connection to a WebSocket connection
|
||||
template<typename Adaptor>
|
||||
void handle_upgrade(const request& req, response& res, Adaptor&& adaptor)
|
||||
{
|
||||
@ -342,7 +343,7 @@ namespace crow
|
||||
|
||||
#ifdef CROW_ENABLE_SSL
|
||||
|
||||
/// use certificate and key files for SSL
|
||||
/// Use certificate and key files for SSL
|
||||
self_t& ssl_file(const std::string& crt_filename, const std::string& key_filename)
|
||||
{
|
||||
ssl_used_ = true;
|
||||
@ -355,7 +356,7 @@ namespace crow
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// use .pem file for SSL
|
||||
/// Use .pem file for SSL
|
||||
self_t& ssl_file(const std::string& pem_filename)
|
||||
{
|
||||
ssl_used_ = true;
|
||||
@ -367,6 +368,19 @@ namespace crow
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Use certificate chain and key files for SSL
|
||||
self_t& ssl_chainfile(const std::string& crt_filename, const std::string& key_filename)
|
||||
{
|
||||
ssl_used_ = true;
|
||||
ssl_context_.set_verify_mode(boost::asio::ssl::verify_peer);
|
||||
ssl_context_.set_verify_mode(boost::asio::ssl::verify_client_once);
|
||||
ssl_context_.use_certificate_chain_file(crt_filename);
|
||||
ssl_context_.use_private_key_file(key_filename, ssl_context_t::pem);
|
||||
ssl_context_.set_options(
|
||||
boost::asio::ssl::context::default_workarounds | boost::asio::ssl::context::no_sslv2 | boost::asio::ssl::context::no_sslv3);
|
||||
return *this;
|
||||
}
|
||||
|
||||
self_t& ssl(boost::asio::ssl::context&& ctx)
|
||||
{
|
||||
ssl_used_ = true;
|
||||
@ -390,6 +404,17 @@ namespace crow
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T, typename... Remain>
|
||||
self_t& ssl_chainfile(T&&, Remain&&...)
|
||||
{
|
||||
// We can't call .ssl() member function unless CROW_ENABLE_SSL is defined.
|
||||
static_assert(
|
||||
// make static_assert dependent to T; always false
|
||||
std::is_base_of<T, void>::value,
|
||||
"Define CROW_ENABLE_SSL to enable ssl support.");
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
self_t& ssl(T&&)
|
||||
{
|
||||
|
@ -417,6 +417,7 @@ namespace crow
|
||||
{
|
||||
is_writing = true;
|
||||
boost::asio::write(adaptor_.socket(), buffers_); // Write the response start / headers
|
||||
cancel_deadline_timer();
|
||||
if (res.body.length() > 0)
|
||||
{
|
||||
std::string buf;
|
||||
|
@ -1,4 +1,6 @@
|
||||
#pragma once
|
||||
#include <iomanip>
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/algorithm/string/trim.hpp>
|
||||
#include "crow/http_request.h"
|
||||
#include "crow/http_response.h"
|
||||
@ -30,10 +32,144 @@ namespace crow
|
||||
|
||||
struct CookieParser
|
||||
{
|
||||
// Cookie stores key, value and attributes
|
||||
struct Cookie
|
||||
{
|
||||
enum class SameSitePolicy
|
||||
{
|
||||
Strict,
|
||||
Lax,
|
||||
None
|
||||
};
|
||||
|
||||
template<typename U>
|
||||
Cookie(const std::string& key, U&& value):
|
||||
Cookie()
|
||||
{
|
||||
key_ = key;
|
||||
value_ = std::forward<U>(value);
|
||||
}
|
||||
|
||||
// format cookie to HTTP header format
|
||||
std::string dump() const
|
||||
{
|
||||
const static char* HTTP_DATE_FORMAT = "%a, %d %b %Y %H:%M:%S GMT";
|
||||
|
||||
std::stringstream ss;
|
||||
ss << key_ << '=';
|
||||
ss << (value_.empty() ? "\"\"" : value_);
|
||||
dumpString(ss, !domain_.empty(), "Domain=", domain_);
|
||||
dumpString(ss, !path_.empty(), "Path=", path_);
|
||||
dumpString(ss, secure_, "Secure");
|
||||
dumpString(ss, httponly_, "HttpOnly");
|
||||
if (expires_at_)
|
||||
{
|
||||
ss << DIVIDER << "Expires="
|
||||
<< std::put_time(expires_at_.get_ptr(), HTTP_DATE_FORMAT);
|
||||
}
|
||||
if (max_age_)
|
||||
{
|
||||
ss << DIVIDER << "Max-Age=" << *max_age_;
|
||||
}
|
||||
if (same_site_)
|
||||
{
|
||||
ss << DIVIDER << "SameSite=";
|
||||
switch (*same_site_)
|
||||
{
|
||||
case SameSitePolicy::Strict:
|
||||
ss << "Strict";
|
||||
break;
|
||||
case SameSitePolicy::Lax:
|
||||
ss << "Lax";
|
||||
break;
|
||||
case SameSitePolicy::None:
|
||||
ss << "None";
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
// Expires attribute
|
||||
Cookie& expires(const std::tm& time)
|
||||
{
|
||||
expires_at_ = time;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Max-Age attribute
|
||||
Cookie& max_age(long long seconds)
|
||||
{
|
||||
max_age_ = seconds;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Domain attribute
|
||||
Cookie& domain(const std::string& name)
|
||||
{
|
||||
domain_ = name;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Path attribute
|
||||
Cookie& path(const std::string& path)
|
||||
{
|
||||
path_ = path;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Secured attribute
|
||||
Cookie& secure()
|
||||
{
|
||||
secure_ = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// HttpOnly attribute
|
||||
Cookie& httponly()
|
||||
{
|
||||
httponly_ = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// SameSite attribute
|
||||
Cookie& same_site(SameSitePolicy ssp)
|
||||
{
|
||||
same_site_ = ssp;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
Cookie() = default;
|
||||
|
||||
static void dumpString(std::stringstream& ss, bool cond, const char* prefix,
|
||||
const std::string& value = "")
|
||||
{
|
||||
if (cond)
|
||||
{
|
||||
ss << DIVIDER << prefix << value;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::string key_;
|
||||
std::string value_;
|
||||
boost::optional<long long> max_age_{};
|
||||
std::string domain_ = "";
|
||||
std::string path_ = "";
|
||||
bool secure_ = false;
|
||||
bool httponly_ = false;
|
||||
boost::optional<std::tm> expires_at_{};
|
||||
boost::optional<SameSitePolicy> same_site_{};
|
||||
|
||||
static constexpr const char* DIVIDER = "; ";
|
||||
};
|
||||
|
||||
|
||||
struct context
|
||||
{
|
||||
std::unordered_map<std::string, std::string> jar;
|
||||
std::unordered_map<std::string, std::string> cookies_to_add;
|
||||
std::vector<Cookie> cookies_to_add;
|
||||
|
||||
std::string get_cookie(const std::string& key) const
|
||||
{
|
||||
@ -43,14 +179,17 @@ namespace crow
|
||||
return {};
|
||||
}
|
||||
|
||||
void set_cookie(const std::string& key, const std::string& value)
|
||||
template<typename U>
|
||||
Cookie& set_cookie(const std::string& key, U&& value)
|
||||
{
|
||||
cookies_to_add.emplace(key, value);
|
||||
cookies_to_add.emplace_back(key, std::forward<U>(value));
|
||||
return cookies_to_add.back();
|
||||
}
|
||||
};
|
||||
|
||||
void before_handle(request& req, response& res, context& ctx)
|
||||
{
|
||||
// TODO(dranikpg): remove copies, use string_view with c++17
|
||||
int count = req.headers.count("Cookie");
|
||||
if (!count)
|
||||
return;
|
||||
@ -97,12 +236,9 @@ namespace crow
|
||||
|
||||
void after_handle(request& /*req*/, response& res, context& ctx)
|
||||
{
|
||||
for (auto& cookie : ctx.cookies_to_add)
|
||||
for (const auto& cookie : ctx.cookies_to_add)
|
||||
{
|
||||
if (cookie.second.empty())
|
||||
res.add_header("Set-Cookie", cookie.first + "=\"\"");
|
||||
else
|
||||
res.add_header("Set-Cookie", cookie.first + "=" + cookie.second);
|
||||
res.add_header("Set-Cookie", cookie.dump());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -42,7 +42,7 @@ namespace crow
|
||||
return empty;
|
||||
}
|
||||
|
||||
/// Same as \ref get_header_value_Object() but for \ref multipart.header
|
||||
/// Same as \ref get_header_value_object() but for \ref multipart.header
|
||||
template<typename T>
|
||||
inline const header& get_header_object(const T& headers, const std::string& key)
|
||||
{
|
||||
|
@ -368,13 +368,15 @@ namespace crow
|
||||
|
||||
///
|
||||
/// Provides the interface for the user to put in the necessary handlers for a websocket to work.
|
||||
template<typename App>
|
||||
class WebSocketRule : public BaseRule
|
||||
{
|
||||
using self_t = WebSocketRule;
|
||||
|
||||
public:
|
||||
WebSocketRule(std::string rule):
|
||||
BaseRule(std::move(rule))
|
||||
WebSocketRule(std::string rule, App* app):
|
||||
BaseRule(std::move(rule)),
|
||||
app_(app)
|
||||
{}
|
||||
|
||||
void validate() override
|
||||
@ -388,12 +390,12 @@ namespace crow
|
||||
|
||||
void handle_upgrade(const request& req, response&, SocketAdaptor&& adaptor) override
|
||||
{
|
||||
new crow::websocket::Connection<SocketAdaptor>(req, std::move(adaptor), open_handler_, message_handler_, close_handler_, error_handler_, accept_handler_);
|
||||
new crow::websocket::Connection<SocketAdaptor, App>(req, std::move(adaptor), app_, open_handler_, message_handler_, close_handler_, error_handler_, accept_handler_);
|
||||
}
|
||||
#ifdef CROW_ENABLE_SSL
|
||||
void handle_upgrade(const request& req, response&, SSLAdaptor&& adaptor) override
|
||||
{
|
||||
new crow::websocket::Connection<SSLAdaptor>(req, std::move(adaptor), open_handler_, message_handler_, close_handler_, error_handler_, accept_handler_);
|
||||
new crow::websocket::Connection<SSLAdaptor, App>(req, std::move(adaptor), app_, open_handler_, message_handler_, close_handler_, error_handler_, accept_handler_);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -433,6 +435,7 @@ namespace crow
|
||||
}
|
||||
|
||||
protected:
|
||||
App* app_;
|
||||
std::function<void(crow::websocket::connection&)> open_handler_;
|
||||
std::function<void(crow::websocket::connection&, const std::string&, bool)> message_handler_;
|
||||
std::function<void(crow::websocket::connection&, const std::string&)> close_handler_;
|
||||
@ -448,9 +451,11 @@ namespace crow
|
||||
struct RuleParameterTraits
|
||||
{
|
||||
using self_t = T;
|
||||
WebSocketRule& websocket()
|
||||
|
||||
template<typename App>
|
||||
WebSocketRule<App>& websocket(App* app)
|
||||
{
|
||||
auto p = new WebSocketRule(static_cast<self_t*>(this)->rule_);
|
||||
auto p = new WebSocketRule<App>(static_cast<self_t*>(this)->rule_, app);
|
||||
static_cast<self_t*>(this)->rule_to_upgrade_.reset(p);
|
||||
return *p;
|
||||
}
|
||||
@ -1468,7 +1473,6 @@ namespace crow
|
||||
allow = allow.substr(0, allow.size() - 2);
|
||||
res = response(204);
|
||||
res.set_header("Allow", allow);
|
||||
res.manual_length_header = true;
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
@ -1486,7 +1490,6 @@ namespace crow
|
||||
allow = allow.substr(0, allow.size() - 2);
|
||||
res = response(204);
|
||||
res.set_header("Allow", allow);
|
||||
res.manual_length_header = true;
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
|
@ -59,6 +59,6 @@
|
||||
#if __cplusplus > 201103L
|
||||
#define CROW_GCC83_WORKAROUND
|
||||
#else
|
||||
#error "GCC 8.1 - 8.3 has a bug that prevents crow from compiling with C++11. Please update GCC to > 8.3 or use C++ > 11."
|
||||
#error "GCC 8.1 - 8.3 has a bug that prevents Crow from compiling with C++11. Please update GCC to > 8.3 or use C++ > 11."
|
||||
#endif
|
||||
#endif
|
||||
|
@ -60,7 +60,7 @@ namespace crow
|
||||
//
|
||||
|
||||
/// A websocket connection.
|
||||
template<typename Adaptor>
|
||||
template<typename Adaptor, typename Handler>
|
||||
class Connection : public connection
|
||||
{
|
||||
public:
|
||||
@ -69,14 +69,19 @@ namespace crow
|
||||
///
|
||||
/// Requires a request with an "Upgrade: websocket" header.<br>
|
||||
/// Automatically handles the handshake.
|
||||
Connection(const crow::request& req, Adaptor&& adaptor,
|
||||
Connection(const crow::request& req, Adaptor&& adaptor, Handler* handler,
|
||||
std::function<void(crow::websocket::connection&)> open_handler,
|
||||
std::function<void(crow::websocket::connection&, const std::string&, bool)> message_handler,
|
||||
std::function<void(crow::websocket::connection&, const std::string&)> close_handler,
|
||||
std::function<void(crow::websocket::connection&)> error_handler,
|
||||
std::function<bool(const crow::request&)> accept_handler):
|
||||
adaptor_(std::move(adaptor)),
|
||||
open_handler_(std::move(open_handler)), message_handler_(std::move(message_handler)), close_handler_(std::move(close_handler)), error_handler_(std::move(error_handler)), accept_handler_(std::move(accept_handler))
|
||||
handler_(handler),
|
||||
open_handler_(std::move(open_handler)),
|
||||
message_handler_(std::move(message_handler)),
|
||||
close_handler_(std::move(close_handler)),
|
||||
error_handler_(std::move(error_handler)),
|
||||
accept_handler_(std::move(accept_handler))
|
||||
{
|
||||
if (!boost::iequals(req.get_header_value("upgrade"), "websocket"))
|
||||
{
|
||||
@ -617,6 +622,7 @@ namespace crow
|
||||
|
||||
private:
|
||||
Adaptor adaptor_;
|
||||
Handler* handler_;
|
||||
|
||||
std::vector<std::string> sending_buffers_;
|
||||
std::vector<std::string> write_buffers_;
|
||||
|
154
mkdocs.yml
154
mkdocs.yml
@ -7,81 +7,103 @@ site_url: https://crowcpp.org
|
||||
edit_uri: ""
|
||||
|
||||
theme:
|
||||
name: material
|
||||
font: false
|
||||
language: 'en'
|
||||
features:
|
||||
navigation.tabs
|
||||
favicon: 'assets/favicon.svg'
|
||||
logo: 'assets/favicon.svg'
|
||||
icon:
|
||||
repo: fontawesome/brands/github-square
|
||||
static_templates:
|
||||
- privacy_policy.html
|
||||
custom_dir: docs/overrides
|
||||
name: material
|
||||
font: false
|
||||
language: 'en'
|
||||
features:
|
||||
navigation.tabs
|
||||
favicon: 'assets/favicon.svg'
|
||||
logo: 'assets/favicon.svg'
|
||||
icon:
|
||||
repo: fontawesome/brands/github-square
|
||||
static_templates:
|
||||
- privacy_policy.html
|
||||
palette:
|
||||
- media: "(prefers-color-scheme: light)"
|
||||
scheme: crow-light
|
||||
toggle:
|
||||
icon: fontawesome/solid/sun
|
||||
name: Using Light Theme
|
||||
- media: "(prefers-color-scheme: dark)"
|
||||
scheme: crow-dark
|
||||
toggle:
|
||||
icon: fontawesome/solid/moon
|
||||
name: Using Dark Theme
|
||||
custom_dir: docs/overrides
|
||||
|
||||
markdown_extensions:
|
||||
- admonition
|
||||
- pymdownx.highlight
|
||||
- pymdownx.tabbed
|
||||
- pymdownx.superfences
|
||||
- pymdownx.inlinehilite
|
||||
- pymdownx.keys
|
||||
- toc:
|
||||
permalink: true
|
||||
- admonition
|
||||
- pymdownx.highlight
|
||||
- pymdownx.tabbed
|
||||
- pymdownx.superfences
|
||||
- pymdownx.inlinehilite
|
||||
- pymdownx.keys
|
||||
- attr_list
|
||||
- pymdownx.emoji:
|
||||
emoji_index: !!python/name:materialx.emoji.twemoji
|
||||
emoji_generator: !!python/name:materialx.emoji.to_svg
|
||||
|
||||
|
||||
nav:
|
||||
- Home: index.md
|
||||
- Getting Started:
|
||||
- Setup:
|
||||
- Linux: getting_started/setup/linux.md
|
||||
- MacOS: getting_started/setup/macos.md
|
||||
- Windows: getting_started/setup/windows.md
|
||||
- Your First Application: getting_started/your_first_application.md
|
||||
- Guides:
|
||||
- Different parts of Crow:
|
||||
- App: guides/app.md
|
||||
- Routes: guides/routes.md
|
||||
- Logging: guides/logging.md
|
||||
- JSON: guides/json.md
|
||||
- Templating (Mustache): guides/templating.md
|
||||
- Multipart: guides/multipart.md
|
||||
- Query Strings: guides/query-string.md
|
||||
- Middleware: guides/middleware.md
|
||||
- SSL: guides/ssl.md
|
||||
- Static Files: guides/static.md
|
||||
- Blueprints: guides/blueprints.md
|
||||
- Compression: guides/compression.md
|
||||
- Websockets: guides/websockets.md
|
||||
- Base64: guides/base64.md
|
||||
- Writing Tests: guides/testing.md
|
||||
- Using Crow:
|
||||
- HTTP Authorization: guides/auth.md
|
||||
- CORS Setup: guides/CORS.md
|
||||
- Server setup:
|
||||
- Proxies: guides/proxies.md
|
||||
- Systemd run on startup: guides/syste.md
|
||||
- API Reference:
|
||||
- API Reference: 'reference/index.html'
|
||||
- Home: index.md
|
||||
- Getting Started:
|
||||
- Setup:
|
||||
- Linux: getting_started/setup/linux.md
|
||||
- MacOS: getting_started/setup/macos.md
|
||||
- Windows: getting_started/setup/windows.md
|
||||
- Your First Application: getting_started/your_first_application.md
|
||||
- Guides:
|
||||
- Different parts of Crow:
|
||||
- App: guides/app.md
|
||||
- Routes: guides/routes.md
|
||||
- Logging: guides/logging.md
|
||||
- JSON: guides/json.md
|
||||
- Templating (Mustache): guides/templating.md
|
||||
- Multipart: guides/multipart.md
|
||||
- Query Strings: guides/query-string.md
|
||||
- Middleware: guides/middleware.md
|
||||
- SSL: guides/ssl.md
|
||||
- Static Files: guides/static.md
|
||||
- Blueprints: guides/blueprints.md
|
||||
- Compression: guides/compression.md
|
||||
- Websockets: guides/websockets.md
|
||||
- Base64: guides/base64.md
|
||||
- Writing Tests: guides/testing.md
|
||||
- Using Crow:
|
||||
- HTTP Authorization: guides/auth.md
|
||||
- Included Middlewares: guides/included-middleware.md
|
||||
- Server setup:
|
||||
- Proxies: guides/proxies.md
|
||||
- Systemd run on startup: guides/syste.md
|
||||
- API Reference:
|
||||
- API Reference: 'reference/index.html'
|
||||
|
||||
extra:
|
||||
analytics:
|
||||
provider: matomo
|
||||
id: 1
|
||||
link: //thee.dev/matomo/
|
||||
social:
|
||||
- icon: fontawesome/brands/github
|
||||
link: https://github.com/crowcpp/crow
|
||||
- icon: fontawesome/brands/gitter
|
||||
link: https://gitter.im/crowfork/community
|
||||
version:
|
||||
provider: mike
|
||||
default: latest
|
||||
analytics:
|
||||
provider: matomo
|
||||
id: 1
|
||||
link: //thee.dev/matomo/
|
||||
social:
|
||||
- icon: fontawesome/brands/github
|
||||
link: https://github.com/crowcpp/crow
|
||||
- icon: fontawesome/brands/gitter
|
||||
link: https://gitter.im/crowfork/community
|
||||
|
||||
plugins:
|
||||
- redirects:
|
||||
redirect_maps:
|
||||
'getting_started/setup/': 'getting_started/setup/linux.md'
|
||||
- meta-descriptions
|
||||
- redirects:
|
||||
redirect_maps:
|
||||
'getting_started/setup/': 'getting_started/setup/linux.md'
|
||||
- meta-descriptions
|
||||
- search
|
||||
|
||||
extra_css:
|
||||
- 'stylesheets/colors.css'
|
||||
- 'stylesheets/latofonts.css'
|
||||
- 'stylesheets/extra.css'
|
||||
- 'stylesheets/colors.css'
|
||||
- 'stylesheets/latofonts.css'
|
||||
- 'stylesheets/extra.css'
|
||||
|
||||
copyright: 'Copyright © 2020-2022 CrowCpp'
|
||||
|
45
scripts/generateDocumentationAndDeploy.sh
Normal file → Executable file
45
scripts/generateDocumentationAndDeploy.sh
Normal file → Executable file
@ -2,14 +2,14 @@
|
||||
################################################################################
|
||||
# Title : generateDocumentationAndDeploy.sh
|
||||
# Date created : 2016/02/22
|
||||
# Notes : This script was modified to suit Crow and work with mkdocs and Drone.io CI.
|
||||
# Notes : This script was modified to suit Crow and work with mkdocs (multiple versions) and Drone.io CI.
|
||||
__AUTHOR__="Jeroen de Bruijn"
|
||||
# Preconditions:
|
||||
# - Packages doxygen doxygen-doc doxygen-latex doxygen-gui graphviz
|
||||
# must be installed.
|
||||
# - Doxygen configuration file must have the destination directory empty and
|
||||
# source code directory with a $(TRAVIS_BUILD_DIR) prefix.
|
||||
# - An gh-pages branch should already exist. See below for mor info on hoe to
|
||||
# - A gh-pages branch should already exist. See below for more info on how to
|
||||
# create a gh-pages branch.
|
||||
#
|
||||
# Required global variables:
|
||||
@ -19,6 +19,7 @@ __AUTHOR__="Jeroen de Bruijn"
|
||||
# - GH_REPO_NAME : The name of the repository.
|
||||
# - GH_REPO_REF : The GitHub reference to the repository.
|
||||
# - GH_REPO_TOKEN : Secure token to the github repository.
|
||||
# - DOCS_VERSION : Used for custom version documentation (defaults to master).
|
||||
#
|
||||
# For information on how to encrypt variables for Travis CI please go to
|
||||
# https://docs.travis-ci.com/user/environment-variables/#Encrypted-Variables
|
||||
@ -30,15 +31,25 @@ __AUTHOR__="Jeroen de Bruijn"
|
||||
# the gh-pages branch of a repository specified by GH_REPO_REF.
|
||||
# Before this script is used there should already be a gh-pages branch in the
|
||||
# repository.
|
||||
#
|
||||
# The branch should be empty except for an empty '.nojekyll' file and an
|
||||
# 'index.html' file that redirects to master/index.html. Optionally you would
|
||||
# also need a 'CNAME' file containing your custom domain (without http or www).
|
||||
#
|
||||
################################################################################
|
||||
################################################################################
|
||||
|
||||
|
||||
################################################################################
|
||||
##### Setup this script and get the current gh-pages branch. #####
|
||||
##### Setup this script and get the current gh-pages branch. #####
|
||||
|
||||
echo 'Setting up the script...'
|
||||
# Exit with nonzero exit code if anything fails
|
||||
set -e
|
||||
|
||||
DOCS_VERSION=${DOCS_VERSION:-"master"}
|
||||
echo "Using $DOCS_VERSION as version."
|
||||
|
||||
# Create a clean working directory for this script.
|
||||
mkdir code_docs
|
||||
cd code_docs
|
||||
@ -55,29 +66,38 @@ git config --global push.default simple
|
||||
git config user.name "Drone CI"
|
||||
git config user.email "drone@drone.io"
|
||||
|
||||
# Remove everything currently in the gh-pages branch.
|
||||
# Create a new directory for this version of the docs if one doesn't exist.
|
||||
# Then navigate to that directory.
|
||||
mkdir -p $DOCS_VERSION
|
||||
cd $DOCS_VERSION
|
||||
|
||||
################################################################################
|
||||
##### Generate the MkDocs documentation to replace the old docs. #####
|
||||
|
||||
echo 'Removing old documentation...'
|
||||
# Remove everything currently in the version directory.
|
||||
# GitHub is smart enough to know which files have changed and which files have
|
||||
# stayed the same and will only update the changed files. So the gh-pages branch
|
||||
# can be safely cleaned, and it is sure that everything pushed later is the new
|
||||
# documentation.
|
||||
cp CNAME ..
|
||||
rm -rf *
|
||||
mv ../CNAME .
|
||||
|
||||
# Copy the mkdocs documentation to the work directory and generate the mkdocs
|
||||
echo 'Generating MkDocs documentation...'
|
||||
# Copy the mkdocs documentation to the work directory and generate the mkdocs'
|
||||
# 'site' directory
|
||||
cp ../../mkdocs.yml .
|
||||
cp -r ../../docs .
|
||||
cp ../../../mkdocs.yml .
|
||||
cp -r ../../../docs .
|
||||
mkdocs build -v
|
||||
|
||||
# Need to create a .nojekyll file to allow filenames starting with an underscore
|
||||
# to be seen on the gh-pages site. Therefore creating an empty .nojekyll file.
|
||||
# Presumably this is only needed when the SHORT_NAMES option in Doxygen is set
|
||||
# to NO, which it is by default. So creating the file just in case.
|
||||
echo "" > .nojekyll
|
||||
#echo "" > .nojekyll
|
||||
|
||||
################################################################################
|
||||
##### Generate the Doxygen code documentation and log the output. #####
|
||||
##### Generate the Doxygen code documentation and log the output. #####
|
||||
|
||||
echo 'Generating Doxygen code documentation...'
|
||||
# Redirect both stderr and stdout to the log file AND the console.
|
||||
doxygen $DOXYFILE 2>&1 | tee doxygen.log
|
||||
@ -89,9 +109,10 @@ mv site/* .
|
||||
rm -r site
|
||||
rm mkdocs.yml
|
||||
rm -r docs
|
||||
mv versions.json ../
|
||||
|
||||
################################################################################
|
||||
##### Upload the documentation to the gh-pages branch of the repository. #####
|
||||
##### Upload the documentation to the gh-pages branch of the repository. #####
|
||||
# Only upload if Doxygen successfully created the documentation.
|
||||
# Check this by verifying that the reference directory (for doxygen) and
|
||||
# the file index.html (for mkdocs) both exist.
|
||||
|
@ -1452,7 +1452,7 @@ TEST_CASE("local_middleware")
|
||||
app.stop();
|
||||
} // local_middleware
|
||||
|
||||
TEST_CASE("middleware_cookieparser")
|
||||
TEST_CASE("middleware_cookieparser_parse")
|
||||
{
|
||||
static char buf[2048];
|
||||
|
||||
@ -1499,9 +1499,56 @@ TEST_CASE("middleware_cookieparser")
|
||||
CHECK("val\"ue4" == value4);
|
||||
}
|
||||
app.stop();
|
||||
} // middleware_cookieparser
|
||||
} // middleware_cookieparser_parse
|
||||
|
||||
|
||||
TEST_CASE("middleware_cookieparser_format")
|
||||
{
|
||||
using Cookie = CookieParser::Cookie;
|
||||
|
||||
auto valid = [](const std::string& s, int parts) {
|
||||
return std::count(s.begin(), s.end(), ';') == parts - 1;
|
||||
};
|
||||
|
||||
// basic
|
||||
{
|
||||
auto c = Cookie("key", "value");
|
||||
auto s = c.dump();
|
||||
CHECK(valid(s, 1));
|
||||
CHECK(s == "key=value");
|
||||
}
|
||||
// max-age + domain
|
||||
{
|
||||
auto c = Cookie("key", "value")
|
||||
.max_age(123)
|
||||
.domain("example.com");
|
||||
auto s = c.dump();
|
||||
CHECK(valid(s, 3));
|
||||
CHECK(s.find("key=value") != std::string::npos);
|
||||
CHECK(s.find("Max-Age=123") != std::string::npos);
|
||||
CHECK(s.find("Domain=example.com") != std::string::npos);
|
||||
}
|
||||
// samesite + secure
|
||||
{
|
||||
auto c = Cookie("key", "value")
|
||||
.secure()
|
||||
.same_site(Cookie::SameSitePolicy::None);
|
||||
auto s = c.dump();
|
||||
CHECK(valid(s, 3));
|
||||
CHECK(s.find("Secure") != std::string::npos);
|
||||
CHECK(s.find("SameSite=None") != std::string::npos);
|
||||
}
|
||||
// expires
|
||||
{
|
||||
auto tp = boost::posix_time::time_from_string("2000-11-01 23:59:59.000");
|
||||
auto c = Cookie("key", "value")
|
||||
.expires(boost::posix_time::to_tm(tp));
|
||||
auto s = c.dump();
|
||||
CHECK(valid(s, 2));
|
||||
CHECK(s.find("Expires=Wed, 01 Nov 2000 23:59:59 GMT") != std::string::npos);
|
||||
}
|
||||
} // middleware_cookieparser_format
|
||||
|
||||
TEST_CASE("middleware_cors")
|
||||
{
|
||||
static char buf[5012];
|
||||
@ -2044,15 +2091,15 @@ TEST_CASE("stream_response")
|
||||
// magic number is 102 (it's the size of the headers, which is how much this line below needs to read)
|
||||
const size_t headers_bytes = 102;
|
||||
while (received_headers_bytes < headers_bytes)
|
||||
received_headers_bytes += c.receive(asio::buffer(buf, 2048));
|
||||
received_headers_bytes += c.receive(asio::buffer(buf, 102));
|
||||
received += received_headers_bytes - headers_bytes; //add any extra that might have been received to the proper received count
|
||||
|
||||
|
||||
while (received < key_response_size)
|
||||
{
|
||||
asio::streambuf::mutable_buffers_type bufs = b.prepare(16384);
|
||||
|
||||
size_t n = c.receive(bufs);
|
||||
size_t n(0);
|
||||
n = c.receive(bufs);
|
||||
b.commit(n);
|
||||
received += n;
|
||||
|
||||
@ -2061,8 +2108,6 @@ TEST_CASE("stream_response")
|
||||
is >> s;
|
||||
|
||||
CHECK(key_response.substr(received - n, n) == s);
|
||||
|
||||
//std::this_thread::sleep_for(std::chrono::milliseconds(20));
|
||||
}
|
||||
}
|
||||
app.stop();
|
||||
@ -2078,10 +2123,10 @@ TEST_CASE("websocket")
|
||||
|
||||
SimpleApp app;
|
||||
|
||||
CROW_ROUTE(app, "/ws").websocket().onopen([&](websocket::connection&) {
|
||||
connected = true;
|
||||
CROW_LOG_INFO << "Connected websocket and value is " << connected;
|
||||
})
|
||||
CROW_WEBSOCKET_ROUTE(app, "/ws").onopen([&](websocket::connection&) {
|
||||
connected = true;
|
||||
CROW_LOG_INFO << "Connected websocket and value is " << connected;
|
||||
})
|
||||
.onmessage([&](websocket::connection& conn, const std::string& message, bool isbin) {
|
||||
CROW_LOG_INFO << "Message is \"" << message << '\"';
|
||||
if (!isbin && message == "PINGME")
|
||||
|
Loading…
Reference in New Issue
Block a user