Merge branch 'master' into ssl_test

This commit is contained in:
Farook Al-Sammarraie 2021-08-18 13:13:29 +03:00 committed by GitHub
commit 84878ae4b1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
69 changed files with 3089 additions and 508 deletions

View File

@ -15,7 +15,7 @@ steps:
commands:
- export DEBIAN_FRONTEND=noninteractive
- export TRAVIS_BRANCH=$DRONE_SOURCE_BRANCH
- export TRAVIS_BRANCH=$DRONE_BRANCH
- export TRAVIS_JOB_ID=$DRONE_BUILD_NUMBER
- apt-get -y update
- apt-get -y install libboost-all-dev doxygen mkdocs graphviz zlib1g-dev gcc clang make cmake python3 python3-pip git openssl libssl-dev

3
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1,3 @@
# These are supported funding model platforms
open_collective: crow

View File

@ -76,3 +76,9 @@ endif()
# Install Files
#####################################
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/crow_all.h DESTINATION include)
set(CPACK_GENERATOR "DEB")
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "CrowCpp")
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
include(CPack)

View File

@ -38,7 +38,7 @@ PROJECT_NAME = Crow
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = 0.2
PROJECT_NUMBER = 0.3
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a

View File

@ -1,4 +1,5 @@
Copyright (c) 2014, ipkn
Copyright (c) 2014-2017, ipkn
2020-2021, CrowCpp
All rights reserved.
Redistribution and use in source and binary forms, with or without
@ -25,3 +26,5 @@ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The Crow logo and other graphic material (excluding third party logos) used are under Copyright (c) 2021, Farook Al-Sammarraie (The-EDev), All rights reserved.

View File

@ -1,11 +1,12 @@
<p align="center"><img src="https://crowcpp.org/assets/crowlogo.svg" width=600></p>
<p align="center"><img src="https://raw.githubusercontent.com/CrowCpp/Crow/master/docs/assets/crowlogo_dual_color.svg" width=600></p>
<h4 align="center">A Fast and Easy to use microframework for the web.</h4>
<p align="center">
<a href="https://cloud.drone.io/CrowCpp/crow"><img src="https://cloud.drone.io/api/badges/CrowCpp/crow/status.svg" alt="Build Status"></a>
<a href="https://coveralls.io/github/CrowCpp/crow?branch=master"><img src="https://coveralls.io/repos/github/CrowCpp/crow/badge.svg?branch=master" alt="Coverage Status"></a>
<a href="https://crowcpp.github.io/crow"><img src="https://img.shields.io/badge/-Documentation-informational" alt="Documentation"></a>
<a href="https://cloud.drone.io/CrowCpp/Crow"><img src="https://cloud.drone.io/api/badges/CrowCpp/Crow/status.svg" alt="Build Status"></a>
<a href="https://coveralls.io/github/CrowCpp/Crow?branch=master"><img src="https://coveralls.io/repos/github/CrowCpp/Crow/badge.svg?branch=master" alt="Coverage Status"></a>
<a href="https://crowcpp.org"><img src="https://img.shields.io/badge/-Documentation-informational" alt="Documentation"></a>
<a href="https://gitter.im/crowfork/community?utm_source=badge&amp;utm_medium=badge&amp;utm_campaign=pr-badge"><img src="https://badges.gitter.im/crowfork/community.svg" alt="Gitter"></a>
<a href="https://opencollective.com/crow"><img alt="Open Collective" src="https://img.shields.io/opencollective/all/crow?label=Support%20Crow&logo=opencollective"></a>
</p>
@ -29,12 +30,13 @@ Crow is a C++ microframework for running web services. It uses routing similar t
- [HTTP/2 support](https://github.com/crowcpp/crow/issues/8)
## Documentation
Available [here](https://crowcpp.github.io/crow).
Available [here](https://crowcpp.org).
## Examples
#### Hello World
```c++
```cpp
#define CROW_MAIN
#include "crow.h"
int main()
@ -97,12 +99,13 @@ CROW_ROUTE(app, "/add_json")
More examples can be found [here](https://github.com/crowcpp/crow/tree/master/examples).
## Setting Up / Building
Available [here](https://crowcpp.github.io/crow/getting_started/setup).
Available [here](https://crowcpp.org/getting_started/setup).
## Disclaimer
CrowCpp/Crow is a project based on ipkn/crow. Neither CrowCpp, it's members, or this project have been associated with, or endorsed or supported by ipkn (Jaeseung Ha) in any way. We do use ipkn/crow's source code under the BSD-3 clause license and sometimes refer to the public comments available on the github repository. But we do not in any way claim to be associated with or in contact with ipkn (Jaeseung Ha) regarding CrowCpp or CrowCpp/Crow
### Attributions
Crow uses the following libraries.
## Attributions
Crow has incorporated the following libraries into its source.
http-parser (used for converting http strings to crow::request objects)

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 15 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -0,0 +1,121 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="900"
height="400"
viewBox="0 0 238.12499 105.83333"
version="1.1"
id="svg8"
sodipodi:docname="crowlogo_inverted.svg"
inkscape:version="1.1 (c4e8f9ed74, 2021-05-24)"
inkscape:export-filename="/home/farook/vaiossd/Pictures/CrowLogo.png"
inkscape:export-xdpi="324.99619"
inkscape:export-ydpi="324.99619"
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"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.35"
inkscape:cx="281.42857"
inkscape:cy="511.42857"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
inkscape:document-rotation="0"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="1007"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
units="px"
inkscape:pagecheckerboard="0" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(2.890729,-78.735456)">
<path
id="rect51232"
style="stroke-width:1.621;stroke-linecap:round;stroke-linejoin:round;fill:#ffffff;fill-opacity:1"
d="m 86.263122,129.89227 c -1.679885,0.94306 -0.970661,50.071 -0.970661,50.071 h 8.67359 c 0,0 -1.146978,-23.39877 0.97066,-22.01299 5.738329,3.75514 18.678879,22.04105 18.678879,22.04105 l 10.82099,0.0233 c 0,0 -22.33706,-23.42311 -21.33927,-25.78171 0.99777,-2.35858 13.45284,-3.56535 14.28699,-5.61353 0.83414,-2.04817 0.74681,-7.53026 0.0119,-9.332 -0.73488,-1.80175 -17.951097,-8.50923 -22.459538,-9.39514 -4.508449,-0.88592 -6.875855,-1.00922 -8.67359,0 z m 8.673589,7.89629 c 0.435027,-0.21177 12.515509,4.68197 12.527659,5.49714 0.0113,0.76226 -12.065069,5.41359 -12.527659,5.04327 -0.327731,-0.26235 -0.43502,-10.32863 0,-10.54041 z"
sodipodi:nodetypes="sccscczzzzszssz" />
<path
id="path55748"
style="stroke-width:1.50035;stroke-linecap:round;stroke-linejoin:round;fill:#ffffff;fill-opacity:1"
d="m 214.40962,132.10711 c 0,0 -6.19646,30.36708 -7.43712,30.33831 -1.22676,-0.0284 -7.40908,-29.27248 -7.40908,-29.27248 l -7.84322,0.0207 c 0,0 -4.25108,28.63573 -6.44505,28.48646 -1.9928,-0.13558 -7.20545,-29.39322 -7.20545,-29.39322 l -7.79639,1.91192 11.03502,45.01483 7.88892,1.48481 c 0,0 5.4369,-26.82435 6.66418,-26.78989 1.22731,0.0345 7.42065,26.61016 7.42065,26.61016 l 7.88891,-1.4848 11.03501,-45.01483 z"
sodipodi:nodetypes="csccscccczcccc" />
<path
id="rect53235"
style="fill:none;stroke:#fefefe;stroke-width:8.65014;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 128.1657,156.63351 c 0.0252,15.02476 7.0482,20.22602 17.35625,20.23066 10.30804,0.005 17.61679,-6.50768 17.8414,-20.03302 0.2246,-13.52536 -8.11076,-20.48288 -17.43254,-20.41622 -9.32178,0.0666 -17.79031,5.1938 -17.76511,20.21858 z"
sodipodi:nodetypes="zzzzz" />
<path
style="color:#000000;fill:#ffffff;stroke-width:0.669208;-inkscape-stroke:none;fill-opacity:1"
d="m 75.361766,164.31848 c -1.522517,0.0929 -3.225106,0.23753 -5.059422,0.41007 -14.861309,1.39786 -38.370023,4.6261 -44.831721,-3.01508 -7.259264,-8.58431 -5.992766,-15.11802 -3.7379,-29.04552 2.254865,-13.92751 11.768175,-32.3183 23.453693,-33.61763 11.685519,-1.299327 24.289435,-0.14247 28.381026,1.21309 L 77.417321,85.791987 C 62.828148,82.27312 56.039475,80.867702 37.328615,83.440263 18.617756,86.012824 9.3053305,108.67011 6.7920712,129.55115 c -2.5132504,20.88098 -0.630659,37.59767 5.7039948,44.13904 6.334653,6.54136 43.941662,8.861 64.480651,5.0425 z"
id="path830"
sodipodi:nodetypes="csszzcczzzcc" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.150696px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 52.770285,159.45785 -1.325495,1.13614 c 0,0 1.379598,1.29845 1.866513,1.86651 0.486919,0.56807 3.056762,4.95033 3.273169,5.70775 0.21641,0.75743 1.136142,0.91974 1.839463,1.7042 0.703326,0.78449 2.109969,1.59601 1.08204,2.40754 -1.027937,0.81154 0.973835,0.35167 0.919732,-0.91972 -0.05411,-1.2714 1.893562,2.40754 0.513964,2.89445 -1.379593,0.48692 0.703322,0.51397 0.973835,0.0541 0.270504,-0.45986 0.405763,-1.29844 0.297562,-2.21817 -0.108205,-0.91974 -1.514856,-2.62395 -1.839468,-2.9215 -0.324607,-0.29757 1.541906,-0.18936 2.05587,0.48691 0.513978,0.67627 0.568071,0.89268 0.189357,1.46075 -0.37871,0.56808 1.487803,-0.45986 0.59513,-1.3796 -0.892688,-0.91972 -0.216416,-0.83858 -1.460759,-1.43369 -1.244344,-0.59513 -1.379598,-0.97385 -2.43458,-0.91973 -1.054986,0.0541 -6.546333,-7.92594 -6.546333,-7.92594 z"
id="path15574" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.150696px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 61.426586,156.42814 -1.568955,0.97384 3.597781,4.0306 c 0,0 1.866513,1.35254 1.487803,2.75918 -0.378714,1.40665 -1.352549,1.92063 -1.352549,1.92063 0,0 0.13525,0.24344 0.568067,0.24344 0.432817,0 0.973835,-1.40663 1.758317,-0.97382 0.784473,0.43282 1.893562,1.51484 2.082919,2.19112 0.189357,0.67628 0.05411,0.83858 0.162303,0.97383 0.108206,0.13526 0.676277,0.13526 0.595121,-0.43281 -0.08115,-0.56807 0.378714,-0.0271 0.486919,0.45986 0.10821,0.48692 0.459862,1.35255 0.405759,2.19113 -0.0541,0.83857 0.486919,1.65011 0.459875,0.43281 -0.02705,-1.21728 0.243455,-2.54278 -0.37871,-3.65187 -0.622174,-1.10909 -0.892687,-2.59688 0.08114,-1.62306 0.973839,0.97383 1.731268,1.08205 2.001776,1.78536 0.270509,0.70333 0.24346,0.86563 0.568067,0.86563 0.324612,0 0.135255,-0.97383 -0.459866,-1.65011 -0.595116,-0.67626 -0.622174,-1.35254 -2.326379,-2.21817 -1.704214,-0.86563 -2.623946,-1.73126 -4.436351,-3.38137 -1.812424,-1.65011 -3.73304,-4.89622 -3.73304,-4.89622 z"
id="path15576" />
<path
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.150696px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 55.533489,166.09236 c 0.531307,0.94733 0.967262,1.78287 1.050983,2.07589 0.21641,0.75743 1.136142,0.91974 1.839463,1.7042 0.703326,0.78449 2.109969,1.59601 1.08204,2.40754 -1.027937,0.81154 0.973835,0.35167 0.919732,-0.91972 -0.05411,-1.2714 1.893562,2.40754 0.513964,2.89445 -1.379593,0.48692 0.703322,0.51397 0.973835,0.0541 0.270504,-0.45986 0.405763,-1.29844 0.297562,-2.21817 -0.108205,-0.91974 -1.514856,-2.62395 -1.839468,-2.9215 -0.324607,-0.29757 1.541906,-0.18936 2.05587,0.48691 0.513978,0.67627 0.568071,0.89268 0.189357,1.46075 -0.37871,0.56808 1.487803,-0.45986 0.59513,-1.3796 -0.892688,-0.91972 -0.216416,-0.83858 -1.460759,-1.43369 -1.244344,-0.59513 -1.379598,-0.97384 -2.43458,-0.91973 -0.290776,0.015 -0.918584,-0.58052 -1.675534,-1.45097 z"
id="path16765"
sodipodi:nodetypes="cssssssssssssscc" />
<path
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.150696px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 65.263268,165.22329 c 0.194353,3.9e-4 0.291031,0.0149 0.484578,0.0788 0.564847,0.18634 2.110365,1.76478 2.252123,2.27108 0.189357,0.67628 0.05411,0.83858 0.162303,0.97383 0.108206,0.13526 0.676277,0.13526 0.595121,-0.43282 -0.08115,-0.56806 0.378714,-0.0271 0.486919,0.45987 0.10821,0.48691 0.459862,1.35254 0.405759,2.19113 -0.0541,0.83857 0.313763,1.62347 0.459875,0.43281 0.148298,-1.20852 0.243455,-2.54277 -0.37871,-3.65187 -0.622174,-1.10909 -0.892687,-2.59689 0.08114,-1.62306 0.973839,0.97383 1.731268,1.08204 2.001776,1.78536 0.270509,0.70333 0.24346,0.86563 0.568067,0.86563 0.324612,0 0.135255,-0.97383 -0.459866,-1.65011 -0.595116,-0.67626 -0.473424,-1.27723 -2.177629,-2.14286 z"
id="path16767"
sodipodi:nodetypes="csssssssssssscc" />
<path
id="path7288"
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.14952px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 49.18396,111.42134 c -1.800635,-0.0245 -5.26385,0.56015 -5.867743,1.66729 -0.644159,1.18095 -0.155808,1.17068 -0.155808,1.17068 0,0 0.09733,-0.0339 0.187346,-0.0614 0.02378,-0.0261 0.02481,-0.0554 0.03436,-0.076 0.02875,-0.062 0.09717,-0.1904 0.336564,-0.33445 0.312033,-0.18776 0.872977,-0.3496 1.664461,-0.30102 h 2.41e-4 c 0.78943,0.0485 2.533815,0.30776 4.087014,0.56604 1.553342,0.25829 2.875385,0.47236 2.875385,0.47236 0.04495,0.006 0.143795,0.10749 0.08567,0.26878 -0.0058,0.0327 -0.06495,-0.002 -0.214412,-0.0993 -0.06614,-0.0229 -1.213381,-0.26531 -2.765708,-0.52344 -1.552327,-0.25813 -3.30239,-0.52923 -4.075718,-0.56439 -0.771201,-0.0351 -1.253838,0.11807 -1.525598,0.31868 -0.153775,0.11351 -0.228149,0.2138 -0.224063,0.25301 0.0041,0.0392 0.763976,0.84306 0.763976,0.84306 0,0 4.729649,0.87015 6.481561,1.60397 0.255147,0.10687 2.364992,3.0533 2.555296,4.88112 0.190027,1.82509 0.08874,3.0699 -0.662772,4.1435 -0.75152,1.07358 -3.006044,3.9722 -5.045868,5.26051 -2.03982,1.28832 -7.622632,22.653 -6.763757,24.37076 0.858876,1.71774 1.610367,0.1072 1.503004,1.1808 -0.107358,1.07358 -1.180964,5.15332 -1.39568,6.87108 -0.21472,1.71775 0.214756,6.01209 -0.107324,7.19305 -0.322074,1.18096 -1.39568,4.72366 -1.39568,4.72366 l 11.165447,0.53685 2.576478,-7.7299 c 0,0 2.68414,-7.40772 3.113569,-8.05188 0.429438,-0.64417 5.904818,-0.96623 8.374084,-2.14718 0.386184,-0.1847 2.247128,-2.12197 2.271453,-0.852 0.02145,1.12014 -0.80722,4.11567 -0.499567,4.18571 0.265174,0.0604 1.984492,-5.14965 2.216279,-4.73504 0.368307,0.65881 -0.329862,3.69047 0.01675,3.54411 0.292186,-0.12338 2.360611,-5.96434 2.758609,-6.6518 0.267772,-0.46251 1.352696,3.30086 1.803794,2.38725 0.297275,-0.60207 -0.01911,-6.23822 0.174166,-5.80208 0.343977,0.77626 0.716858,0.003 0.684425,-0.37704 -0.1192,-1.39704 0.503605,1.2942 0.632411,1.077 0.156555,-0.264 -0.06427,-2.07035 0.08261,-2.35477 0.09703,-0.18785 0.302823,0.0275 0.392109,-0.17652 0.07237,-0.16541 -0.230366,-2.42098 -0.160751,-2.57954 0.365525,-0.83251 1.0931,-1.05675 1.222458,-1.72942 0.276707,-1.43889 0.612145,-4.71323 -1.730598,-7.65294 -0.154852,-0.1943 -0.01998,-0.41678 -0.100969,-1.07512 -0.20216,-1.64276 -0.836217,-2.55634 -1.213983,-3.12299 -0.858876,-1.28831 -1.034214,-0.70998 -2.322527,-2.42773 -1.288308,-1.71774 -2.14702,-0.9661 -1.9323,-2.57648 0.03143,-0.23549 0.28671,-1.26106 0.146864,-2.26862 -0.06782,-0.48855 -0.633083,-1.13463 -0.588163,-1.37497 0.07731,-0.41364 0.992454,1.03201 0.945674,0.63288 -0.07976,-0.68054 -0.815421,-1.13673 -0.917901,-1.64563 -0.06656,-0.33058 0.88395,0.20012 0.657123,-0.0852 -0.664175,-0.83545 -1.153015,-1.72183 -1.39168,-2.40373 -0.751521,-2.14718 -3.361144,-6.81149 -6.259852,-7.67036 -2.898695,-0.85888 -3.921434,-0.55656 -6.548874,-0.4027 -0.509915,0.0299 -1.43137,0.31166 -1.666814,0.30455 -0.644036,-0.0194 -2.486166,-0.49098 -3.938503,-0.58981 -0.103926,-0.007 -0.216521,-0.0115 -0.336564,-0.0132 z"
sodipodi:nodetypes="ssccssssscccssszcsssssssscccssssssssscsssssscsscssssssscssss" />
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.421764;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="m 56.347762,114.81929 c 0.161825,0.10884 0.335437,0.26186 0.591376,0.25596 0.255976,-0.006 0.976809,-0.26479 0.967991,-0.59138 -0.009,-0.32658 -0.194171,-0.60901 -0.408951,-0.70612 -0.214776,-0.0971 -0.550714,-0.0673 -0.724035,-0.0349 -0.173348,0.0322 -0.455781,0.26752 -0.544051,0.39991 -0.08826,0.13237 -0.04418,0.56783 0.11767,0.67669 z"
id="path19231"
sodipodi:nodetypes="scssccs" />
<ellipse
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.260928;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0"
id="path871"
cx="-10.937903"
cy="127.09028"
rx="0.50466883"
ry="0.28456745"
transform="rotate(-31.358267)" />
<path
style="fill:none;stroke:none;stroke-width:0.14952px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 44.389921,115.02116 c 0,0 4.831171,0.75152 6.119483,2.1472 1.288312,1.39567 2.791337,2.57662 2.57662,4.40172 -0.214721,1.82511 0.429438,3.00606 -0.322074,4.07967 -0.751517,1.07358 -3.006063,3.97228 -5.045887,5.26059 -2.039829,1.28831 -7.622516,22.65282 -6.763641,24.37057 0.858874,1.71774 1.610396,0.10735 1.503033,1.18095 -0.107358,1.07358 -1.180954,5.15325 -1.395671,6.87099 -0.214721,1.71775 0.214717,6.01212 -0.107362,7.19307 -0.322075,1.18096 -1.395667,4.72381 -1.395667,4.72381 l 11.165366,0.5368 2.57662,-7.72987 c 0,0 2.683983,-7.40778 3.11342,-8.05194 0.429438,-0.64417 5.904767,-0.96624 8.374029,-2.14719 0.386179,-0.1847 2.247326,-2.12188 2.271656,-0.85191 0.02145,1.12014 -1.801065,5.44911 -1.437061,5.54899 0.375712,0.1031 2.349547,-4.82589 2.581334,-4.41129 0.368312,0.65882 -0.247513,3.75415 0.248173,3.39069 0.738355,-0.5414 2.701532,-7.49811 3.099534,-8.18557 0.267767,-0.46251 1.352722,3.30089 1.803821,2.38728 0.297271,-0.60206 -0.01908,-6.23809 0.174191,-5.80195 0.343972,0.77626 0.716747,0.003 0.684315,-0.3771 -0.1192,-1.39703 0.503735,1.29404 0.63254,1.07683 0.15656,-0.264 -0.06434,-2.07033 0.08254,-2.35476 0.09702,-0.18785 0.302732,0.0277 0.392023,-0.17632 0.07237,-0.16542 -0.230316,-2.42104 -0.160696,-2.5796 0.36552,-0.83251 1.093075,-1.05669 1.222427,-1.72935 0.276712,-1.43889 0.612072,-4.7133 -1.730671,-7.65301 -0.154852,-0.1943 0.363352,-0.6248 0.303944,-0.85138 -0.584768,-2.23024 -0.879494,-3.38266 -1.257256,-3.9493 -0.85887,-1.28831 -1.39567,-0.10736 -2.683983,-1.8251 -1.288308,-1.71775 -2.147187,-0.96625 -1.932466,-2.57663 0.03143,-0.2355 0.286691,-1.26102 0.14685,-2.26858 -0.06782,-0.48855 -0.632868,-1.1346 -0.587947,-1.37494 0.07731,-0.41364 0.992317,1.03207 0.945533,0.63294 -0.07975,-0.68054 -0.815425,-1.13672 -0.917906,-1.64562 -0.06656,-0.33058 0.88397,0.20005 0.657148,-0.0853 -0.664175,-0.83544 -1.153003,-1.72174 -1.391667,-2.40363 -0.751521,-2.14719 -3.361098,-6.8116 -6.259802,-7.67048 -2.898699,-0.85887 -3.921467,-0.55646 -6.548911,-0.4026 -1.735895,0.10165 -3.548997,-0.14554 -5.605391,-0.28547 -1.662818,-0.11314 -5.559983,0.47335 -6.204137,1.6543 -0.644159,1.18096 -0.156005,1.1706 -0.156005,1.1706 0,0 0.264793,-0.0941 0.322635,-0.0949 0.275738,-0.004 0.906961,0.85675 0.906961,0.85675 z"
id="path3379"
sodipodi:nodetypes="csssssssscccsssssssssssssssssssssssssssssscsc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 15 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 15 KiB

105
docs/assets/fast_icon.svg Normal file
View 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 (c4e8f9ed74, 2021-05-24)"
sodipodi:docname="fast_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="236.85572"
inkscape:cy="257.89448"
inkscape:window-width="1920"
inkscape:window-height="1007"
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:#122027;stroke-width:6.46499;stroke-linecap:round;stroke-opacity:1"
id="path7742"
cx="106.62331"
cy="153.48967"
r="70" />
<circle
style="fill:#343434;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:#343434;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:#122027;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:#122027;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:#122027;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:#122027;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:#122027;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:#122027;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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

View File

@ -1,19 +1,19 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="95mm"
height="95mm"
viewBox="0 0 95 95"
version="1.1"
id="svg8"
sodipodi:docname="crowbirdlight.svg"
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)">
sodipodi:docname="favicon.svg"
inkscape:version="1.1 (c4e8f9ed74, 2021-05-24)"
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"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs
id="defs2" />
<sodipodi:namedview
@ -21,11 +21,11 @@
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="0.98994949"
inkscape:cx="148.31628"
inkscape:cy="216.73575"
inkscape:zoom="1.979899"
inkscape:cx="148.74496"
inkscape:cy="185.86807"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
inkscape:document-rotation="0"
@ -34,7 +34,8 @@
inkscape:window-height="1007"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1" />
inkscape:window-maximized="1"
inkscape:pagecheckerboard="0" />
<metadata
id="metadata5">
<rdf:RDF>
@ -43,7 +44,6 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
@ -53,14 +53,50 @@
id="layer1"
transform="translate(-52.906909,-78.735456)">
<path
style="fill:#ffffff;stroke-width:0.0846667;fill-opacity:1"
d="m 71.571997,171.19568 c -3.572219,-2.5391 -6.958416,-4.99717 -7.297368,-5.29725 l -0.255219,-0.22595 0.463991,-1.397 c 0.255194,-0.76835 1.834897,-5.5499 3.510451,-10.62566 3.505253,-10.61849 6.335239,-19.079 8.227096,-24.59567 1.239876,-3.61549 1.312204,-3.86077 1.176445,-3.98957 -0.07956,-0.0755 -2.002027,-1.49736 -4.272152,-3.15973 -2.270126,-1.66237 -4.127501,-3.03677 -4.127501,-3.05422 0,-0.0174 0.447675,-0.17021 0.994834,-0.33945 4.886112,-1.51137 7.962219,-2.73416 9.445623,-3.75477 0.362819,-0.24963 0.387836,-0.2923 0.440626,-0.75162 0.254599,-2.21523 1.509656,-5.3475 3.28228,-8.19164 0.769332,-1.23437 1.327539,-1.89818 2.310037,-2.74704 1.807481,-1.56165 2.634149,-2.51067 2.87318,-3.298457 l 0.06174,-0.20349 -2.402627,0.0407 c -0.884406,-0.0983 -3.436624,1.252417 -4.036603,1.362387 -0.186563,0.0342 0.182778,-0.48865 0.827027,-0.8947 0.608067,-0.383237 2.967885,-1.868996 2.967885,-1.997926 0,-0.15087 -1.203166,0.2373 -2.304491,0.84657 -1.380268,0.763599 -2.708103,1.732686 -3.500379,2.442516 -0.395318,0.35418 -0.527363,0.47539 -0.576329,0.38396 -0.06369,-0.11892 1.312215,-2.814056 2.077584,-4.104836 0.984944,-1.661076 1.899268,-2.849086 2.965763,-3.853476 0.843653,-0.79454 1.169069,-1.00799 2.819519,-1.84946 0.6985,-0.35612 1.337903,-0.70012 1.420901,-0.76444 0.08299,-0.0643 0.438345,-0.85281 0.789669,-1.7522 0.762127,-1.95101 1.125034,-2.52632 2.402087,-3.80797 1.702596,-1.70871 3.541031,-2.68504 7.45234,-3.95765 2.632654,-0.85657 3.351464,-1.00385 5.868544,-1.20244 1.91219,-0.15087 2.39954,-0.16398 3.09033,-0.0831 3.13159,0.36649 5.80893,1.54633 9.04058,3.98397 0.85831,0.64742 1.46873,1.21026 2.54753,2.34895 0.78031,0.82364 1.59139,1.60837 1.80239,1.74385 0.48283,0.31002 1.36664,0.63352 2.66964,0.97715 2.19445,0.57872 3.18724,0.98741 4.488,1.84752 3.01295,1.99228 4.94472,5.175526 5.50942,9.078652 0.16952,1.17171 0.12699,3.48039 -0.0873,4.74136 -0.6988,4.11128 -2.69437,8.25567 -5.88294,12.21763 -2.65138,3.29447 -6.19099,6.58361 -9.38246,8.71852 -0.38426,0.25705 -1.69459,0.97024 -2.91184,1.58486 -2.34712,1.18513 -3.18189,1.65693 -3.57412,2.02002 -0.32252,0.29857 -4.7335,1.93493 -5.57734,3.13278 -1.4867,2.11039 -2.81695,9.84328 -3.87325,13.56096 l -0.86395,3.04071 1.60672,2.35209 c 0.88369,1.29365 3.39835,4.98099 5.58814,8.19409 5.88176,8.63041 5.30521,7.83167 5.65314,7.83167 0.16249,0 1.33262,-0.0797 2.60029,-0.17705 3.58462,-0.27535 5.36791,-0.16751 6.66165,0.4029 0.53171,0.23444 1.31143,0.79856 1.44267,1.04376 0.0828,0.15478 0.0726,0.16086 -0.13666,0.0813 -0.1244,-0.0473 -0.35049,-0.21254 -0.53149,-0.32585 -0.60447,-0.37843 -0.80593,-0.43812 -2.50665,-0.55585 -1.41918,0.003 -3.18867,0.13023 -3.62073,0.26008 -0.35615,0.10703 0.0151,0.17949 1.19163,0.23259 1.82677,0.0824 3.32001,0.3425 4.45473,0.77585 0.34294,0.13097 0.37119,0.21293 0.56494,0.52514 0.24967,0.40148 0.44912,0.77 0.6691,1.1632 0,0.0755 -0.31013,-0.0966 -0.93952,-0.52131 -0.50651,-0.34182 -0.66835,-0.3991 -1.73854,-0.61535 -4.11561,-0.83164 -9.67012,-0.84815 -12.8894,-0.0383 -0.60141,0.1513 -0.83385,0.17774 -0.96159,0.10937 -0.23979,-0.12833 -0.12667,-0.19934 0.78105,-0.49027 0.97335,-0.31197 2.06406,-0.85524 2.10087,-1.04641 0.0148,-0.0767 -0.88293,-1.46501 -1.99488,-3.08513 -1.11197,-1.62011 -2.98963,-4.35536 -4.17261,-6.07833 -1.18298,-1.72297 -3.10541,-4.52332 -4.27208,-6.223 l -2.121217,-3.09033 -0.561707,-0.0557 c -0.672863,-0.0668 -0.65693,-0.61032 -1.066759,-1.02015 -0.393624,-0.39363 -0.327565,-0.76458 -0.321727,-1.56889 0.0042,-0.58339 0.04272,-0.93417 0.237368,-2.88281 0.343284,-3.43671 0.648721,-11.14728 0.594721,-11.20128 -0.0118,-0.0119 -2.390554,0.778 -2.736553,0.88937 -4.142858,1.33368 -6.369262,1.9958 -6.719782,1.99843 -0.142629,0.001 -0.754625,0.0789 -1.359992,0.173 -0.605367,0.0941 -2.23724,0.3376 -3.626375,0.54116 -1.389143,0.20355 -2.545901,0.39029 -2.570573,0.41496 -0.02467,0.0247 -0.360833,1.771 -0.747034,3.88073 -0.386197,2.10973 -0.955554,5.16937 -1.26524,6.79921 -0.976296,5.13812 -2.064443,10.8145 -2.669894,13.92766 -0.548282,2.8192 -1.290101,6.64221 -1.872882,9.652 -0.288412,1.48953 -0.318055,1.60918 -0.398208,1.60737 -0.03179,-8.5e-4 -1.356829,-0.92465 -2.944538,-2.05317 z"
id="path26"
sodipodi:nodetypes="cscsssssscsssssccsssssssssssssscsssssscsssssscssscsssscscsccsssssssssccssscccsssssssccc" />
style="color:#000000;fill:#ffffff;stroke-width:0.633931;-inkscape-stroke:none;fill-opacity:1"
d="m 131.60351,157.53369 c -1.44225,0.088 -3.05509,0.225 -4.79271,0.38845 -14.0779,1.32417 -36.347368,4.38223 -42.468437,-2.85614 -6.876591,-8.13179 -5.676856,-14.32107 -3.540856,-27.51438 2.136,-13.19332 11.147817,-30.61464 22.217343,-31.845476 11.06952,-1.230833 23.00902,-0.134959 26.88493,1.149142 l 3.64693,-13.70856 c -13.8201,-3.333369 -20.25092,-4.6647 -37.975455,-2.227752 -17.724509,2.436948 -26.546029,23.899856 -28.926801,43.680146 -2.380764,19.78024 -0.597414,35.6157 5.403308,41.81224 6.000721,6.19654 41.625298,8.3939 61.081568,4.77669 z"
id="path830"
sodipodi:nodetypes="csszzcczzzcc" />
<path
style="fill:#ffffff;fill-opacity:1;stroke-width:0.0846667"
d="m 103.24635,166.01478 c -4.1e-4,-0.0172 0.42481,-0.16375 0.94495,-0.32557 0.52013,-0.16182 0.99458,-0.31099 1.05432,-0.33149 0.0849,-0.0292 0.0862,-0.0768 0.006,-0.21787 -0.20866,-0.36832 -10.950188,-15.72058 -11.242607,-16.06842 -0.05962,-0.0709 -0.295982,-0.2506 -0.52525,-0.39928 -0.895092,-0.58043 -0.863337,-1.85618 -0.80318,-3.21042 0.02658,-0.59894 0.771215,-5.06795 1.491861,-9.39694 l 0.297644,-1.78798 c 0,0 -0.607552,-0.94689 3.600609,-2.41413 0.343222,-0.11967 0.633892,-0.20822 0.645912,-0.19675 0.012,0.0114 0.616817,1.86077 0.21254,4.03222 l -0.706969,3.79731 c 0,0 0,0 -0.417463,1.55135 -0.663151,2.46437 -0.798564,3.08375 -1.610943,5.38562 -0.439112,1.24422 -0.6823,2.26031 -0.70158,2.3144 -0.01927,0.0541 0.198595,0.47031 0.484162,0.92491 0.285576,0.4546 2.107625,3.3418 4.049014,6.41599 4.99398,7.90797 5.77721,9.08693 5.98879,9.01462 0.0719,-0.0245 0.36278,-0.14845 0.64644,-0.27532 0.58431,-0.2613 2.24506,-0.77345 3.30998,-1.02073 l 0.71353,-0.16568 0.42505,0.25623 0.42502,0.25623 -0.77419,0.0186 c -0.86578,0.0208 -1.566,0.15966 -1.70733,0.33853 -0.0785,0.0994 0.0348,0.1144 0.69539,0.0922 0.43405,-0.0144 1.19084,-0.0306 1.68176,-0.0354 l 0.89256,-0.009 0.33,0.29661 c 0.12162,0.10931 0.19804,0.18983 0.23555,0.25196 0.0376,0.0621 0.0362,0.10584 0.002,0.14154 -0.034,0.0357 -0.0753,0.053 -0.13356,0.0519 -0.0583,-0.002 -0.13345,-0.0211 -0.23537,-0.0598 -0.91405,-0.34638 -2.21414,-0.39029 -3.79182,-0.12849 -0.90397,0.15025 -2.41249,0.49222 -2.5411,0.57605 -0.0392,0.0255 -0.66947,0.11443 -1.40058,0.19738 -1.49048,0.16924 -1.54048,0.17343 -1.54153,0.1296 z"
id="path28"
sodipodi:nodetypes="sssssssscscscsssssssscccsscccsssscsscss" />
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.142752px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 110.20292,152.92929 -1.25562,1.07624 c 0,0 1.30687,1.23 1.76812,1.76812 0.46125,0.53812 2.89562,4.68937 3.10062,5.40686 0.205,0.7175 1.07625,0.87126 1.7425,1.61437 0.66625,0.74313 1.99874,1.51187 1.025,2.28062 -0.97375,0.76876 0.9225,0.33314 0.87124,-0.87124 -0.0512,-1.20438 1.79375,2.28063 0.48688,2.74187 -1.30687,0.46125 0.66624,0.48687 0.92249,0.0512 0.25625,-0.43562 0.38438,-1.22999 0.28188,-2.10124 -0.1025,-0.87126 -1.435,-2.48563 -1.7425,-2.76749 -0.3075,-0.28189 1.46062,-0.17938 1.94749,0.46124 0.48689,0.64062 0.53813,0.84562 0.17938,1.38374 -0.35875,0.53814 1.40937,-0.43562 0.56376,-1.30687 -0.84563,-0.87124 -0.20501,-0.79437 -1.38376,-1.35811 -1.17875,-0.56376 -1.30687,-0.92251 -2.30624,-0.87125 -0.99937,0.0513 -6.20124,-7.50811 -6.20124,-7.50811 z"
id="path15574" />
<path
style="fill:#fefefe;fill-opacity:1;stroke:none;stroke-width:0.142752px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 118.4029,150.05928 -1.48624,0.9225 3.40812,3.81813 c 0,0 1.76812,1.28124 1.40937,2.61373 -0.35875,1.3325 -1.28125,1.81938 -1.28125,1.81938 0,0 0.12812,0.23062 0.53812,0.23062 0.41,0 0.9225,-1.33249 1.66563,-0.92249 0.74312,0.41 1.79374,1.43498 1.97312,2.07561 0.17937,0.64063 0.0513,0.79438 0.15375,0.9225 0.1025,0.12813 0.64062,0.12813 0.56374,-0.41 -0.0769,-0.53812 0.35875,-0.0256 0.46126,0.43562 0.1025,0.46125 0.43562,1.28125 0.38436,2.07562 -0.0512,0.79437 0.46126,1.56313 0.43564,0.41 -0.0256,-1.15311 0.23062,-2.40873 -0.35875,-3.45936 -0.58937,-1.05063 -0.84563,-2.45999 0.0769,-1.5375 0.9225,0.92249 1.64,1.02501 1.89625,1.69124 0.25625,0.66626 0.23062,0.82 0.53812,0.82 0.3075,0 0.12812,-0.92249 -0.43562,-1.56313 -0.56375,-0.64061 -0.58938,-1.28124 -2.20375,-2.10123 -1.61437,-0.82 -2.48562,-1.64 -4.20249,-3.20312 -1.71688,-1.56312 -3.53625,-4.63812 -3.53625,-4.63812 z"
id="path15576" />
<path
style="fill:#010101;fill-opacity:1;stroke:none;stroke-width:0.142752px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 112.82046,159.21405 c 0.5033,0.8974 0.91627,1.68889 0.99558,1.96646 0.205,0.7175 1.07625,0.87126 1.7425,1.61437 0.66625,0.74313 1.99874,1.51187 1.025,2.28062 -0.97375,0.76876 0.9225,0.33314 0.87124,-0.87124 -0.0512,-1.20438 1.79375,2.28063 0.48688,2.74187 -1.30687,0.46125 0.66624,0.48687 0.92249,0.0512 0.25625,-0.43562 0.38438,-1.22999 0.28188,-2.10124 -0.1025,-0.87126 -1.435,-2.48563 -1.7425,-2.76749 -0.3075,-0.28189 1.46062,-0.17938 1.94749,0.46124 0.48689,0.64062 0.53813,0.84562 0.17938,1.38374 -0.35875,0.53814 1.40937,-0.43562 0.56376,-1.30687 -0.84563,-0.87124 -0.20501,-0.79437 -1.38376,-1.35811 -1.17875,-0.56376 -1.30687,-0.92251 -2.30624,-0.87125 -0.27545,0.0142 -0.87016,-0.54991 -1.58721,-1.37448 z"
id="path16765"
sodipodi:nodetypes="cssssssssssssscc" />
<path
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.142752px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 122.03733,158.3908 c 0.18411,3.7e-4 0.27569,0.0141 0.45904,0.0746 0.53507,0.17652 1.99911,1.67175 2.1334,2.15136 0.17937,0.64063 0.0513,0.79438 0.15375,0.92249 0.1025,0.12814 0.64062,0.12814 0.56374,-0.40999 -0.0769,-0.53812 0.35875,-0.0256 0.46126,0.43562 0.1025,0.46124 0.43562,1.28124 0.38436,2.07562 -0.0512,0.79437 0.29723,1.53789 0.43564,0.41 0.14048,-1.14481 0.23062,-2.40873 -0.35875,-3.45936 -0.58937,-1.05063 -0.84563,-2.46 0.0769,-1.5375 0.9225,0.92249 1.64,1.025 1.89625,1.69124 0.25625,0.66626 0.23062,0.82 0.53812,0.82 0.3075,0 0.12812,-0.9225 -0.43562,-1.56313 -0.56375,-0.64061 -0.44847,-1.2099 -2.06284,-2.02989 z"
id="path16767"
sodipodi:nodetypes="csssssssssssscc" />
<path
id="path7288"
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.141638px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 106.80565,107.42503 c -1.70572,-0.0232 -4.98637,0.53061 -5.55843,1.57939 -0.6102,1.1187 -0.14759,1.10896 -0.14759,1.10896 0,0 0.0922,-0.0321 0.17747,-0.0582 0.0225,-0.0247 0.0235,-0.0525 0.0326,-0.072 0.0272,-0.0588 0.0921,-0.18036 0.31882,-0.31681 0.29558,-0.17787 0.82696,-0.33118 1.57672,-0.28516 h 2.3e-4 c 0.74781,0.046 2.40024,0.29154 3.87156,0.5362 1.47146,0.24468 2.72381,0.44746 2.72381,0.44746 0.0426,0.005 0.13622,0.10183 0.0812,0.25462 -0.006,0.031 -0.0615,-0.001 -0.20311,-0.0941 -0.0626,-0.0217 -1.14942,-0.25133 -2.61991,-0.49585 -1.4705,-0.24452 -3.12831,-0.50133 -3.86087,-0.53463 -0.73055,-0.0332 -1.18774,0.11185 -1.44518,0.30187 -0.14567,0.10753 -0.21612,0.20254 -0.21225,0.23968 0.004,0.0371 0.7237,0.79861 0.7237,0.79861 0,0 4.48033,0.82429 6.13989,1.51942 0.2417,0.10124 2.24032,2.89235 2.42059,4.62381 0.18001,1.72889 0.0841,2.90807 -0.62783,3.92508 -0.71191,1.01699 -2.84758,3.7628 -4.77988,4.9832 -1.93229,1.22041 -7.220799,21.45885 -6.4072,23.08605 0.8136,1.62719 1.52548,0.10155 1.42377,1.11855 -0.1017,1.01699 -1.118707,4.88167 -1.322104,6.50887 -0.203401,1.6272 0.203435,5.69517 -0.101666,6.81387 -0.305096,1.1187 -1.322107,4.47465 -1.322107,4.47465 l 10.576857,0.50856 2.44066,-7.32243 c 0,0 2.54264,-7.01721 2.94944,-7.62742 0.4068,-0.61021 5.59354,-0.91529 7.93264,-2.03399 0.36583,-0.17496 2.12867,-2.01011 2.15171,-0.80709 0.0203,1.0611 -0.76466,3.89871 -0.47323,3.96507 0.2512,0.0572 1.87988,-4.87819 2.09945,-4.48544 0.34889,0.62408 -0.31248,3.49592 0.0159,3.35728 0.27679,-0.11687 2.23617,-5.64993 2.61319,-6.30114 0.25366,-0.43813 1.28139,3.12685 1.70871,2.2614 0.2816,-0.57033 -0.0181,-5.90937 0.16498,-5.49622 0.32585,0.73534 0.67907,0.003 0.64835,-0.35717 -0.11292,-1.32339 0.47706,1.22598 0.59907,1.02023 0.1483,-0.25009 -0.0609,-1.96121 0.0783,-2.23064 0.0919,-0.17795 0.28686,0.0261 0.37144,-0.16721 0.0686,-0.1567 -0.21823,-2.29336 -0.15228,-2.44356 0.34625,-0.78862 1.03548,-1.00105 1.15801,-1.63825 0.26212,-1.36304 0.57988,-4.46478 -1.63936,-7.24952 -0.14669,-0.18406 -0.0189,-0.39481 -0.0956,-1.01845 -0.1915,-1.55615 -0.79214,-2.42158 -1.14999,-2.95835 -0.8136,-1.2204 -0.97969,-0.67256 -2.20009,-2.29975 -1.2204,-1.6272 -2.03384,-0.91518 -1.83044,-2.44066 0.0298,-0.22309 0.27159,-1.19459 0.13912,-2.14904 -0.0642,-0.46279 -0.59971,-1.07482 -0.55716,-1.30249 0.0732,-0.39183 0.94014,0.97761 0.89582,0.59952 -0.0756,-0.64466 -0.77243,-1.07681 -0.86951,-1.55888 -0.0631,-0.31315 0.83735,0.18957 0.62248,-0.0807 -0.62916,-0.7914 -1.09223,-1.63106 -1.31831,-2.27701 -0.71191,-2.034 -3.18396,-6.45242 -5.92987,-7.26602 -2.74589,-0.8136 -3.71471,-0.52722 -6.20364,-0.38147 -0.48304,0.0283 -1.35592,0.29523 -1.57895,0.2885 -0.61009,-0.0184 -2.35511,-0.4651 -3.73089,-0.55872 -0.0984,-0.007 -0.2051,-0.0109 -0.31882,-0.0125 z"
sodipodi:nodetypes="ssccssssscccssszcsssssssscccssssssssscsssssscsscssssssscssss" />
<path
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.399531;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="m 113.59181,110.64385 c 0.15329,0.1031 0.31775,0.24805 0.5602,0.24247 0.24248,-0.005 0.92532,-0.25083 0.91696,-0.56021 -0.009,-0.30937 -0.18393,-0.57691 -0.38739,-0.6689 -0.20345,-0.092 -0.52168,-0.0638 -0.68587,-0.0331 -0.16421,0.0305 -0.43175,0.25342 -0.51537,0.37884 -0.0836,0.12539 -0.0418,0.53789 0.11147,0.64101 z"
id="path19231"
sodipodi:nodetypes="scssccs" />
<ellipse
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.247173;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0"
id="path871"
cx="40.080688"
cy="153.32861"
rx="0.47806513"
ry="0.26956642"
transform="rotate(-31.358267)" />
<path
style="fill:none;stroke:none;stroke-width:0.141638px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 102.26433,110.83508 c 0,0 4.57649,0.7119 5.79689,2.03401 1.2204,1.3221 2.64419,2.44079 2.44079,4.16968 -0.2034,1.7289 0.4068,2.8476 -0.30509,3.86461 -0.7119,1.01698 -2.8476,3.76288 -4.77989,4.98328 -1.9323,1.2204 -7.220698,21.45867 -6.407099,23.08587 0.813599,1.62719 1.525499,0.10169 1.423799,1.1187 -0.1017,1.01699 -1.118698,4.88159 -1.322096,6.50878 -0.203402,1.6272 0.203398,5.69519 -0.101703,6.81389 -0.305097,1.1187 -1.322093,4.47479 -1.322093,4.47479 l 10.576782,0.5085 2.44079,-7.32239 c 0,0 2.5425,-7.01728 2.9493,-7.62748 0.4068,-0.61021 5.59349,-0.9153 7.93259,-2.034 0.36582,-0.17496 2.12886,-2.01002 2.1519,-0.807 0.0203,1.06109 -1.70612,5.16186 -1.3613,5.25648 0.3559,0.0977 2.22569,-4.57149 2.44526,-4.17875 0.34889,0.62408 -0.23447,3.55624 0.23509,3.21194 0.69943,-0.51286 2.55912,-7.10284 2.93614,-7.75406 0.25365,-0.43813 1.28141,3.12689 1.70873,2.26144 0.2816,-0.57033 -0.0181,-5.90925 0.16501,-5.49611 0.32584,0.73534 0.67896,0.003 0.64824,-0.35721 -0.11292,-1.32339 0.47718,1.22581 0.5992,1.02006 0.1483,-0.25009 -0.0609,-1.9612 0.0782,-2.23063 0.0919,-0.17795 0.28677,0.0263 0.37136,-0.16703 0.0686,-0.15669 -0.21818,-2.29341 -0.15223,-2.44361 0.34625,-0.78862 1.03546,-1.00099 1.15799,-1.63819 0.26212,-1.36304 0.57981,-4.46484 -1.63944,-7.24958 -0.14669,-0.18406 0.3442,-0.59186 0.28792,-0.8065 -0.55394,-2.11267 -0.83313,-3.20434 -1.19098,-3.74111 -0.81359,-1.2204 -1.3221,-0.1017 -2.54249,-1.72889 -1.2204,-1.6272 -2.034,-0.91531 -1.8306,-2.4408 0.0298,-0.22308 0.27158,-1.19455 0.13911,-2.14899 -0.0642,-0.4628 -0.59951,-1.0748 -0.55695,-1.30247 0.0732,-0.39183 0.94,0.97767 0.89568,0.59958 -0.0755,-0.64466 -0.77244,-1.07679 -0.86951,-1.55887 -0.0631,-0.31315 0.83737,0.1895 0.6225,-0.0808 -0.62916,-0.79141 -1.09222,-1.63098 -1.3183,-2.27693 -0.71191,-2.034 -3.18392,-6.45253 -5.92982,-7.26612 -2.74589,-0.8136 -3.71474,-0.52713 -6.20368,-0.38138 -1.64439,0.0963 -3.36191,-0.13787 -5.3099,-0.27042 -1.57517,-0.10718 -5.26689,0.44839 -5.87709,1.56709 -0.6102,1.1187 -0.14778,1.10889 -0.14778,1.10889 0,0 0.25083,-0.0891 0.30563,-0.0899 0.2612,-0.004 0.85915,0.81159 0.85915,0.81159 z"
id="path3379"
sodipodi:nodetypes="csssssssscccsssssssssssssssssssssssssssssscsc" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 7.6 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View 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 (c4e8f9ed74, 2021-05-24)"
sodipodi:docname="header_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="-10.180046"
inkscape:cy="249.75045"
inkscape:window-width="1920"
inkscape:window-height="1007"
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:#122027;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

BIN
docs/assets/og_img.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View 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 (c4e8f9ed74, 2021-05-24)"
sodipodi:docname="typesafe_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="-37.911464"
inkscape:cy="204.43397"
inkscape:window-width="1920"
inkscape:window-height="1007"
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:#122027;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

View 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 (c4e8f9ed74, 2021-05-24)"
sodipodi:docname="websocket_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="158.13004"
inkscape:cy="343.40687"
inkscape:window-width="1920"
inkscape:window-height="1007"
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:#122027;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

View File

@ -3,21 +3,36 @@ This page explains how to set Crow up for use with your project.
##Requirements
- C++ compiler with C++14 support.
- Continuous Testing on g++-9.3 and clang-7.0, AMD64 (x86_64) and Arm64 v8
- Crow's CI uses g++-9.3 and clang-7.0 running on AMD64 (x86_64) and ARM64v8
- boost library (1.70 or later).
- (optional) CMake and Python3 to build tests and/or examples.
- (optional) Linking with jemalloc/tcmalloc is recommended for speed.
- **(optional)** ZLib for HTTP Compression.
- **(optional)** CMake and Python3 to build tests and/or examples.
- **(optional)** Linking with jemalloc/tcmalloc is recommended for speed.
!!!note
While using Boost 1.70 or later is recommended, it may be possible to compile a Crow application with version 1.64
<br><br>
##Installing Requirements
!!! note
The Linux requirements are for developing and compiling a Crow application. Running a built application requires the actual libraries rather than just the development headers.
###Ubuntu
`sudo apt-get install libboost-all-dev`
`sudo apt-get install build-essential libboost-all-dev`
###Non Debian based GNU/Linux
Use your package manager to install the following:
- GCC and G++ (or Clang and Clang++)
- Boost Development headers (sometimes part of the Boost package itself)
###OSX
`brew install boost`
###Windows
Download boost from [here](https://www.boost.org/) and install it
Microsoft Visual Studio 2019 (older versions not tested)
##Downloading
Either run `git clone https://github.com/crowcpp/crow.git` or download `crow_all.h` from the releases section. You can also download a zip of the project on github.
@ -29,7 +44,7 @@ Either run `git clone https://github.com/crowcpp/crow.git` or download `crow_all
<br><br>
##Single header file
If you've downloaded `crow_all.h`, you can skip to step 4.
If you've downloaded `crow_all.h`, you can skip to step **4**.
1. Make sure you have python 3 installed.
2. Open a terminal (or `cmd.exe`) instance in `/path/to/crow/scripts`.
@ -44,17 +59,30 @@ If you've downloaded `crow_all.h`, you can skip to step 4.
To build a crow Project, do the following:
###GCC (G++)
- Release: `g++ main.cpp -lpthread -lboost_system -lz`.
- Debug: `g++ main.cpp -ggdb -lpthread -lboost_system -lz -D CROW_ENABLE_DEBUG`.
- SSL: `g++ main.cpp -lssl -lcrypto -lpthread -lboost_system -lz -D CROW_ENABLE_SSL`.
- Release: `g++ main.cpp -lpthread -lboost_system`.
- Debug: `g++ main.cpp -ggdb -lpthread -lboost_system -DCROW_ENABLE_DEBUG`.
- SSL: `g++ main.cpp -lssl -lcrypto -lpthread -lboost_system -DCROW_ENABLE_SSL`.
###Clang
- Release: `clang++ main.cpp -lpthread -lboost_system -lz`.
- Debug: `clang++ main.cpp -g -lpthread -lboost_system -lz -DCROW_ENABLE_DEBUG`.
- SSL: `clang++ main.cpp -lssl -lcrypto -lpthread -lboost_system -lz -DCROW_ENABLE_SSL`.
- Release: `clang++ main.cpp -lpthread -lboost_system`.
- Debug: `clang++ main.cpp -g -lpthread -lboost_system -DCROW_ENABLE_DEBUG`.
- SSL: `clang++ main.cpp -lssl -lcrypto -lpthread -lboost_system -DCROW_ENABLE_SSL`.
###Microsoft Visual Studio
***Help needed***
###Microsoft Visual Studio 2019
The following guide will use `example_with_all.cpp` as the Crow application for demonstration purposes.
1. Generate `crow_all.h` following [Single header file](#single-header-file).
2. `git clone https://github.com/microsoft/vcpkg.git`
3. `.\vcpkg\bootstrap-vcpkg.bat`
4. `.\vcpkg\vcpkg integrate install`
5. Create empty Visual Studio project.
6. In solution explorer, right click the name of your project then click `Open Folder in File Explorer`.
7. Copy `crow_all.h`, `example_with_all.cpp`, `vcpkg.json` to opened folder.
8. Add `crow_all.h` to `Header Files` and `example_with_all.cpp` to `Source Files`.
9. In solution explorer, right click the name of your project then click `Properties`.
10. Under `vcpkg`, set `Use Vcpkg Manifest` to `Yes` and `Additional Options` to `--feature-flags="versions"`.
11. Set `Debug/Release` and `x64/x86`.
12. Run.
##building via CMake
@ -86,7 +114,9 @@ set(PROJECT_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include)
include_directories("${PROJECT_INCLUDE_DIR}")
```
**Note**: The last 2 lines are unnecessary if you're using `crow_all.h`.
!!!note
The last 2 lines are unnecessary if you're using `crow_all.h`.
##Building Crow tests and examples
Out-of-source build with CMake is recommended.

View File

@ -1,11 +1,11 @@
This page shows how you can get started with a simple hello world application.
##1. Include
Starting with an empty `main.cpp` file, add `#!cpp #CROW_MAIN` then `#!cpp #include "crow.h"` or `#!cpp #include "crow_all.h"` if you're using the single header file.
Starting with an empty `main.cpp` file, first add `#!cpp #define CROW_MAIN` then `#!cpp #include "crow.h"` or `#!cpp #include "crow_all.h"` if you're using the single header file.
!!! note
If you're using multiple C++ source files make sure to have `#CROW_MAIN` defined only in your main source file.
If you're using multiple C++ source files make sure to have `CROW_MAIN` defined only in your main source file.
##2. App declaration
Next Create a `main()` and declare a `#!cpp crow::SimpleApp` inside, your code should look like this
@ -39,6 +39,7 @@ Please note that the `port()` and `multithreaded()` methods aren't needed, Thoug
Once you've followed all the steps above, your code should look similar to this
``` cpp linenums="1"
#define CROW_MAIN //let the compiler know this is your main cpp file
#include "crow.h"
//#include "crow_all.h"

43
docs/guides/blueprints.md Normal file
View File

@ -0,0 +1,43 @@
!!!Warning
This feature is currently only available on the "master" branch.
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>
In order for a blueprint to work, it has to be registered with a Crow app before the app is run. This can be done using `#!cpp app.register_blueprint(blueprint);`.<br><br>
Blueprints let you do the following:<br><br>
### Define Routes
You can define routes in a blueprint, similarly to how `#!cpp CROW_ROUTE(app, "/xyz")` works, you can use `#!cpp CROW_BP_ROUTE(blueprint, "/xyz")` to define a blueprint route.
### Define a Prefix
Blueprints can have a prefix assigned to them. This can be done when creating a new blueprint as in `#!cpp crow::blueprint bp("prefix");`. This prefix will be applied to all routes belonging to the blueprint. truning a route such as `/crow/rocks` into `/prefix/crow/rocks`.
!!!Warning
Unlike routes, blueprint prefixes should contain no slashes.
### Use a custom Static directory
Blueprints let you define a custom static directory (relative to your working directory). This can be done by initializing a blueprint as `#!cpp crow::blueprint bp("prefix", "custom_static");`. This does not have an effect on `#!cpp set_static_file_info()`, it's only for when you want direct access to a file.
!!!note
Currently changing which endpoint the blueprint uses isn't possible, so whatever you've set in `CROW_STATIC_ENDPOINT` (default is "static") will be used. Making your final route `/prefix/static/filename`.
### Use a custom Templates directory
Similar to static directories, You can set a custom templates directory (relative to your working directory). To do this you initialize the blueprint as `#!cpp crow::blueprint bp("prefix", "custom_static", "custom_templates");`. Any routes defined for the blueprint will use that directory when calling `#!cpp crow::mustache::load("filename.html")`.
!!!note
If you want to define a custom templates directory without defining a custom static directory, you can pass the static directory as an empty string. Making your constructor `#!cpp crow::blueprint bp("prefix", "", "custom_templates");`.
### Define a custom Catchall route
You can define a custom catchall route for a blueprint by calling `#!cpp CROW_BP_CATCHALL_ROUTE(blueprint)`. This causes any requests with a URL starting with `/prefix` and no route found to call the blueprint's catchall route. if no catchall route is defined, Crow will default to either the parent blueprint or the app's catchall route.
### Register other Blueprints
Blueprints can also register other blueprints. This is done through `#!cpp blueprint.register_blueprint(blueprint_2);`. The child blueprint's routes become `/prefix/prefix_2/abc/xyz`.

View File

@ -0,0 +1,19 @@
**Introduced in: `v0.3`**<br><br>
Crow supports Zlib compression using Gzip or Deflate algorithms.
## HTTP Compression
HTTP compression is by default disabled in crow. Do the following to enable it: <br>
1. Add `#!cpp #define CROW_ENABLE_COMPRESSION` to the top of your main source file.
2. Call `#!cpp use_compression(crow::compression::algorithm)` on your crow app.
3. When compiling your application, make sure that ZLIB is included as a dependency. Either through `-lz` argument or `find_package(ZLIB)` in CMake.
!!! note
step 3 is not needed for MSVC since `vcpckg.json` already includes zlib as a dependency by default
For the compression algorim you can use `crow::compression::algorithm::DEFLATE` or `crow::compression::algorithm::GZIP`.<br>
And now your HTTP responses will be compressed.
## Websocket Compression
Crow currently does not support Websocket compression.<br>
Feel free to discuss the subject with us on Github if you're feeling adventurous and want to try to implement it. We appreciate all the help.

View File

@ -1,5 +1,19 @@
Crow has built in support for JSON data.<br><br>
##type
The types of values that `rvalue and wvalue` can take are as follows:<br>
- `False`: from type `bool`.
- `True`: from type `bool`.
- `Number`
- `Floating_point`: from type `double`.
- `Signed_integer`: from type `int`.
- `Unsigned_integer`: from type `unsigned int`.
- `String`: from type `std::string`.
- `List`: from type `std::vector`.
- `Object`: from type `crow::json::wvalue or crow::json::rvalue`.<br>
This last type means that `rvalue or wvalue` can have keys.
##rvalue
JSON read value, used for taking a JSON string and parsing it into `crow::json`.<br><br>
@ -11,19 +25,18 @@ For more info on read values go [here](/reference/classcrow_1_1json_1_1rvalue.ht
#wvalue
JSON write value, used for creating, editing and converting JSON to a string.<br><br>
The types of values that `wvalue` can take are as follows:<br>
!!!note
- `False`: from type `bool`.
- `True`: from type `bool`.
- `Number`
- `Floating_point`: from type `double`.
- `Signed_integer`: from type `int`.
- `Unsigned_integer`: from type `unsigned int`.
- `String`: from type `std::string`.
- `List`: from type `std::vector`.
- `Object`: from type `crow::json::wvalue`.<br>
This last type means that `wvalue` can have keys, this is done by simply assigning a value to whatever string key you like, something like `#!cpp wval["key1"] = val1;`. Keep in mind that val1 can be any of the above types.<br><br>
setting a `wvalue` to object type can be done by simply assigning a value to whatever string key you like, something like `#!cpp wval["key1"] = val1;`. Keep in mind that val1 can be any of the above types.
A JSON wvalue can be returned directly inside a route handler, this will cause the `content-type` header to automatically be set to `Application/json` and the JSON value will be converted to string and placed in the response body. For more information go to [Routes](../routes).<br><br>
A `wvalue` can be treated as an object or even a list (setting a value by using `json[3] = 32` for example). Please note that this will remove the data in the value if it isn't of List type.<br><br>
An object type `wvalue` uses `std::unordered_map` by default, if you want to have your returned `wvalue` key value pairs be sorted (using `std::map`) you can add `#!cpp #define CROW_JSON_USE_MAP` to the top of your program.<br><br>
A JSON `wvalue` can be returned directly inside a route handler, this will cause the `content-type` header to automatically be set to `Application/json` and the JSON value will be converted to string and placed in the response body. For more information go to [Routes](../routes).<br><br>
For more info on write values go [here](../../reference/classcrow_1_1json_1_1wvalue.html).
!!!note
Crow's json exceptions can be disabled by using the `#!cpp #define CROW_JSON_NO_ERROR_CHECK` macro. This should increase the program speed with the drawback of having unexpected behavious when used incorrectly (e.g. by attempting to parse an invalid json object).

View File

@ -1,3 +1,4 @@
**Introduced in: `v0.2`**<br><br>
Multipart is a way of forming HTTP requests or responses to contain multiple distinct parts.<br>
Such an approach allows a request to contain multiple different pieces of data with potentially conflicting data types in a single response payload.<br>
It is typically used either in html forms, or when uploading multiple files.<br><br>

View File

@ -0,0 +1,32 @@
A query string is the part of the url that comes after a `?` character, it is usually formatted as `key=value&otherkey=othervalue`.
<br><br>
Crow supports query strings through `crow::request::url_params`. The object is of type `crow::query_string` and can has the following functions:<br>
##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>
Works the same as `get`, but removes the returned value.
!!! note
`crow::request::url_params` is a const value, therefore for pop (also pop_list and pop_dict) to work, a copy needs to be made.
##get_list(name)
A url can be `http://example.com?key[]=value1&key[]=value2&key[]=value3`. Using `get_list("key")` on such a url returns an `std::vector<std::string>` containing `[value1, value2, value3]`.<br><br>
`#!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>
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>
Works the same as `get_dict` but removing the values from the query string.
!!!warning
if your query string contains both a list and dictionary with the same key, it is best to use `pop_list` before either `get_dict` or `pop_dict`, since a map cannot contain more than one value per key, each item in the list will override the previous and only the last will remain with an empty key.
<br><br>
For more information take a look [here](../../reference/classcrow_1_1query__string.html).

View File

@ -52,6 +52,7 @@ 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>
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>
@ -73,4 +74,5 @@ class a : public crow::returnable
```
##Catchall routes
**Introduced in: `v0.3`**<br><br>
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.

View File

@ -7,4 +7,6 @@ To enable SSL, first your application needs to define either a `.crt` and `.key`
You can also set your own SSL context (by using `boost::asio::ssl::context ctx`) and then applying it via the `#!cpp app.ssl(ctx)` method.<br><br>
**IMPORTANT NOTICE**: If you plan on using a proxy like Nginx or Apache2, **DO NOT** use SSL in crow, instead define it in your proxy instead and keep the connection between the proxy and Crow non-SSL.
!!! warning
If you plan on using a proxy like Nginx or Apache2, **DO NOT** use SSL in crow, instead define it in your proxy and keep the connection between the proxy and Crow non-SSL.

View File

@ -1,3 +1,4 @@
**Introduced in: `v0.2`**<br><br>
A static file is any file that resides in the server's storage.
Crow supports returning Static files as responses in 2 ways.

View File

@ -1,101 +1,3 @@
#
<p align="center"><img src="assets/crowlogo.svg" width=600></p>
<h4 align="center">A Fast and Easy to use microframework for the web.</h4>
<p align="center">
<a href="https://cloud.drone.io/CrowCpp/crow"><img src="https://cloud.drone.io/api/badges/CrowCpp/crow/status.svg" alt="Build Status"></a>
<a href="https://coveralls.io/github/CrowCpp/crow?branch=master"><img src="https://coveralls.io/repos/github/CrowCpp/crow/badge.svg?branch=master" alt="Coverage Status"></a>
<a href="https://crowcpp.github.io/crow"><img src="https://img.shields.io/badge/-Documentation-informational" alt="Documentation"></a>
<a href="https://gitter.im/crowfork/community?utm_source=badge&amp;utm_medium=badge&amp;utm_campaign=pr-badge"><img src="https://badges.gitter.im/crowfork/community.svg" alt="Gitter"></a>
</p>
## Description
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.
### Features
- Easy Routing (similar to flask).
- Type-safe Handlers.
- Blazingly fast (see [this benchmark](https://github.com/ipkn/crow-benchmark) and [this benchmark](https://github.com/guteksan/REST-CPP-benchmark)).
- Built in JSON support.
- [Mustache](http://mustache.github.io/) based templating library (`crow::mustache`).
- Header only library (single header file available).
- Middleware support for extensions.
- HTTP/1.1 and Websocket support.
- Multi-part request and response support.
- Uses modern C++ (11/14)
### Still in development
- [HTTP/2 support](https://github.com/crowcpp/crow/issues/8)
## Documentation
Available [here](https://crowcpp.github.io/crow).
## Examples
#### Hello World
```c++
#include "crow.h"
int main()
{
crow::SimpleApp app;
CROW_ROUTE(app, "/")([](){
return "Hello world";
});
app.port(18080).multithreaded().run();
}
```
#### JSON Response
```cpp
CROW_ROUTE(app, "/json")
([]{
crow::json::wvalue x;
x["message"] = "Hello, World!";
return x;
});
```
#### Arguments
```cpp
CROW_ROUTE(app,"/hello/<int>")
([](int count){
if (count > 100)
return crow::response(400);
std::ostringstream os;
os << count << " bottles of beer!";
return crow::response(os.str());
});
```
Handler arguments type check at compile time
```cpp
// Compile error with message "Handler type is mismatched with URL paramters"
CROW_ROUTE(app,"/another/<int>")
([](int a, int b){
return crow::response(500);
});
```
#### Handling JSON Requests
```cpp
CROW_ROUTE(app, "/add_json")
.methods("POST"_method)
([](const crow::request& req){
auto x = crow::json::load(req.body);
if (!x)
return crow::response(400);
int sum = x["a"].i()+x["b"].i();
std::ostringstream os;
os << sum;
return crow::response{os.str()};
});
```
More examples can be found [here](https://github.com/crowcpp/crow/tree/master/examples).
## Setting Up / Building
Available [here](https://crowcpp.github.io/crow/getting_started/setup).
---
template: home.html
---

300
docs/overrides/home.html Normal file
View File

@ -0,0 +1,300 @@
{% extends "main.html" %}
<!-- Render hero under tabs -->
<!-- Content -->
{% block content %}
<style>
.clogo{
margin-left: 15rem;
margin-right: 15rem;
width: 30rem;
}
.ccard{
border-style: solid;
border-width: .1rem;
border-color: #00000080;
border-radius: 0.5rem;
width: 10rem;
height: 12rem;
box-shadow: 2px 5px 5px #00000040;
margin-inline: 2rem;
transition: transform 0.3s;
}
.ccard:hover{
transform: scale(1.1);
}
.ccard__image{
max-width: 7.5rem;
max-height: 7.5rem;
margin-left: auto;
margin-right: auto;
display: block;
margin-top: 1rem;
padding-bottom: 0.5rem;
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%);
}
.ccard__text{
text-align: center;
}
.csection{
display: flex;
justify-content: center;
}
.ssection{
display:flex;
justify-content: center;
}
.sdescription{
display:flex;
align-items: center;
justify-content: center;
width: 50%;
height: 14rem;
}
.scontent{
display:flex;
align-items: center;
justify-content: center;
width: 50%;
height: 14rem;
}
.highlight{
width: 100%
}
.sbuttons{
display: flex;
justify-content: center;
}
.crow-button{
margin: 0rem 1rem;
}
code{
border-radius: 0.3rem !important;
}
.dcard{
width: 10rem;
height: 15rem;
margin-inline: 2rem;
transition: transform 0.3s;
}
.dcard:hover{
transform: scale(1.1);
}
.dcard__image{
max-width: 7.5rem;
max-height: 7.5rem;
margin-left: auto;
margin-right: auto;
display: block;
margin-top: 1rem;
}
.dcard__title{
font-size: 1.25rem;
margin: 0px 0px;
text-align: center;
}
.dcard__description{
font-size: 0.75rem;
margin: 0.1rem 0px;
text-align: center;
}
</style>
<img class="clogo" style="width:30rem" alt="logo" src="/assets/crowlogo_main_color.svg">
<h1 style="text-align:center;">A Fast and Easy to use microframework for the web.</h1>
<hr>
<section class="csection">
<div class="ccard">
<img class="ccard__image" src= /assets/fast_icon.svg>
<p class="ccard__text">Blazingly Fast</p>
</div>
<div class="ccard">
<img class="ccard__image" src= /assets/header_icon.svg>
<p class="ccard__text">Header Only</p>
</div>
<div class="ccard">
<img class="ccard__image" src= /assets/typesafe_icon.svg>
<p class="ccard__text">Typesafe handlers</p>
</div>
<div class="ccard">
<img class="ccard__image" src= /assets/websocket_icon.svg>
<p class="ccard__text">Websocket Support</p>
</div>
</section>
<hr>
<section class="ssection">
<div class="sdescription">
<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">#define CROW_MAIN</span>
<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>
<span class="n">crow</span><span class="o">::</span><span class="n">SimpleApp</span> <span class="n">app</span><span class="p">;</span>
<span class="cp">CROW_ROUTE</span><span class="p">(</span><span class="n">app</span><span class="p">,</span> <span class="s">"/"</span><span class="p">)([](){</span>
<span class="k">return</span> <span class="s">"Hello world"</span><span class="p">;</span>
<span class="p">});</span>
<span class="n">app</span><span class="p">.</span><span class="n">port</span><span class="p">(</span><span class="mi">18080</span><span class="p">).</span><span class="n">run</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div>
</div>
</section>
<section class="ssection">
<div class="scontent">
<div class="highlight"><pre id="__code_1"><span></span><button class="md-clipboard md-icon" title="Copy to clipboard" data-clipboard-target="#__code_1 > code"></button><code><span class="cp">CROW_ROUTE</span><span class="p">(</span><span class="n">app</span><span class="p">,</span> <span class="s">"/json"</span><span class="p">)</span>
<span class="p">([]{</span>
<span class="n">crow</span><span class="o">::</span><span class="n">json</span><span class="o">::</span><span class="n">wvalue</span> <span class="n">x</span><span class="p">;</span>
<span class="n">x</span><span class="p">[</span><span class="s">"message"</span><span class="p">]</span> <span class="o">=</span> <span class="s">"Hello, World!"</span><span class="p">;</span>
<span class="k">return</span> <span class="n">x</span><span class="p">;</span>
<span class="p">});</span>
</code></pre></div>
</div>
<div class="sdescription">
<h2 style="text-align: center;">JSON Support Built-in</h3>
</div>
</section>
<section class="ssection">
<div class="sdescription">
<h2 style="text-align: center;">URL parameter support as well!</h3>
</div>
<div class="scontent">
<div class="highlight"><pre id="__code_2"><span></span><button class="md-clipboard md-icon" title="Copy to clipboard" data-clipboard-target="#__code_2 > code"></button><code><span class="cp">CROW_ROUTE</span><span class="p">(</span><span class="n">app</span><span class="p">,</span><span class="s">"/hello/&lt;int&gt;"</span><span class="p">)</span>
<span class="p">([](</span><span class="kt">int</span> <span class="n">count</span><span class="p">){</span>
<span class="k">return</span> <span class="n">crow</span><span class="o">::</span><span class="n">response</span><span class="p">(std::to_string(count));</span></span>
<span class="p">});</span>
</code></pre></div>
</div>
</section>
<hr>
<h1 style="text-align:center;">Support Crow</h1>
<h3 style="text-align:center;">Crow is provided free of charge courtesy of everyone who is donating their money, time, and expertise to keep it going.<h3>
<h3 style="text-align:center;">Help us make something great!<h3>
<dev class="sbuttons">
<a href="https://opencollective.com/crow" title="Crow - OpenCollective" class="md-button crow-button">Fund Crow</a>
<a href="https://github.com/CrowCpp/Crow" title="Crow - OpenCollective" class="md-button crow-button">Develop Crow</a>
<a href="https://gitter.im/crowfork/community" title="Crow - OpenCollective" class="md-button crow-button">Chat with us</a>
</dev>
<hr>
<h1 style="text-align:center;">Get Crow</h1>
<h3 style="text-align:center;">Crow is everywhere, you just need to grab it!<h3>
<section class="csection">
<div class="dcard">
<a href="https://github.com/CrowCpp/Crow/releases/latest">
<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>
</div>
<div class="dcard">
<a href="https://aur.archlinux.org/packages/crow">
<img class="dcard__image" src="/assets/pkg_logos/arch.png">
<p class="dcard__title">AUR</p>
<p class="dcard__description">for Arch based systems</p>
</a>
</div>
<div class="dcard">
<a href="https://vcpkg.io">
<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>
</div>
<div class="dcard">
<a href="https://conan.io/center/crowcpp-crow">
<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>
</div>
<div class="dcard">
<a href="https://github.com/CrowCpp/Crow/releases/latest">
<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>
</div>
</section>
<hr>
<h1 style="text-align:center;">Learn Crow</h1>
<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>
</dev>
{% endblock %}
{% block site_nav %}{% endblock %}
{% block footer %}
<footer class="md-footer">
<!-- Further information -->
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<!-- Copyright and theme information -->
<div class="md-footer-copyright">
{% if config.copyright %}
<div class="md-footer-copyright__highlight">
{{ config.copyright }}
</div>
{% endif %}
{{ extracopyright }}
</div>
<!-- Social links -->
{% include "partials/social.html" %}
</div>
</div>
</footer>
{% endblock %}

9
docs/overrides/main.html Normal file
View File

@ -0,0 +1,9 @@
{% extends "base.html" %}
{% block extrahead %}
<meta property="og:title" content="CrowCpp"/>
<meta property="og:type" content="website" />
<meta property="og:description" content="A Fast and Easy to use microframework for the web."/>
<meta property="og:image" content="/assets/og_img.png" />
<meta property="og:url" content="https://crowcpp.org">
{% endblock %}

View File

@ -0,0 +1,150 @@
<!--
Copyright (c) 2016-2021 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.
-->
<!-- Header -->
<header class="md-header" data-md-component="header">
<nav
class="md-header__inner md-grid"
aria-label="{{ lang.t('header.title') }}"
>
<!-- Link to home -->
<a
href="{{ config.extra.homepage | d(nav.homepage.url, true) | url }}"
title="{{ config.site_name | e }}"
class="md-header__button md-logo"
aria-label="{{ config.site_name }}"
data-md-component="logo"
>
{% include "partials/logo.html" %}
</a>
<!-- Button to open drawer -->
<label class="md-header__button md-icon" for="__drawer">
{% include ".icons/material/menu" ~ ".svg" %}
</label>
<!-- Header title -->
<div class="md-header__title" data-md-component="header-title">
<div class="md-header__ellipsis">
<div class="md-header__topic">
<span class="md-ellipsis">
{{ config.site_name }}
</span>
</div>
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
{% if page and page.meta and page.meta.title %}
{{ page.meta.title }}
{% else %}
{{ page.title }}
{% endif %}
</span>
</div>
</div>
</div>
<!-- Color palette -->
{% if not config.theme.palette is mapping %}
<form class="md-header__option" data-md-component="palette">
{% for option in config.theme.palette %}
{% set primary = option.primary | replace(" ", "-") | lower %}
{% set accent = option.accent | replace(" ", "-") | lower %}
<input
class="md-option"
data-md-color-media="{{ option.media }}"
data-md-color-scheme="{{ option.scheme }}"
data-md-color-primary="{{ primary }}"
data-md-color-accent="{{ accent }}"
{% if option.toggle %}
aria-label="{{ option.toggle.name }}"
{% else %}
aria-hidden="true"
{% endif %}
type="radio"
name="__palette"
id="__palette_{{ loop.index }}"
/>
{% if option.toggle %}
<label
class="md-header__button md-icon"
title="{{ option.toggle.name }}"
for="__palette_{{ loop.index0 or loop.length }}"
hidden
>
{% include ".icons/" ~ option.toggle.icon ~ ".svg" %}
</label>
{% endif %}
{% endfor %}
</form>
{% endif %}
<!-- Site language selector -->
{% if config.extra.alternate %}
<div class="md-header__option"></form>
<div class="md-select">
{% set icon = config.theme.icon.alternate or "material/translate" %}
<button
class="md-header__button md-icon"
aria-label="{{ lang.t('select.language.title') }}"
>
{% include ".icons/" ~ icon ~ ".svg" %}
</button>
<div class="md-select__inner">
<ul class="md-select__list">
{% for alt in config.extra.alternate %}
<li class="md-select__item">
<a
href="{{ alt.link | url }}"
hreflang="{{ alt.lang }}"
class="md-select__link"
>
{{ alt.name }}
</a>
</li>
{% endfor %}
</ul>
</div>
</div>
</div>
{% endif %}
<!-- Button to open search modal -->
{% if "search" in config["plugins"] %}
<label class="md-header__button md-icon" for="__search">
{% include ".icons/material/magnify.svg" %}
</label>
<!-- Search interface -->
{% include "partials/search.html" %}
{% endif %}
<div class="md-header__source">
<a class="md-source" href="https://opencollective.com/crow" style="padding-left:2.4rem;"><img style="border-radius: 5px" alt="Open Collective" src="https://img.shields.io/opencollective/all/crow?label=Support%20Crow&color=important&labelColor=122027&logo=opencollective&style=for-the-badge"></a>
</div>
<!-- Repository information -->
{% if config.repo_url %}
<div class="md-header__source">
{% include "partials/source.html" %}
</div>
{% endif %}
</nav>
</header>

View File

@ -1,6 +1,31 @@
:root {
--md-primary-fg-color: #161616;
--md-accent-fg-color: #396A97;
--md-typeset-a-color: var(--md-accent-fg-color);
--md-primary-fg-color: #24404f;
--md-accent-fg-color: #122027;
--md-typeset-a-color: var(--md-accent-fg-color) !important;
--md-default-bg-color: #e5f2f8;
--md-code-bg-color: #2e3639 !important;
--md-code-hl-punctuation-color: #fff !important;
}
.md-typeset code {
background-color: #2e3639;
color: #afafaf;
}
.linenos {
background-color: #2e3639 !important;
color: #afafaf !important;
}
.highlight .p {
color: #bbb;
}
.highlight .o {
color: #afafaf;
}
.highlight .n {
color: #afafaf;
}

View File

@ -0,0 +1,8 @@
.md-header__source {
margin-left: 0px;
width: autho;
min-width: 9.6rem;
}
.code {
border-radius: 5px;
}

View File

@ -65,9 +65,21 @@ else ()
target_compile_options(example_chat PRIVATE "${compiler_options}")
target_link_libraries(example_chat PUBLIC ${REQUIRED_LIBRARIES})
add_executable(example_static_file example_static_file.cpp)
target_compile_options(example_static_file PRIVATE "${compiler_options}")
target_link_libraries(example_static_file PUBLIC ${REQUIRED_LIBRARIES})
add_executable(example_catchall example_catchall.cpp)
target_compile_options(example_catchall PRIVATE "${compiler_options}")
target_link_libraries(example_catchall PUBLIC ${REQUIRED_LIBRARIES})
add_executable(example_json_map example_json_map.cpp)
target_compile_options(example_json_map PRIVATE "${compiler_options}")
target_link_libraries(example_json_map PUBLIC ${REQUIRED_LIBRARIES})
add_executable(example_blueprint example_blueprint.cpp)
target_compile_options(example_blueprint PRIVATE "${compiler_options}")
target_link_libraries(example_blueprint PUBLIC ${REQUIRED_LIBRARIES})
add_custom_command(OUTPUT example_chat.html
COMMAND ${CMAKE_COMMAND} -E

View File

@ -0,0 +1,35 @@
#define CROW_MAIN
#include "crow.h"
int main()
{
crow::SimpleApp app;
crow::Blueprint bp("bp_prefix", "cstat", "ctemplate");
crow::Blueprint sub_bp("bp2", "csstat", "cstemplate");
CROW_BP_ROUTE(sub_bp, "/")
([]() {
return "Hello world!";
});
/* CROW_BP_ROUTE(bp, "/templatt")
([]() {
crow::mustache::context ctxdat;
ctxdat["messg"] = "fifty five!!";
auto page = crow::mustache::load("indks.html");
return page.render(ctxdat);
});
*/
CROW_BP_CATCHALL_ROUTE(sub_bp)([](){return "WRONG!!";});
bp.register_blueprint(sub_bp);
app.register_blueprint(bp);
app.loglevel(crow::LogLevel::DEBUG).port(18080).run();
}

View File

@ -1,4 +1,5 @@
#define CROW_MAIN
#define CROW_ENABLE_COMPRESSION
#include "crow.h"
#include "crow/compression.h"

View File

@ -0,0 +1,42 @@
#define CROW_MAIN
#define CROW_JSON_USE_MAP
#include "crow.h"
int main()
{
crow::SimpleApp app;
// simple json response using a map
// To see it in action enter {ip}:18080/json
// it shoud show amessage before zmessage despite adding zmessage first.
CROW_ROUTE(app, "/json")
([]{
crow::json::wvalue x;
x["zmessage"] = "Hello, World!";
x["amessage"] = "Hello, World2!";
return x;
});
CROW_ROUTE(app, "/json-initializer-list-constructor")
([] {
return crow::json::wvalue({
{"first", "Hello world!"}, /* stores a char const* hence a json::type::String */
{"second", std::string("How are you today?")}, /* stores a std::string hence a json::type::String. */
{"third", 54}, /* stores an int (as 54 is an int literal) hence a std::int64_t. */
{"fourth", 54l}, /* stores a long (as 54l is a long literal) hence a std::int64_t. */
{"fifth", 54u}, /* stores an unsigned int (as 54u is a unsigned int literal) hence a std::uint64_t. */
{"sixth", 54ul}, /* stores an unsigned long (as 54ul is an unsigned long literal) hence a std::uint64_t. */
{"seventh", 2.f}, /* stores a float (as 2.f is a float literal) hence a double. */
{"eighth", 2.}, /* stores a double (as 2. is a double literal) hence a double. */
{"ninth", nullptr}, /* stores a std::nullptr hence json::type::Null . */
{"tenth", true} /* stores a bool hence json::type::True . */
});
});
// enables all log
app.loglevel(crow::LogLevel::Debug);
app.port(18080)
.multithreaded()
.run();
}

View File

@ -1,5 +1,6 @@
//#define CROW_STATIC_DRIECTORY "alternative_directory/"
//#define CROW_STATIC_ENDPOINT "/alternative_endpoint/<path>"
//#define CROW_DISABLE_STATIC_DIR
#define CROW_MAIN
#include "crow.h"

View File

@ -44,31 +44,32 @@ int main()
app.get_middleware<ExampleMiddleware>().setMessage("hello");
app.route_dynamic("/")
CROW_ROUTE(app, "/")
.name("hello")
([]{
return "Hello World!";
});
app.route_dynamic("/about")
CROW_ROUTE(app, "/about")
([](){
return "About Crow example.";
});
// a request to /path should be forwarded to /path/
app.route_dynamic("/path/")
CROW_ROUTE(app, "/path/")
([](){
return "Trailing slash test case..";
});
// simple json response
app.route_dynamic("/json")
CROW_ROUTE(app, "/json")
([]{
crow::json::wvalue x;
x["message"] = "Hello, World!";
return x;
});
app.route_dynamic("/hello/<int>")
CROW_ROUTE(app, "/hello/<int>")
([](int count){
if (count > 100)
return crow::response(400);
@ -77,7 +78,7 @@ int main()
return crow::response(os.str());
});
app.route_dynamic("/add/<int>/<int>")
CROW_ROUTE(app, "/add/<int>/<int>")
([](crow::response& res, int a, int b){
std::ostringstream os;
os << a+b;
@ -92,7 +93,7 @@ int main()
//});
// more json example
app.route_dynamic("/add_json")
CROW_ROUTE(app, "/add_json")
.methods(crow::HTTPMethod::Post)
([](const crow::request& req){
auto x = crow::json::load(req.body);

View File

@ -42,7 +42,7 @@ int main()
return crow::response(os.str());
});
// example which uses only response as a paramter wihtout
// example which uses only response as a paramter without
// request being a parameter.
CROW_ROUTE(app,"/add/<int>/<int>")
([](crow::response& res, int a, int b){

View File

@ -8,7 +8,7 @@ int main()
{
crow::SimpleApp app;
std::mutex mtx;;
std::mutex mtx;
std::unordered_set<crow::websocket::connection*> users;
CROW_ROUTE(app, "/ws")

View File

@ -10,6 +10,7 @@
#include <thread>
#include <condition_variable>
#include "crow/version.h"
#include "crow/settings.h"
#include "crow/logging.h"
#include "crow/utility.h"
@ -18,15 +19,19 @@
#include "crow/http_request.h"
#include "crow/http_server.h"
#include "crow/dumb_timer_queue.h"
#ifdef CROW_ENABLE_COMPRESSION
#include "crow/compression.h"
#endif
#ifdef CROW_MSVC_WORKAROUND
#define CROW_ROUTE(app, url) app.route_dynamic(url)
#define CROW_BP_ROUTE(blueprint, url) blueprint.new_rule_dynamic(url)
#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)
#endif
#define CROW_CATCHALL_ROUTE(app) app.catchall_route()
#define CROW_BP_CATCHALL_ROUTE(blueprint) blueprint.catchall_rule()
namespace crow
{
@ -119,7 +124,7 @@ namespace crow
return *this;
}
///Set the server name (default Crow/0.2)
///Set the server name
self_t& server_name(std::string server_name)
{
server_name_ = server_name;
@ -157,12 +162,18 @@ namespace crow
/// crow::LogLevel::Warning (2)<br>
/// crow::LogLevel::Error (3)<br>
/// crow::LogLevel::Critical (4)<br>
self_t& loglevel(crow::LogLevel level)
self_t& loglevel(LogLevel level)
{
crow::logger::setLogLevel(level);
return *this;
}
self_t& register_blueprint(Blueprint& blueprint)
{
router_.register_blueprint(blueprint);
return *this;
}
///Set a custom duration and function to run on every tick
template <typename Duration, typename Func>
self_t& tick(Duration d, Func f) {
@ -171,6 +182,7 @@ namespace crow
return *this;
}
#ifdef CROW_ENABLE_COMPRESSION
self_t& use_compression(compression::algorithm algorithm)
{
comp_algorithm_ = algorithm;
@ -182,14 +194,41 @@ namespace crow
{
return comp_algorithm_;
}
#endif
///A wrapper for `validate()` in the router
///
///Go through the rules, upgrade them if possible, and add them to the list of rules
void validate()
{
router_.validate();
if (!validated_)
{
#ifndef CROW_DISABLE_STATIC_DIR
route<crow::black_magic::get_parameter_tag(CROW_STATIC_ENDPOINT)>(CROW_STATIC_ENDPOINT)
([](crow::response& res, std::string file_path_partial)
{
res.set_static_file_info(CROW_STATIC_DIRECTORY + file_path_partial);
res.end();
});
for (auto& bp : router_.blueprints())
{
if (!bp->static_dir().empty())
{
bp->new_rule_tagged<crow::black_magic::get_parameter_tag(CROW_STATIC_ENDPOINT)>(CROW_STATIC_ENDPOINT)
([bp](crow::response& res, std::string file_path_partial)
{
res.set_static_file_info(bp->static_dir() + '/' + file_path_partial);
res.end();
});
}
}
#endif
router_.validate();
validated_ = true;
}
}
///Notify anything using `wait_for_server_start()` to proceed
@ -203,15 +242,8 @@ namespace crow
///Run the server
void run()
{
#ifndef CROW_DISABLE_STATIC_DIR
route<crow::black_magic::get_parameter_tag(CROW_STATIC_ENDPOINT)>(CROW_STATIC_ENDPOINT)
([](crow::response& res, std::string file_path_partial)
{
res.set_static_file_info(CROW_STATIC_DIRECTORY + file_path_partial);
res.end();
});
validate();
#endif
#ifdef CROW_ENABLE_SSL
if (use_ssl_)
@ -358,10 +390,14 @@ namespace crow
private:
uint16_t port_ = 80;
uint16_t concurrency_ = 1;
std::string server_name_ = "Crow/0.2";
bool validated_ = false;
std::string server_name_ = std::string("Crow/") + VERSION;
std::string bindaddr_ = "0.0.0.0";
Router router_;
#ifdef CROW_ENABLE_COMPRESSION
compression::algorithm comp_algorithm_;
#endif
std::chrono::milliseconds tick_interval_;
std::function<void()> tick_function_;

View File

@ -8,7 +8,7 @@
namespace crow
{
enum class HTTPMethod
enum class HTTPMethod : char
{
#ifndef DELETE
DELETE = 0,
@ -69,7 +69,7 @@ namespace crow
return "invalid";
}
enum class ParamType
enum class ParamType : char
{
INT,
UINT,

View File

@ -1,10 +1,10 @@
#ifdef CROW_ENABLE_COMPRESSION
#pragma once
#include <string>
#include <zlib.h>
// http://zlib.net/manual.html
namespace crow
{
namespace compression
@ -95,3 +95,5 @@ namespace crow
}
}
}
#endif

View File

@ -263,7 +263,7 @@ namespace crow
req_ = std::move(parser_.to_request());
request& req = req_;
req.remoteIpAddress = adaptor_.remote_endpoint().address().to_string();
req.remote_ip_address = adaptor_.remote_endpoint().address().to_string();
if (parser_.check_version(1, 0))
{
@ -357,7 +357,7 @@ namespace crow
decltype(*middlewares_)>
(*middlewares_, ctx_, req_, res);
}
#ifdef CROW_ENABLE_COMPRESSION
std::string accept_encoding = req_.get_header_value("Accept-Encoding");
if (!accept_encoding.empty() && res.compressed)
{
@ -381,7 +381,7 @@ namespace crow
break;
}
}
#endif
//if there is a redirection with a partial URL, treat the URL as a route.
std::string location = res.get_header_value("Location");
if (!location.empty() && location.find("://", 0) == std::string::npos)

View File

@ -31,7 +31,7 @@ namespace crow
query_string url_params; ///< The parameters associated with the request. (everything after the `?`)
ci_map headers;
std::string body;
std::string remoteIpAddress; ///< The IP address from which the request was sent.
std::string remote_ip_address; ///< The IP address from which the request was sent.
void* middleware_context{};
boost::asio::io_service* io_service{};

View File

@ -28,7 +28,10 @@ namespace crow
int code{200}; ///< The Status code for the response.
std::string body; ///< The actual payload containing the response data.
ci_map headers; ///< HTTP headers.
#ifdef CROW_ENABLE_COMPRESSION
bool compressed = true; ///< If compression is enabled and this is false, the individual response will not be compressed.
#endif
bool is_head_response = false; ///< Whether this is a response to a HEAD request.
bool manual_length_header = false; ///< Whether Crow should automatically add a "Content-Length" header.
@ -84,6 +87,7 @@ namespace crow
code = r.code;
headers = std::move(r.headers);
completed_ = r.completed_;
file_info = std::move(r.file_info);
return *this;
}
@ -195,7 +199,9 @@ namespace crow
void set_static_file_info(std::string path){
file_info.path = path;
file_info.statResult = stat(file_info.path.c_str(), &file_info.statbuf);
#ifdef CROW_ENABLE_COMPRESSION
compressed = false;
#endif
if (file_info.statResult == 0)
{
std::size_t last_dot = path.find_last_of(".");

View File

@ -13,6 +13,7 @@
#include <memory>
#include "crow/version.h"
#include "crow/http_connection.h"
#include "crow/logging.h"
#include "crow/dumb_timer_queue.h"
@ -26,7 +27,7 @@ namespace crow
class Server
{
public:
Server(Handler* handler, std::string bindaddr, uint16_t port, std::string server_name = "Crow/0.2", std::tuple<Middlewares...>* middlewares = nullptr, uint16_t concurrency = 1, typename Adaptor::context* adaptor_ctx = nullptr)
Server(Handler* handler, std::string bindaddr, uint16_t port, std::string server_name = std::string("Crow/") + VERSION, std::tuple<Middlewares...>* middlewares = nullptr, uint16_t concurrency = 1, typename Adaptor::context* adaptor_ctx = nullptr)
: acceptor_(io_service_, tcp::endpoint(boost::asio::ip::address::from_string(bindaddr), port)),
signals_(io_service_, SIGINT, SIGTERM),
tick_timer_(io_service_),
@ -121,7 +122,7 @@ namespace crow
init_count ++;
while(1)
{
try
try
{
if (io_service_pool_[i]->run() == 0)
{
@ -135,7 +136,7 @@ namespace crow
}
}));
if (tick_function_ && tick_interval_.count() > 0)
if (tick_function_ && tick_interval_.count() > 0)
{
tick_timer_.expires_from_now(boost::posix_time::milliseconds(tick_interval_.count()));
tick_timer_.async_wait([this](const boost::system::error_code& ec)

View File

@ -1,9 +1,14 @@
#pragma once
//#define CROW_JSON_NO_ERROR_CHECK
//#define CROW_JSON_USE_MAP
#include <string>
#ifdef CROW_JSON_USE_MAP
#include <map>
#else
#include <unordered_map>
#endif
#include <iostream>
#include <algorithm>
#include <memory>
@ -36,7 +41,7 @@ namespace crow
inline void escape(const std::string& str, std::string& ret)
{
ret.reserve(ret.size() + str.size()+str.size()/4);
for(unsigned char c:str)
for(auto c:str)
{
switch(c)
{
@ -295,6 +300,28 @@ namespace crow
return static_cast<int>(i());
}
///Return any json value (not object or list) as a string.
explicit operator std::string() const
{
#ifndef CROW_JSON_NO_ERROR_CHECK
if (t() == type::Object || t() == type::List)
throw std::runtime_error("json type container");
#endif
switch (t())
{
case type::String:
return std::string(s());
case type::Null:
return std::string("null");
case type::True:
return std::string("true");
case type::False:
return std::string("false");
default:
return std::string(start_, end_-start_);
}
}
/// The type of the JSON value.
type t() const
{
@ -382,6 +409,22 @@ namespace crow
return detail::r_string{start_, end_};
}
///The list or object value
std::vector<rvalue> lo()
{
#ifndef CROW_JSON_NO_ERROR_CHECK
if (t() != type::Object && t() != type::List)
throw std::runtime_error("value is not a container");
#endif
std::vector<rvalue> ret;
ret.reserve(lsize_);
for (uint32_t i = 0; i<lsize_; i++)
{
ret.emplace_back(l_[i]);
}
return ret;
}
/// Convert escaped string character to their original form ("\\n" -> '\n').
void unescape() const
{
@ -448,6 +491,7 @@ namespace crow
}
}
///Check if the json object has the passed string as a key.
bool has(const char* str) const
{
return has(std::string(str));
@ -590,6 +634,21 @@ namespace crow
{
return (option_&error_bit)!=0;
}
std::vector<std::string> keys()
{
#ifndef CROW_JSON_NO_ERROR_CHECK
if (t() != type::Object)
throw std::runtime_error("value is not an object");
#endif
std::vector<std::string> ret;
ret.reserve(lsize_);
for (uint32_t i = 0; i<lsize_; i++)
{
ret.emplace_back(std::string(l_[i].key()));
}
return ret;
}
private:
bool is_cached() const
{
@ -1091,6 +1150,7 @@ namespace crow
}
// TODO caching key to speed up (flyweight?)
// I have no idea how flyweight could apply here, but maybe some speedup can happen if we stopped checking type since decode_string returns a string anyway
auto key = t.s();
ws_skip();
@ -1164,22 +1224,78 @@ namespace crow
class wvalue : public returnable
{
friend class crow::mustache::template_t;
public:
using object_type =
#ifdef CROW_JSON_USE_MAP
std::map<std::string, wvalue>;
#else
std::unordered_map<std::string, wvalue>;
#endif
public:
type t() const { return t_; }
private:
type t_{type::Null}; ///< The type of the value.
num_type nt{num_type::Null}; ///< The specific type of the number if \ref t_ is a number.
union {
union number {
double d;
int64_t si;
uint64_t ui {};
uint64_t ui;
public:
constexpr number() noexcept : ui() {} /* default constructor initializes unsigned integer. */
constexpr number(std::uint64_t value) noexcept : ui(value) {}
constexpr number(std::int64_t value) noexcept : si(value) {}
constexpr number(double value) noexcept : d(value) {}
} num; ///< Value if type is a number.
std::string s; ///< Value if type is a string.
std::unique_ptr<std::vector<wvalue>> l; ///< Value if type is a list.
#ifdef CROW_JSON_USE_MAP
std::unique_ptr<std::map<std::string, wvalue>> o;
#else
std::unique_ptr<std::unordered_map<std::string, wvalue>> o; ///< Value if type is a JSON object.
public:
#endif
public:
wvalue() : returnable("application/json") {}
wvalue(std::nullptr_t) : returnable("application/json"), t_(type::Null) {}
wvalue(bool value) : returnable("application/json"), t_(value ? type::True : type::False) {}
wvalue(std::uint8_t value) : returnable("application/json"), t_(type::Number), nt(num_type::Unsigned_integer), num(static_cast<std::uint64_t>(value)) {}
wvalue(std::uint16_t value) : returnable("application/json"), t_(type::Number), nt(num_type::Unsigned_integer), num(static_cast<std::uint64_t>(value)) {}
wvalue(std::uint32_t value) : returnable("application/json"), t_(type::Number), nt(num_type::Unsigned_integer), num(static_cast<std::uint64_t>(value)) {}
wvalue(std::uint64_t value) : returnable("application/json"), t_(type::Number), nt(num_type::Unsigned_integer), num(static_cast<std::uint64_t>(value)) {}
wvalue(std::int8_t value) : returnable("application/json"), t_(type::Number), nt(num_type::Signed_integer), num(static_cast<std::int64_t>(value)) {}
wvalue(std::int16_t value) : returnable("application/json"), t_(type::Number), nt(num_type::Signed_integer), num(static_cast<std::int64_t>(value)) {}
wvalue(std::int32_t value) : returnable("application/json"), t_(type::Number), nt(num_type::Signed_integer), num(static_cast<std::int64_t>(value)) {}
wvalue(std::int64_t value) : returnable("application/json"), t_(type::Number), nt(num_type::Signed_integer), num(static_cast<std::int64_t>(value)) {}
wvalue(float value) : returnable("application/json"), t_(type::Number), nt(num_type::Floating_point), num(static_cast<double>(value)) {}
wvalue(double value) : returnable("application/json"), t_(type::Number), nt(num_type::Floating_point), num(static_cast<double>(value)) {}
wvalue(char const* value) : returnable("application/json"), t_(type::String), s(value) {}
wvalue(std::string const& value) : returnable("application/json"), t_(type::String), s(value) {}
wvalue(std::string&& value) : returnable("application/json"), t_(type::String), s(std::move(value)) {}
wvalue(std::initializer_list<std::pair<std::string const, wvalue>> initializer_list) : returnable("application/json"), t_(type::Object), o(new object_type(initializer_list)) {}
wvalue(object_type const& value) : returnable("application/json"), t_(type::Object), o(new object_type(value)) {}
wvalue(object_type&& value) : returnable("application/json"), t_(type::Object), o(new object_type(std::move(value))) {}
wvalue(std::vector<wvalue>& r) : returnable("application/json")
{
t_ = type::List;
l = std::unique_ptr<std::vector<wvalue>>(new std::vector<wvalue>{});
l->reserve(r.size());
for(auto it = r.begin(); it != r.end(); ++it)
l->emplace_back(*it);
}
/// Create a write value from a read value (useful for editing JSON strings).
wvalue(const rvalue& r) : returnable("application/json")
{
@ -1209,16 +1325,55 @@ namespace crow
l->emplace_back(*it);
return;
case type::Object:
o = std::unique_ptr<
std::unordered_map<std::string, wvalue>
>(
new std::unordered_map<std::string, wvalue>{});
#ifdef CROW_JSON_USE_MAP
o = std::unique_ptr<std::map<std::string, wvalue>>(new std::map<std::string, wvalue>{});
#else
o = std::unique_ptr<std::unordered_map<std::string, wvalue>>(new std::unordered_map<std::string, wvalue>{});
#endif
for(auto it = r.begin(); it != r.end(); ++it)
o->emplace(it->key(), *it);
return;
}
}
wvalue(const wvalue& r) : returnable("application/json")
{
t_ = r.t();
switch(r.t())
{
case type::Null:
case type::False:
case type::True:
return;
case type::Number:
nt = r.nt;
if (nt == num_type::Floating_point)
num.d = r.num.d;
else if (nt == num_type::Signed_integer)
num.si = r.num.si;
else
num.ui = r.num.ui;
return;
case type::String:
s = r.s;
return;
case type::List:
l = std::unique_ptr<std::vector<wvalue>>(new std::vector<wvalue>{});
l->reserve(r.size());
for(auto it = r.l->begin(); it != r.l->end(); ++it)
l->emplace_back(*it);
return;
case type::Object:
#ifdef CROW_JSON_USE_MAP
o = std::unique_ptr<std::map<std::string, wvalue>>(new std::map<std::string, wvalue>{});
#else
o = std::unique_ptr<std::unordered_map<std::string, wvalue>>(new std::unordered_map<std::string, wvalue>{});
#endif
o->insert(r.o->begin(), r.o->end());
return;
}
}
wvalue(wvalue&& r) : returnable("application/json")
{
*this = std::move(r);
@ -1394,6 +1549,42 @@ namespace crow
return *this;
}
wvalue& operator=(std::initializer_list<std::pair<std::string const, wvalue>> initializer_list)
{
if (t_ != type::Object) {
reset();
t_ = type::Object;
o = std::unique_ptr<object_type>(new object_type(initializer_list));
} else {
(*o) = initializer_list;
}
return *this;
}
wvalue& operator=(object_type const& value)
{
if (t_ != type::Object) {
reset();
t_ = type::Object;
o = std::unique_ptr<object_type>(new object_type(value));
} else {
(*o) = value;
}
return *this;
}
wvalue& operator=(object_type&& value)
{
if (t_ != type::Object) {
reset();
t_ = type::Object;
o = std::unique_ptr<object_type>(new object_type(std::move(value)));
} else {
(*o) = std::move(value);
}
return *this;
}
wvalue& operator[](unsigned index)
{
if (t_ != type::List)
@ -1421,10 +1612,11 @@ namespace crow
reset();
t_ = type::Object;
if (!o)
o = std::unique_ptr<
std::unordered_map<std::string, wvalue>
>(
new std::unordered_map<std::string, wvalue>{});
#ifdef CROW_JSON_USE_MAP
o = std::unique_ptr<std::map<std::string, wvalue>>(new std::map<std::string, wvalue>{});
#else
o = std::unique_ptr<std::unordered_map<std::string, wvalue>>(new std::unordered_map<std::string, wvalue>{});
#endif
return (*o)[str];
}
@ -1440,6 +1632,15 @@ namespace crow
return result;
}
/// If the wvalue is a list, it returns the length of the list, otherwise it returns 1.
std::size_t size() const
{
if (t_ != type::List)
return 1;
return l->size();
}
/// Returns an estimated size of the value in bytes.
size_t estimate_length() const
{
switch(t_)
@ -1482,14 +1683,14 @@ namespace crow
private:
inline void dump_string(const std::string& str, std::string& out)
inline void dump_string(const std::string& str, std::string& out) const
{
out.push_back('"');
escape(str, out);
out.push_back('"');
}
inline void dump_internal(const wvalue& v, std::string& out)
inline void dump_internal(const wvalue& v, std::string& out) const
{
switch(v.t_)
{
@ -1565,7 +1766,7 @@ namespace crow
}
public:
std::string dump()
std::string dump() const
{
std::string ret;
ret.reserve(estimate_length());

View File

@ -14,11 +14,13 @@ namespace crow
enum class LogLevel
{
#ifndef ERROR
#ifndef DEBUG
DEBUG = 0,
INFO,
WARNING,
ERROR,
CRITICAL,
#endif
#endif
Debug = 0,

View File

@ -0,0 +1,27 @@
#pragma once
#include "crow/http_request.h"
#include "crow/http_response.h"
namespace crow
{
struct UTF8
{
struct context
{
};
void before_handle(request& /*req*/, response& /*res*/, context& /*ctx*/)
{
}
void after_handle(request& /*req*/, response& res, context& ctx)
{
if (get_header_value(res.headers, "Content-Type").empty())
{
res.set_header("Content-Type", "text/plain; charset=utf-8");
}
}
};
}

View File

@ -45,7 +45,7 @@ namespace crow
}
///Represent all parts as a string (**does not include message headers**)
std::string dump() override
std::string dump() const override
{
std::stringstream str;
std::string delimiter = dd + boundary;
@ -60,7 +60,7 @@ namespace crow
}
///Represent an individual part as a string
std::string dump(int part_)
std::string dump(int part_) const
{
std::stringstream str;
part item = parts[part_];
@ -92,7 +92,7 @@ namespace crow
private:
std::string get_boundary(const std::string& header)
std::string get_boundary(const std::string& header) const
{
size_t found = header.find("boundary=");
if (found)
@ -181,14 +181,14 @@ namespace crow
}
}
inline std::string trim (std::string& string, const char& excess = '"')
inline std::string trim (std::string& string, const char& excess = '"') const
{
if (string.length() > 1 && string[0] == excess && string[string.length()-1] == excess)
return string.substr(1, string.length()-2);
return string;
}
inline std::string pad (std::string& string, const char& padding = '"')
inline std::string pad (std::string& string, const char& padding = '"') const
{
return (padding + string + padding);
}

View File

@ -196,7 +196,7 @@ inline char * qs_k2v(const char * key, char * const * qs_kv, int qs_kv_size, int
}
#endif // _qsSORTING
return NULL;
return nullptr;
}
inline boost::optional<std::pair<std::string, std::string>> qs_dict_name2kv(const char * dict_name, char * const * qs_kv, int qs_kv_size, int nth = 0)
@ -362,16 +362,41 @@ namespace crow
}
/// Get a value from a name, used for `?name=value`.
///
/// Note: this method returns the value of the first occurrence of the key only, to return all occurrences, see \ref get_list().
char* get (const std::string& name) const
{
char* ret = qs_k2v(name.c_str(), key_value_pairs_.data(), key_value_pairs_.size());
return ret;
}
std::vector<char*> get_list (const std::string& name) const
/// Works similar to \ref get() except it removes the item from the query string.
char* pop (const std::string& name)
{
char* ret = get(name);
if (ret != nullptr)
{
for (unsigned int i = 0; i<key_value_pairs_.size(); i++)
{
std::string str_item(key_value_pairs_[i]);
if (str_item.substr(0, name.size()+1) == name+'=')
{
key_value_pairs_.erase(key_value_pairs_.begin()+i);
break;
}
}
}
return ret;
}
/// Returns a list of values, passed as `?name[]=value1&name[]=value2&...name[]=valuen` with n being the size of the list.
///
/// Note: Square brackets in the above example are controlled by `use_brackets` boolean (true by default). If set to false, the example becomes `?name=value1,name=value2...name=valuen`
std::vector<char*> get_list (const std::string& name, bool use_brackets = true) const
{
std::vector<char*> ret;
std::string plus = name + "[]";
std::string plus = name + (use_brackets ? "[]" : "");
char* element = nullptr;
int count = 0;
@ -385,6 +410,29 @@ namespace crow
return ret;
}
/// Similar to \ref get_list() but it removes the
std::vector<char*> pop_list (const std::string& name, bool use_brackets = true)
{
std::vector<char*> ret = get_list(name, use_brackets);
if (!ret.empty())
{
for (unsigned int i = 0; i<key_value_pairs_.size(); i++)
{
std::string str_item(key_value_pairs_[i]);
if ((use_brackets ? (str_item.substr(0, name.size()+3) == name+"[]=") : (str_item.substr(0, name.size()+1) == name+'=')))
{
key_value_pairs_.erase(key_value_pairs_.begin()+i--);
}
}
}
return ret;
}
/// Works similar to \ref get_list() except the brackets are mandatory must not be empty.
///
/// For example calling `get_dict(yourname)` on `?yourname[sub1]=42&yourname[sub2]=84` would give a map containing `{sub1 : 42, sub2 : 84}`.
///
/// if your query string has both empty brackets and ones with a key inside, use pop_list() to get all the values without a key before running this method.
std::unordered_map<std::string, std::string> get_dict (const std::string& name) const
{
std::unordered_map<std::string, std::string> ret;
@ -400,6 +448,35 @@ namespace crow
return ret;
}
/// Works the same as \ref get_dict() but removes the values from the query string.
std::unordered_map<std::string, std::string> pop_dict (const std::string& name)
{
std::unordered_map<std::string, std::string> ret = get_dict(name);
if (!ret.empty())
{
for (unsigned int i = 0; i<key_value_pairs_.size(); i++)
{
std::string str_item(key_value_pairs_[i]);
if (str_item.substr(0, name.size()+1) == name+'[')
{
key_value_pairs_.erase(key_value_pairs_.begin()+i--);
}
}
}
return ret;
}
std::vector<std::string> keys() const
{
std::vector<std::string> ret;
for (auto element: key_value_pairs_)
{
std::string str_element(element);
ret.emplace_back(str_element.substr(0, str_element.find('=')));
}
return ret;
}
private:
std::string url_;
std::vector<char*> key_value_pairs_;

View File

@ -8,7 +8,7 @@ namespace crow
struct returnable
{
std::string content_type;
virtual std::string dump() = 0;
virtual std::string dump() const = 0;
returnable(std::string ctype) : content_type {ctype}
{}

File diff suppressed because it is too large Load Diff

10
include/crow/version.h Normal file
View File

@ -0,0 +1,10 @@
#pragma once
namespace crow {
#ifdef CROW_MAIN
char VERSION[] = "master";
#else
extern char VERSION[];
#endif
}

View File

@ -194,7 +194,7 @@ namespace crow
buf[0] += opcode;
if (size < 126)
{
buf[1] += size;
buf[1] += static_cast<char>(size);
return {buf, buf+2};
}
else if (size < 0x10000)
@ -408,10 +408,10 @@ namespace crow
break;
case WebSocketReadState::Payload:
{
size_t to_read = buffer_.size();
auto to_read = static_cast<std::uint64_t>(buffer_.size());
if (remaining_length_ < to_read)
to_read = remaining_length_;
adaptor_.socket().async_read_some( boost::asio::buffer(buffer_, to_read),
adaptor_.socket().async_read_some(boost::asio::buffer(buffer_, static_cast<std::size_t>(to_read)),
[this](const boost::system::error_code& ec, std::size_t bytes_transferred)
{
is_reading = false;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@ -1,9 +1,9 @@
site_name: Crow
# Repository
repo_name: crowcpp/crow
repo_url: https://github.com/crowcpp/crow
site_url: https://crowcpp.github.io/crow
repo_name: CrowCpp/Crow
repo_url: https://github.com/CrowCpp/Crow
site_url: https://crowcpp.org
edit_uri: ""
theme:
@ -16,6 +16,7 @@ theme:
logo: 'assets/favicon.svg'
icon:
repo: fontawesome/brands/github-square
custom_dir: docs/overrides
markdown_extensions:
- admonition
@ -37,9 +38,12 @@ nav:
- 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
- Writing Tests: guides/testing.md
- Server setup:
@ -58,5 +62,6 @@ extra:
extra_css:
- 'stylesheets/colors.css'
- 'stylesheets/latofonts.css'
- 'stylesheets/extra.css'
copyright: 'Copyright &copy; 2020 Farook Al-Sammarraie'
copyright: 'Copyright &copy; 2020-2021 CrowCpp'

View File

@ -18,6 +18,8 @@ output_path = sys.argv[2]
middlewares = [x.rsplit(sep, 1)[-1][:-2] for x in glob(pt.join(header_path, ('crow'+sep+'middlewares'+sep+'*.h*')))]
with open(header_path+'/../LICENSE', 'r') as file:
lsc = '/*' + file.read() + '*/'
middlewares_actual = []
if len(sys.argv) > 3:
@ -83,7 +85,7 @@ for x in edges:
assert order.index(x) < order.index(y), 'cyclic include detected'
print(order)
build = []
build = [lsc]
for header in order:
d = open(pt.join(header_path, header)).read()
build.append(re_depends.sub(lambda x: '\n', d))

21
scripts/release.py Executable file
View File

@ -0,0 +1,21 @@
#!/bin/env python3
import os
import sys
import shutil
if len(sys.argv) != 2:
print("Usage: {} VERSION".format(sys.argv[0]))
sys.exit(1)
version = str(sys.argv[1])
releasePath = os.path.join(os.path.dirname(__file__), "..", "build_release")
if os.path.exists(releasePath):
shutil.rmtree(releasePath)
os.mkdir(releasePath)
os.chdir(releasePath)
os.system("cmake -DBUILD_EXAMPLES=OFF -DBUILD_TESTING=OFF -DCPACK_PACKAGE_FILE_NAME=\"crow-{}\" .. && make -j5".format(version))
os.system("sed -i 's/constexpr char VERSION\\[\\] = \"master\";/constexpr char VERSION\\[\\] = \"{}\";/g' crow_all.h".format(version))
os.system("cpack")

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 41 KiB

View File

@ -1,4 +1,5 @@
#define CATCH_CONFIG_MAIN
#define CROW_ENABLE_COMPRESSION
#define CROW_LOG_LEVEL 0
#define CROW_MAIN
#include <sys/stat.h>
@ -665,6 +666,24 @@ TEST_CASE("json_read_unescaping")
}
}
TEST_CASE("json_read_string")
{
auto x = json::load(R"({"message": 53})");
int y (x["message"]);
std::string z(x["message"]);
CHECK(53 == y);
CHECK("53" == z);
}
TEST_CASE("json_read_container")
{
auto x = json::load(R"({"first": 53, "second": "55", "third": [5,6,7,8,3,2,1,4]})");
CHECK(std::vector<std::string>({"first", "second", "third"}) == x.keys());
CHECK(53 == int(x.lo()[0]));
CHECK("55" == std::string(x.lo()[1]));
CHECK (8 == int(x.lo()[2].lo()[3]));
}
TEST_CASE("json_write")
{
json::wvalue x;
@ -700,11 +719,12 @@ TEST_CASE("json_write")
CHECK(R"({"scores":[1,2,3]})" == y.dump());
}
TEST_CASE("json_copy_r_to_w_to_r")
TEST_CASE("json_copy_r_to_w_to_w_to_r")
{
json::rvalue r = json::load(
R"({"smallint":2,"bigint":2147483647,"fp":23.43,"fpsc":2.343e1,"str":"a string","trueval":true,"falseval":false,"nullval":null,"listval":[1,2,"foo","bar"],"obj":{"member":23,"other":"baz"}})");
json::wvalue w{r};
json::wvalue v{r};
json::wvalue w(v);
json::rvalue x =
json::load(w.dump()); // why no copy-ctor wvalue -> rvalue?
CHECK(2 == x["smallint"]);
@ -726,6 +746,294 @@ TEST_CASE("json_copy_r_to_w_to_r")
CHECK("other" == x["obj"]["other"].key());
}
TEST_CASE("json::wvalue::wvalue(bool)") {
CHECK(json::wvalue(true).t() == json::type::True);
CHECK(json::wvalue(false).t() == json::type::False);
}
TEST_CASE("json::wvalue::wvalue(std::uint8_t)") {
std::uint8_t i = 42;
json::wvalue value = i;
CHECK(value.t() == json::type::Number);
CHECK(value.dump() == "42");
}
TEST_CASE("json::wvalue::wvalue(std::uint16_t)") {
std::uint16_t i = 42;
json::wvalue value = i;
CHECK(value.t() == json::type::Number);
CHECK(value.dump() == "42");
}
TEST_CASE("json::wvalue::wvalue(std::uint32_t)") {
std::uint32_t i = 42;
json::wvalue value = i;
CHECK(value.t() == json::type::Number);
CHECK(value.dump() == "42");
}
TEST_CASE("json::wvalue::wvalue(std::uint64_t)") {
std::uint64_t i = 42;
json::wvalue value = i;
CHECK(value.t() == json::type::Number);
CHECK(value.dump() == "42");
}
TEST_CASE("json::wvalue::wvalue(std::int8_t)") {
std::int8_t i = -42;
json::wvalue value = i;
CHECK(value.t() == json::type::Number);
CHECK(value.dump() == "-42");
}
TEST_CASE("json::wvalue::wvalue(std::int16_t)") {
std::int16_t i = -42;
json::wvalue value = i;
CHECK(value.t() == json::type::Number);
CHECK(value.dump() == "-42");
}
TEST_CASE("json::wvalue::wvalue(std::int32_t)") {
std::int32_t i = -42;
json::wvalue value = i;
CHECK(value.t() == json::type::Number);
CHECK(value.dump() == "-42");
}
TEST_CASE("json::wvalue::wvalue(std::int64_t)") {
std::int64_t i = -42;
json::wvalue value = i;
CHECK(value.t() == json::type::Number);
CHECK(value.dump() == "-42");
}
TEST_CASE("json::wvalue::wvalue(float)") {
float f = 4.2;
json::wvalue value = f;
CHECK(value.t() == json::type::Number);
CHECK(value.dump() == "4.2");
}
TEST_CASE("json::wvalue::wvalue(double)") {
double d = 4.2;
json::wvalue value = d;
CHECK(value.t() == json::type::Number);
CHECK(value.dump() == "4.2");
}
TEST_CASE("json::wvalue::wvalue(char const*)") {
char const* str = "Hello world!";
json::wvalue value = str;
CHECK(value.t() == json::type::String);
CHECK(value.dump() == "\"Hello world!\"");
}
TEST_CASE("json::wvalue::wvalue(std::string const&)") {
std::string str = "Hello world!";
json::wvalue value = str;
CHECK(value.t() == json::type::String);
CHECK(value.dump() == "\"Hello world!\"");
}
TEST_CASE("json::wvalue::wvalue(std::string&&)") {
std::string str = "Hello world!";
json::wvalue value = std::move(str);
CHECK(value.t() == json::type::String);
CHECK(value.dump() == "\"Hello world!\"");
}
TEST_CASE("json::wvalue::wvalue(std::initializer_list<std::pair<std::string const, json::wvalue>>)") {
json::wvalue integer, number, truth, lie, null;
integer = 2147483647;
number = 23.43;
truth = true;
lie = false;
/* initializer-list constructor. */
json::wvalue value({
{"integer", integer},
{"number", number},
{"truth", truth},
{"lie", lie},
{"null", null}
});
CHECK(value["integer"].dump() == integer.dump());
CHECK(value["number"].dump() == number.dump());
CHECK(value["truth"].dump() == truth.dump());
CHECK(value["lie"].dump() == lie.dump());
CHECK(value["null"].dump() == null.dump());
}
TEST_CASE("json::wvalue::wvalue(std::[unordered_]map<std::string, json::wvalue> const&)") {
json::wvalue integer, number, truth, lie, null;
integer = 2147483647;
number = 23.43;
truth = true;
lie = false;
json::wvalue::object_type map({
{"integer", integer},
{"number", number},
{"truth", truth},
{"lie", lie},
{"null", null}
});
json::wvalue value(map); /* copy-constructor. */
CHECK(value["integer"].dump() == integer.dump());
CHECK(value["number"].dump() == number.dump());
CHECK(value["truth"].dump() == truth.dump());
CHECK(value["lie"].dump() == lie.dump());
CHECK(value["null"].dump() == null.dump());
}
TEST_CASE("json::wvalue::wvalue(std::[unordered_]map<std::string, json::wvalue>&&)") {
json::wvalue integer, number, truth, lie, null;
integer = 2147483647;
number = 23.43;
truth = true;
lie = false;
json::wvalue::object_type map = {{
{"integer", integer},
{"number", number},
{"truth", truth},
{"lie", lie},
{"null", null}
}};
json::wvalue value(std::move(map)); /* move constructor. */
// json::wvalue value = std::move(map); /* move constructor. */
CHECK(value["integer"].dump() == integer.dump());
CHECK(value["number"].dump() == number.dump());
CHECK(value["truth"].dump() == truth.dump());
CHECK(value["lie"].dump() == lie.dump());
CHECK(value["null"].dump() == null.dump());
}
TEST_CASE("json::wvalue::operator=(std::initializer_list<std::pair<std::string const, json::wvalue>>)") {
json::wvalue integer, number, truth, lie, null;
integer = 2147483647;
number = 23.43;
truth = true;
lie = false;
json::wvalue value;
/* initializer-list assignment. */
value = {
{"integer", integer},
{"number", number},
{"truth", truth},
{"lie", lie},
{"null", null}
};
CHECK(value["integer"].dump() == integer.dump());
CHECK(value["number"].dump() == number.dump());
CHECK(value["truth"].dump() == truth.dump());
CHECK(value["lie"].dump() == lie.dump());
CHECK(value["null"].dump() == null.dump());
}
TEST_CASE("json::wvalue::operator=(std::[unordered_]map<std::string, json::wvalue> const&)") {
json::wvalue integer, number, truth, lie, null;
integer = 2147483647;
number = 23.43;
truth = true;
lie = false;
json::wvalue::object_type map({
{"integer", integer},
{"number", number},
{"truth", truth},
{"lie", lie},
{"null", null}
});
json::wvalue value;
value = map; /* copy assignment. */
CHECK(value["integer"].dump() == integer.dump());
CHECK(value["number"].dump() == number.dump());
CHECK(value["truth"].dump() == truth.dump());
CHECK(value["lie"].dump() == lie.dump());
CHECK(value["null"].dump() == null.dump());
}
TEST_CASE("json::wvalue::operator=(std::[unordered_]map<std::string, json::wvalue>&&)") {
json::wvalue integer, number, truth, lie, null;
integer = 2147483647;
number = 23.43;
truth = true;
lie = false;
json::wvalue::object_type map({
{"integer", integer},
{"number", number},
{"truth", truth},
{"lie", lie},
{"null", null}
});
json::wvalue value;
value = std::move(map); /* move assignment. */
CHECK(value["integer"].dump() == integer.dump());
CHECK(value["number"].dump() == number.dump());
CHECK(value["truth"].dump() == truth.dump());
CHECK(value["lie"].dump() == lie.dump());
CHECK(value["null"].dump() == null.dump());
}
TEST_CASE("json_vector")
{//TODO probably make constructors for the same values as = operator
json::wvalue a;
json::wvalue b;
json::wvalue c;
json::wvalue d;
json::wvalue e;
json::wvalue f;
json::wvalue g;
json::wvalue h;
a = 5;
b = 6;
c = 7;
d = 8;
e = 4;
f = 3;
g = 2;
h = 1;
std::vector<json::wvalue> nums;
nums.emplace_back(a);
nums.emplace_back(b);
nums.emplace_back(c);
nums.emplace_back(d);
nums.emplace_back(e);
nums.emplace_back(f);
nums.emplace_back(g);
nums.emplace_back(h);
json::wvalue x(nums);
CHECK(8 == x.size());
CHECK("[5,6,7,8,4,3,2,1]" == x.dump());
}
TEST_CASE("template_basic")
{
auto t = crow::mustache::compile(R"---(attack of {{name}})---");
@ -1130,9 +1438,15 @@ TEST_CASE("simple_url_params")
c.receive(asio::buffer(buf, 2048));
c.close();
CHECK(string(last_url_params.get("hello")) == "world");
CHECK(string(last_url_params.get("left")) == "right");
CHECK(string(last_url_params.get("up")) == "down");
query_string mutable_params(last_url_params);
CHECK(string(mutable_params.get("hello")) == "world");
CHECK(string(mutable_params.get("left")) == "right");
CHECK(string(mutable_params.get("up")) == "down");
std::string z = mutable_params.pop("left");
CHECK(z == "right");
CHECK(mutable_params.get("left") == nullptr);
}
// check multiple value, multiple types
sendmsg = "GET /params?int=100&double=123.45&boolean=1\r\n\r\n";
@ -1165,8 +1479,7 @@ TEST_CASE("simple_url_params")
CHECK(string(last_url_params.get_list("tmnt")[0]) == "leonardo");
}
// check multiple array value
sendmsg =
"GET /params?tmnt[]=leonardo&tmnt[]=donatello&tmnt[]=raphael\r\n\r\n";
sendmsg = "GET /params?tmnt[]=leonardo&tmnt[]=donatello&tmnt[]=raphael\r\n\r\n";
{
asio::ip::tcp::socket c(is);
@ -1180,6 +1493,25 @@ TEST_CASE("simple_url_params")
CHECK(string(last_url_params.get_list("tmnt")[0]) == "leonardo");
CHECK(string(last_url_params.get_list("tmnt")[1]) == "donatello");
CHECK(string(last_url_params.get_list("tmnt")[2]) == "raphael");
CHECK(last_url_params.pop_list("tmnt").size() == 3);
CHECK(last_url_params.get_list("tmnt").size() == 0);
}
// check dictionary value
sendmsg = "GET /params?kees[one]=vee1&kees[two]=vee2&kees[three]=vee3\r\n\r\n";
{
asio::ip::tcp::socket c(is);
c.connect(asio::ip::tcp::endpoint(asio::ip::address::from_string(LOCALHOST_ADDRESS), 45451));
c.send(asio::buffer(sendmsg));
c.receive(asio::buffer(buf, 2048));
c.close();
CHECK(last_url_params.get_dict("kees").size() == 3);
CHECK(string(last_url_params.get_dict("kees")["one"]) == "vee1");
CHECK(string(last_url_params.get_dict("kees")["two"]) == "vee2");
CHECK(string(last_url_params.get_dict("kees")["three"]) == "vee3");
CHECK(last_url_params.pop_dict("kees").size() == 3);
CHECK(last_url_params.get_dict("kees").size() == 0);
}
app.stop();
}
@ -1341,14 +1673,15 @@ TEST_CASE("stream_response")
SimpleApp app;
CROW_ROUTE(app, "/test")
([](const crow::request&, crow::response& res)
{
std::string keyword_ = "hello";
std::string key_response;
for (unsigned int i = 0; i<250000; i++)
key_response += keyword_;
std::string keyword_ = "hello";
std::string key_response;
for (unsigned int i = 0; i<250000; i++)
key_response += keyword_;
CROW_ROUTE(app, "/test")
([&key_response](const crow::request&, crow::response& res)
{
res.body = key_response;
res.end();
});
@ -1356,7 +1689,7 @@ TEST_CASE("stream_response")
app.validate();
//running the test on a separate thread to allow the client to sleep
std::thread runTest([&app](){
std::thread runTest([&app, &key_response](){
auto _ = async(launch::async,
[&] { app.bindaddr(LOCALHOST_ADDRESS).port(45451).run(); });
@ -1370,9 +1703,6 @@ TEST_CASE("stream_response")
{
asio::streambuf b;
std::string keyword_ = "hello";
std::string key_response;
asio::ip::tcp::socket c(is);
c.connect(asio::ip::tcp::endpoint(
asio::ip::address::from_string(LOCALHOST_ADDRESS), 45451));
@ -1382,10 +1712,6 @@ TEST_CASE("stream_response")
static char buf[2048];
c.receive(asio::buffer(buf, 2048));
//creating the string to compare against
for (unsigned int i = 0; i<250000; i++)
key_response += keyword_;
//"hello" is 5 bytes, (5*250000)/16384 = 76.2939
for (unsigned int i = 0; i<76; i++)
{
@ -1810,3 +2136,115 @@ TEST_CASE("catchall")
CHECK(404 == res.code);
}
}
TEST_CASE("blueprint")
{
SimpleApp app;
crow::Blueprint bp("bp_prefix", "cstat", "ctemplate");
crow::Blueprint bp_not_sub("bp_prefix_second");
crow::Blueprint sub_bp("bp2", "csstat", "cstemplate");
crow::Blueprint sub_sub_bp("bp3");
CROW_BP_ROUTE(sub_bp, "/hello")
([]() {
return "Hello world!";
});
CROW_BP_ROUTE(bp_not_sub, "/hello")
([]() {
return "Hello world!";
});
CROW_BP_ROUTE(sub_sub_bp, "/hi")
([]() {
return "Hi world!";
});
CROW_BP_CATCHALL_ROUTE(sub_bp)([](){return response(200, "WRONG!!");});
app. register_blueprint(bp);
app. register_blueprint(bp_not_sub);
bp. register_blueprint(sub_bp);
sub_bp.register_blueprint(sub_sub_bp);
app.validate();
{
request req;
response res;
req.url = "/bp_prefix/bp2/hello";
app.handle(req, res);
CHECK("Hello world!" == res.body);
}
{
request req;
response res;
req.url = "/bp_prefix_second/hello";
app.handle(req, res);
CHECK("Hello world!" == res.body);
}
{
request req;
response res;
req.url = "/bp_prefix/bp2/bp3/hi";
app.handle(req, res);
CHECK("Hi world!" == res.body);
}
{
request req;
response res;
req.url = "/bp_prefix/nonexistent";
app.handle(req, res);
CHECK(404 == res.code);
}
{
request req;
response res;
req.url = "/bp_prefix_second/nonexistent";
app.handle(req, res);
CHECK(404 == res.code);
}
{
request req;
response res;
req.url = "/bp_prefix/bp2/nonexistent";
app.handle(req, res);
CHECK(200 == res.code);
CHECK("WRONG!!" == res.body);
}
{
request req;
response res;
req.url = "/bp_prefix/bp2/bp3/nonexistent";
app.handle(req, res);
CHECK(200 == res.code);
CHECK("WRONG!!" == res.body);
}
}

71
vcpkg.json Normal file
View File

@ -0,0 +1,71 @@
{
"name": "crow-examples",
"version": "master",
"dependencies": [
{
"name": "boost-array",
"version>=": "1.70.0"
},
{
"name": "boost-algorithm",
"version>=": "1.70.0"
},
{
"name": "boost-asio",
"version>=": "1.70.0"
},
{
"name": "boost-date-time",
"version>=": "1.70.0"
},
{
"name": "boost-functional",
"version>=": "1.70.0"
},
{
"name": "boost-lexical-cast",
"version>=": "1.70.0"
},
{
"name": "boost-optional",
"version>=": "1.70.0"
},
{
"name": "openssl-windows"
},
{
"name": "zlib"
}
],
"overrides": [
{
"name": "boost-array",
"version": "1.70.0"
},
{
"name": "boost-algorithm",
"version": "1.70.0"
},
{
"name": "boost-asio",
"version-semver": "1.70.0-2"
},
{
"name": "boost-date-time",
"version": "1.70.0"
},
{
"name": "boost-functional",
"version": "1.70.0"
},
{
"name": "boost-lexical-cast",
"version": "1.70.0"
},
{
"name": "boost-optional",
"version": "1.70.0"
}
],
"builtin-baseline": "44d94c2edbd44f0c01d66c2ad95eb6982a9a61bc"
}