Merge pull request #372 from CrowCpp/doc_updates

Updated documentation in mkdocs and doxygen
This commit is contained in:
Farook Al-Sammarraie 2022-03-24 13:06:47 +03:00 committed by GitHub
commit 90bd4b9494
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 162 additions and 75 deletions

View File

@ -680,7 +680,7 @@ GENERATE_DEPRECATEDLIST= YES
# sections, marked by \if <section_label> ... \endif and \cond <section_label>
# ... \endcond blocks.
ENABLED_SECTIONS = $(RAPIDJSON_SECTIONS)
ENABLED_SECTIONS =
# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
# initial value of a variable or macro / define can have for it to appear in the
@ -2129,14 +2129,7 @@ INCLUDE_FILE_PATTERNS =
# recursively expanded use the := operator instead of the = operator.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
PREDEFINED = RAPIDJSON_DOXYGEN_RUNNING \
"RAPIDJSON_NAMESPACE_BEGIN=namespace rapidjson {" \
"RAPIDJSON_NAMESPACE_END=}" \
RAPIDJSON_REMOVEFPTR_(x)=x \
RAPIDJSON_ENABLEIF_RETURN(cond \
"returntype)=RAPIDJSON_REMOVEFPTR_ returntype" \
RAPIDJSON_DISABLEIF_RETURN(cond \
"returntype)=RAPIDJSON_REMOVEFPTR_ returntype"
PREDEFINED =
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
# tag can be used to specify a list of macro names that should be expanded. The
@ -2145,7 +2138,7 @@ PREDEFINED = RAPIDJSON_DOXYGEN_RUNNING \
# definition found in the source code.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
EXPAND_AS_DEFINED = RAPIDJSON_NOEXCEPT
EXPAND_AS_DEFINED =
# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
# remove all references to function-like macros that are alone on a line, have

View File

@ -1,4 +1,4 @@
This page explains how to set Crow up for use with your project (***For versions 0.3+2 and lower***).
This page explains how to set Crow up for use with your project (***For versions 0.3+4 and lower***).
##Requirements
@ -34,7 +34,7 @@ Use your package manager to install the following:
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.
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.
##Includes folder
1. Copy the `/includes` folder to your project's root folder.
@ -126,7 +126,7 @@ cd build
cmake ..
make
```
Running Cmake will create `crow_all.h` file and place it in the build directory.<br>
Running CMake will create `crow_all.h` file and place it in the build directory.<br>
You can run tests with following command:
```

View File

@ -32,14 +32,20 @@ You can also download the `crow_all.h` file and simply include that into your pr
<br><br>
### Installing from source
#### Using CMake
1. Download Crow's source code (Either through github's UI or by using<br> `git clone https://github.com/CrowCpp/Crow.git`).
1. Download Crow's source code (Either through Github's UI or by using<br> `git clone https://github.com/CrowCpp/Crow.git`).
2. Run `mkdir build` inside of crow's source directory.
3. Navigate to the new "build" directory and run the following:<br>
`cmake .. -DCROW_BUILD_EXAMPLES=OFF -DCROW_BUILD_TESTS=OFF`
4. Run `make install`.
!!!note
!!! note
You can ignore `-DCROW_BUILD_EXAMPLES=OFF -DCROW_BUILD_TESTS=OFF` if you want to build the Examples and Unit Tests.
!!! note
You can uninstall Crow at a later time using `make uninstall`.
<br>
#### Manually
Crow can be installed manually on your Linux computer.
@ -53,13 +59,15 @@ Crow can be installed manually on your Linux computer.
Copy Crow's `include` directory to the `/usr/local/include` directory.
##### Single header (crow_all.h)
!!!warning
!!! warning
`crow_all.h` is recommended only for small, possibly single source file projects, and ideally should not be installed on your system.
navigate to the `scripts` directory and run `./merge_all.py ../include crow_all.h`. This will generate a `crow_all.h` file that you can use in your projects.
!!!note
!!! note
You can also include or exclude middlewares from your `crow_all.h` by using `-i` or `-e` followed by the middleware header file names separated by a comma (e.g. `merge_all.py ../include crow_all.h -e cookie_parser` to exclude the cookie parser middleware).
## Compiling your project
### Using CMake
In order to get your CMake project to work with Crow, all you need are the following lines in your CMakeLists.txt:
@ -74,6 +82,6 @@ All you need to do is run the following command:
g++ main.cpp -lpthread
```
You can use arguments like `-DCROW_ENABLE_DEBUG`, `-DCROW_ENABLE_COMPRESSION -lz` for HTTP Compression, or `-DCROW_ENABLE_SSL -lssl` for HTTPS support, or even replace g++ with clang++.
!!!warning
!!! warning
If you're using a version of boost prior to 1.69, you'll need to add the argument `-lboost_system` in order for you Crow application to compile correctly.

View File

@ -16,7 +16,7 @@ You can generate your own single header file by navigating to the `scripts` fold
python3 merge_all.py ../include crow_all.h
```
This will generate a `crow_all.h` file which you can use in the following steps
!!!warning
!!! warning
`crow_all.h` is recommended only for small, possibly single source file projects. For larger projects, it is advised to use the multi-header version.
@ -44,7 +44,7 @@ This will generate a `crow_all.h` file which you can use in the following steps
## Building Crow's tests/examples
!!!note
!!! note
This tutorial can be used for Crow projects built with CMake as well
@ -56,20 +56,20 @@ This will generate a `crow_all.h` file which you can use in the following steps
2. `cd build`
3. `cmake ..`
4. `make -j12`
!!!note
!!! note
You can add options like `-DCROW_ENABLE_SSL`, `-DCROW_ENABLE_COMPRESSION`, or `-DCROW_AMALGAMATE` to `3.c` to build their tests/examples.
You can add options like `-DCROW_ENABLE_SSL`, `-DCROW_ENABLE_COMPRESSION`, or `-DCROW_AMALGAMATE` to `cmake ..` to build their tests/examples.
## Compiling using a compiler directly
All you need to do is run the following command:
```
g++ main.cpp -lpthread
```
!!!note
!!! note
You'll need to install GCC via `brew install gcc`. the Clang compiler should be part of Xcode or Xcode command line tools.
You'll need to install GCC via `brew install gcc`. the Clang compiler should be part of XCode or XCode command line tools.
You can use arguments like `-DCROW_ENABLE_DEBUG`, `-DCROW_ENABLE_COMPRESSION -lz` for HTTP Compression, or `-DCROW_ENABLE_SSL -lssl` for HTTPS support, or even replace g++ with clang++.
!!!warning
!!! warning
If you're using a version of boost prior to 1.69, you'll need to add the argument `-lboost_system` in order for you Crow application to compile correctly.

7
docs/guides/CORS.md Normal file
View File

@ -0,0 +1,7 @@
Crow Allows a developer to set CORS policies by using the `CORSHandler` middleware.<br><br>
This middleware can be added to the app simply by defining a `#!cpp crow::App<crow::CORSHandler>`. This will use the default CORS rules globally<br><br>
The CORS rules can be modified by first getting the middleware via `#!cpp auto& cors = app.get_middleware<crow::CORSHandler>();`. The rules can be set per URL prefix using `prefix()`, per blueprint using `blueprint()`, or globally via `global()`. These will return a `CORSRules` object which contains the actual rules for the prefix, blueprint, or application. For more details go [here](../../reference/structcrow_1_1_c_o_r_s_handler.html).
`CORSRules` can be modified using the methods `origin()`, `methods()`, `headers()`, `max_age()`, `allow_credentials()`, or `ignore()`. For more details on these methods and what default values they take go [here](../../reference/structcrow_1_1_c_o_r_s_rules.html).

View File

@ -1,5 +1,5 @@
A Crow app defines an interface to allow the developer access to all the different parts of the framework, without having to manually deal with each one.<br><br>
An app allows access to the http server (for handling connections), router (for handling URLs and requests), Middlewares (for extending Crow), among many others.<br><br>
An app allows access to the HTTP server (for handling connections), router (for handling URLs and requests), Middlewares (for extending Crow), among many others.<br><br>
Crow has 2 different app types:
@ -23,6 +23,11 @@ app.bindaddr(192.168.1.2)
.multithreaded()
.run();
```
!!! note
The `run()` method is blocking. To run a Crow app asynchronously `run_async()` should be used instead.
<br><br>
For more info on middlewares, check out [this page](../middleware).<br><br>

View File

@ -11,7 +11,7 @@ Every way boils down to the same basic flow:
For the purposes of this tutorial, we will assume that the verification function is defined as `#!cpp bool verify(crow::request req, crow::response res)`
## Basic Auth
Basic HTTP authentication requires the client to send the Username and Password as a single string, separated by a colon (':') and then encoded as base64. This data needs to be placed in the `Authorization` header of the request. A sample header using the credentials "Username" and "Password" would look like this: `Authorization: Basic VXNlcm5hbWU6UGFzc3dvcmQ=`.<br><br>
Basic HTTP authentication requires the client to send the Username and Password as a single string, separated by a colon (':') and then encoded as Base64. This data needs to be placed in the `Authorization` header of the request. A sample header using the credentials "Username" and "Password" would look like this: `Authorization: Basic VXNlcm5hbWU6UGFzc3dvcmQ=`.<br><br>
We don't need to worry about creating the request, we only need to extract the credentials from the `Authorization` header and verify them.
!!! note
@ -47,7 +47,7 @@ return true; //or false if the username/password are invalid
Tokens are some form of unique data that a server can provide to a client in order to verify the client's identity later. While on the surface level they don't provide more security than a strong password, they are designed to be less valuable by being *temporary* and providing *limited access*. Variables like expiration time and access scopes are heavily reliant on the implementation however.<br><br>
### Access Tokens
The kind of the token itself can vary depending on the implementation and project requirements: Many services use randomly generated strings as tokens. Then compare them against a database to retrieve the associated user data. Some services however prefer using data bearing tokens. One example of the latter kind is JWT, which uses JSON strings encoded in base64 and signed using a private key or an agreed upon secret. While this has the added hassle of signing the token to ensure that it's not been tampered with. It does allow for the client to issue tokens without ever needing to present a password or contact a server. The server would simply be able to verify the signature using the client's public key or secret.<br><br>
The kind of the token itself can vary depending on the implementation and project requirements: Many services use randomly generated strings as tokens. Then compare them against a database to retrieve the associated user data. Some services however prefer using data bearing tokens. One example of the latter kind is JWT, which uses JSON strings encoded in Base64 and signed using a private key or an agreed upon secret. While this has the added hassle of signing the token to ensure that it's not been tampered with. It does allow for the client to issue tokens without ever needing to present a password or contact a server. The server would simply be able to verify the signature using the client's public key or secret.<br><br>
### Using an Access Token
Authenticating with an access token usually involves 2 stages: The first being acquiring the access token from an authority (either by providing credentials such as a username and a password to a server or generating a signed token). The scope of the token (what kind of information it can read or change) is usually defined in this step.<br><br>

8
docs/guides/base64.md Normal file
View File

@ -0,0 +1,8 @@
## Encoding
Using `#!cpp crow::utility::base64encode(mystring, mystring.size())` will return a Base64 encoded string. For URL safe Base64 `#!cpp crow::utility::base64encode_urlsafe(mystring, mystring.size())` can be used. The key used in the encoding process can be changed, it is a string containing all 64 characters to be used.
## Decoding
**Introduced in: `master`**<br><br>
Using `#!cpp crow::utility::base64decode(mystring, mystring.size())` with `mystring` being a Base64 encoded string will return a plain-text string. The function works with both normal and URL safe Base64. However it cannot decode a Base64 string encoded with a custom key.

View File

@ -1,4 +1,4 @@
!!!Warning
!!! Warning
This feature is currently only available on the "master" branch.
@ -16,7 +16,7 @@ You can define routes in a blueprint, similarly to how `#!cpp CROW_ROUTE(app, "/
### 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, turning a route such as `/crow/rocks` into `/prefix/crow/rocks`.
!!!Warning
!!! Warning
Unlike routes, blueprint prefixes should contain no slashes.
@ -24,7 +24,7 @@ Blueprints can have a prefix assigned to them. This can be done when creating a
### 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
!!! 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`.
@ -32,7 +32,7 @@ Blueprints let you define a custom static directory (relative to your working di
### 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
!!! 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");`.

View File

@ -25,13 +25,19 @@ 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>
!!!note
!!! note
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 `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>
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.
Additionally, a `wvalue` can be initialized as an object using an initializer list, an example object would be `wvalue x = {{"a", 1}, {"b", 2}}`. Or as a list using `wvalue x = json::wvalue::list({1, 2, 3})`, lists can include any type that `wvalue` supports.
!!! warning
JSON does not allow floating point values like `NaN` or `INF`, Crow will output `null` instead of `NaN` or `INF` when converting `wvalue` to a string. (`{"Key": NaN}` becomes `{"Key": null}`) (master and later)
<br><br>
Additionally, a `wvalue` can be initialized as an object using an initializer list, an example object would be `wvalue x = {{"a", 1}, {"b", 2}}`. Or as a list using `wvalue x = json::wvalue::list({1, 2, 3})`, lists can include any type that `wvalue` supports.<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>
@ -39,6 +45,6 @@ A JSON `wvalue` can be returned directly inside a route handler, this will cause
For more info on write values go [here](../../reference/classcrow_1_1json_1_1wvalue.html).
!!!note
!!! 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,5 +1,9 @@
Crow comes with a simple and easy to use logging system.<br><br>
!!! note
Currently Crow's Logger is not linked to the Crow application, meaning if an executable has more than one Crow application they'll be sharing any variables or classes relating to Logging.
## Setting up logging level
You can set up the level at which crow displays logs by using the app's `loglevel(crow::LogLevel)` method.<br><br>
@ -22,7 +26,13 @@ To set a logLevel, just use `#!cpp app.loglevel(crow::LogLevel::Warning)`, This
## Writing a log
Writing a log is as simple as `#!cpp CROW_LOG_<LOG LEVEL> << "Hello";` (replace&lt;LOG LEVEL&gt; with the actual level in all caps, so you have `CROW_LOG_WARNING`).
!!! note
Log times are reported in GMT timezone by default. This is because HTTP requires all reported times for requests and responses to be in GMT. This can be changed by using the macro `CROW_USE_LOCALTIMEZONE` which will set **only the log timezone** to the server's local timezone.
## Creating A custom logger
**Introduced in: `master`**<br><br>
Assuming you have an existing logger or Crow's default format just doesn't work for you. Crow allows you to use a custom logger for any log made using the `CROW_LOG_<LOG LEVEL>` macro.<br>
All you need is a class extending `#!cpp crow::ILogHandler` containing the method `#!cpp void log(std::string, crow::LogLevel)`.<br>
Once you have your custom logger, you need to set it via `#!cpp crow::logger::setHandler(&MyLogger);`. Here's a full example:<br>

View File

@ -1,9 +1,11 @@
**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>
It is typically used either in HTML forms, or when uploading multiple files.<br><br>
## How multipart messages work
The structure of a multipart request is typically consistent of:<br>
- A Header: Typically `multipart/form-data;boundary=<boundary>`, This defines the HTTP message as being multipart, as well as defining the separator used to distinguish the different parts.<br>
@ -13,10 +15,16 @@ The structure of a multipart request is typically consistent of:<br>
- Value
- `--<boundary>--`<br><br>
## Multipart messages in Crow
Crow supports multipart requests and responses though `crow::multipart::message`.<br>
A message can be created either by defining the headers, boundary, and individual parts and using them to create the message. or simply by reading a `crow::request`.<br><br>
Once a multipart message has been made, the individual parts can be accessed throughout `mpmes.parts`, `parts` is an `std::vector`, so accessing the individual parts should be straightforward.<br>
In order to access the individual part's name or filename, something like `#!cpp mpmes.parts[0].headers[0].params["name"]` sould do the trick.<br><br>
Once a multipart message has been made, the individual parts can be accessed throughout `msg.parts`, `parts` is an `std::vector`.<br><br>
**Introduced in: `master`**<br><br>
Part headers are organized in a similar way to request and response headers, and can be retrieved via `crow::multipart::get_header_object("header-key")`. This function returns a `crow::multipart::header` object.<br><br>
The message's individual body parts can be accessed by name using `msg.get_part_by_name("part-name")`.<br><br>
For more info on Multipart messages, go [here](../../reference/namespacecrow_1_1multipart.html)

View File

@ -10,7 +10,7 @@ We advise that you set crow up behind some form of reverse proxy if you plan on
## Apache2
Assuming you have both Apache2 and the modules [proxy](https://httpd.apache.org/docs/2.4/mod/mod_proxy.html), [proxy_http](https://httpd.apache.org/docs/2.4/mod/mod_proxy_http.html), [proxy_html](https://httpd.apache.org/docs/2.4/mod/mod_proxy_html.html) (if you plan on serving html pages), and [proxy_wstunnel](https://httpd.apache.org/docs/2.4/mod/mod_proxy_wstunnel.html) (if you plan on using websockets). You will need to enable those modules, which you can do using the following commands:
Assuming you have both Apache2 and the modules [proxy](https://httpd.apache.org/docs/2.4/mod/mod_proxy.html), [proxy_http](https://httpd.apache.org/docs/2.4/mod/mod_proxy_http.html), [proxy_html](https://httpd.apache.org/docs/2.4/mod/mod_proxy_html.html) (if you plan on serving HTML pages), and [proxy_wstunnel](https://httpd.apache.org/docs/2.4/mod/mod_proxy_wstunnel.html) (if you plan on using websockets). You will need to enable those modules, which you can do using the following commands:
```sh
a2enmod proxy

View File

@ -1,4 +1,4 @@
A query string is the part of the url that comes after a `?` character, it is usually formatted as `key=value&otherkey=othervalue`.
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>
@ -12,7 +12,7 @@ Works the same as `get`, but removes the returned value.
`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>
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)

View File

@ -2,7 +2,7 @@ Routes define what happens when your client connects to a certain URL.<br>
## Macro
`CROW_ROUTE(app, url)`<br>
Can be replaced with `#!cpp app.route<crow::black_magick::get_parameter_tag(url)>(url)` or `#!cpp app.route_dynamic(url)` if you're using VS2013 or want runtime url evaluation. Although this usage is **NOT** recommended.
Can be replaced with `#!cpp app.route<crow::black_magick::get_parameter_tag(url)>(url)` or `#!cpp app.route_dynamic(url)` if you're using VS2013 or want runtime URL evaluation. Although this usage is **NOT** recommended.
## App
Which app class to assign the route to.
## Path (URL)
@ -33,7 +33,7 @@ Basically a piece of code that gets executed whenever the client calls the assoc
### Request
Handlers can also use information from the request by adding it as a parameter `#!cpp ([](const crow::request& req){...})`.<br><br>
You can also access the url parameters in the handler using `#!cpp req.url_params.get("param_name");`. If the parameter doesn't exist, `nullptr` is returned.<br><br>
You can also access the URL parameters in the handler using `#!cpp req.url_params.get("param_name");`. If the parameter doesn't exist, `nullptr` is returned.<br><br>
For more information on `crow::request` go [here](../../reference/structcrow_1_1request.html).<br><br>
@ -82,6 +82,6 @@ Instead of assigning a response code, you can use the `crow::status` enum, for e
## 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.
!!!note
!!! note
For versions higher than 0.3 (excluding patches), Catchall routes handle 404 and 405 responses. The default response will contain the code 404 or 405.

View File

@ -6,10 +6,19 @@ Crow supports returning Static files as responses in 2 ways.
## Implicit
Crow implicitly returns any static files placed in a `static` directory and any subdirectories, as long as the user calls the endpoint `/static/path/to/file`.<br><br>
The static folder or endpoint can be changed by defining the macros `CROW_STATIC_DIRECTORY "alternative_directory/"` and `CROW_STATIC_ENDPOINT "/alternative_endpoint/<path>"`.<br>
static directory changes the directory in the server's filesystem, while the endpoint changes the URL that the client needs to access.
static directory changes the directory in the server's file system, while the endpoint changes the URL that the client needs to access.
## Explicit
You can directly return a static file by using the `crow::response` method `#!cpp response.set_static_file_info("path/to/file");`. The path is relative to the executable unless preceded by `/`, then it is an absolute path.<br>
Please keep in mind that using the `set_static_file_info` method does invalidate any data already in your response body.<br><br>
You can directly return a static file by using the `crow::response` method `#!cpp response.set_static_file_info("path/to/file");`. The path is relative to the working directory.
**Note**: Crow sets the `content-type` header automatically based on the file's extension, if an extension is unavailable or undefined, Crow uses `text/plain`, if you'd like to explicitly set a `content-type`, use `#!cpp response.set_header("content-type", "mime/type");` **AFTER** calling `set_static_file_info`.
!!! Warning
The path to the file is sanitized by default. it should be fine for most circumstances but if you know what you're doing and need the sanitizer off you can use `#!cpp response.set_static_file_info_unsafe("path/to/file")` instead.
!!! note
Crow sets the `content-type` header automatically based on the file's extension, if an extension is unavailable or undefined, Crow uses `text/plain`, if you'd like to explicitly set a `content-type`, use `#!cpp response.set_header("content-type", "mime/type");` **AFTER** calling `set_static_file_info`.
!!! note
Please keep in mind that using the `set_static_file_info` method means any data already in your response body is ignored and not sent to the client.

View File

@ -1,7 +1,11 @@
Templating is when you return an html page with custom data. You can probably tell why that's useful.<br><br>
Templating is when you return an HTML page with custom data. You can probably tell why that's useful.<br><br>
Crow supports [mustache](http://mustache.github.io) for templates through its own implementation `crow::mustache`.<br><br>
!!! note
Currently Crow's Mustache implementation is not linked to the Crow application, meaning if an executable has more than one Crow application they'll be sharing any variables or classes relating to template loading and compiling.
## Components of mustache
There are 2 components of a mustache template implementation:
@ -12,6 +16,8 @@ There are 2 components of a mustache template implementation:
### Page
The HTML page (including the mustache tags). It is usually loaded into `crow::mustache::template_t`. It needs to be placed in the *templates directory* which should be directly inside the current working directory of the crow executable.<br><br>
The templates directory is usually called `templates`, but can be adjusted per Route (via `crow::mustache::set_base("new_templates_directory")`), per [Blueprint](../blueprints), or globally (via `crow::mustache::set_global_base("new_templates_directory"")`).<br><br>
For more information on how to formulate a template, see [this mustache manual](http://mustache.github.io/mustache.5.html).
### Context
@ -21,13 +27,26 @@ A JSON object containing the tags as keys and their values. `crow::mustache::con
`crow::mustache::context` can take a C++ lambda as a value. The lambda needs to take a string as an argument and return a string, such as `#!cpp ctx[lmd] = [&](std::string){return "Hello World";};`.
!!! note
The string returned by the lamdba can contain mustache tags, Crow will parse it as any normal template string.
## Returning a template
To return a mustache template, you need to load a page using `#!cpp auto page = crow::mustache::load("path/to/template.html");`, keep in mind that the path is relative to the templates directory.<br>
You also need to set up the context by using `#!cpp crow::mustache::context ctx;`. Then you need to assign the keys and values, this can be done the same way you assign values to a json write value (`ctx["key"] = value;`).<br>
To return a mustache template, you need to load a page using `#!cpp auto page = crow::mustache::load("path/to/template.html");`. Or just simply load a string using `#!cpp auto page = crow::mustache::compile("my mustache {{value}}");`. Keep in mind that the path is relative to the templates directory.
!!! note
You can also use `#!cpp auto page = crow::mustache::load_text("path/to/template.html");` if you want to load a template without mustache processing.
!!! Warning
The path to the template is sanitized by default. it should be fine for most circumstances but if you know what you're doing and need the sanitizer off you can use `#!cpp crow::mustache::load_unsafe()` instead.
<br>
You also need to set up the context by using `#!cpp crow::mustache::context ctx;`. Then you need to assign the keys and values, this can be done the same way you assign values to a JSON write value (`ctx["key"] = value;`).<br>
With your context and page ready, just `#!cpp return page.render(ctx);`. This will use the context data to return a filled template.<br>
Alternatively you could just render the page without a context using `#!cpp return page.render();`.
!!! note
`#!cpp page.render();` returns a crow::returnable class in order to set the `Content-Type` header. to get a simple string, use `#!cpp page.render_string()` instead.

View File

@ -9,7 +9,7 @@ A websocket route follows the macro with `.websocket()` which is then followed b
By default, Crow allows Clients to send unmasked websocket messages, which is useful for debugging but goes against the protocol specification. Production Crow applications should enforce the protocol by adding `#!cpp #define CROW_ENFORCE_WS_SPEC` to their source code.
- `#!cpp onaccept([&](const crow::request&){handler code goes here})` (This handler has to return bool)
- `#!cpp onaccept([&](const crow::request&){handler code goes here})` (This handler has to return `bool`)
- `#!cpp onopen([&](crow::websocket::connection& conn){handler code goes here})`
- `#!cpp onmessage([&](crow::websocket::connection& conn, const std::string message, bool is_binary){handler code goes here})`
- `#!cpp onerror([&](crow::websocket::connection& conn){handler code goes here})`

View File

@ -83,6 +83,10 @@ add_executable(example_middleware example_middleware.cpp)
add_warnings_optimizations(example_middleware)
target_link_libraries(example_middleware PUBLIC Crow::Crow)
add_executable(example_cors middlewares/example_cors.cpp)
add_warnings_optimizations(example_cors)
target_link_libraries(example_cors PUBLIC Crow::Crow)
if(MSVC)
add_executable(example_vs example_vs.cpp)
add_warnings_optimizations(example_vs)

View File

@ -1,7 +1,6 @@
#include "crow.h"
#include "crow/middlewares/cors.h"
int main()
{
// Enable CORS

View File

@ -121,6 +121,7 @@ namespace crow
return *this;
}
/// Get the port that Crow will handle requests on
std::uint16_t port()
{
return port_;
@ -178,7 +179,7 @@ namespace crow
return *this;
}
/// Set a response body size (in bytes) beyond which Crow automatically streams responses (Default is 1MiB)
/// Set the response body size (in bytes) beyond which Crow automatically streams responses (Default is 1MiB)
///
/// Any streamed response is unaffected by Crow's timer, and therefore won't timeout before a response is fully sent.
@ -188,6 +189,7 @@ namespace crow
return *this;
}
/// Get the response body size (in bytes) beyond which Crow automatically streams responses
size_t& stream_threshold()
{
return res_stream_threshold_;
@ -328,6 +330,7 @@ namespace crow
}
}
/// Print the routing paths defined for each HTTP method
void debug_print()
{
CROW_LOG_DEBUG << "Routing:";

View File

@ -222,6 +222,7 @@ namespace crow
MAX
};
/// @cond SKIP
struct routing_params
{
std::vector<int64_t> int_params;
@ -273,6 +274,7 @@ namespace crow
{
return string_params[index];
}
/// @endcond
} // namespace crow
// clang-format off

View File

@ -7,26 +7,26 @@ namespace crow
{
struct CORSHandler;
// CORSRules is used for tuning cors policies
/// Used for tuning CORS policies
struct CORSRules
{
friend struct crow::CORSHandler;
// Set Access-Control-Allow-Origin. Default is "*"
/// Set Access-Control-Allow-Origin. Default is "*"
CORSRules& origin(const std::string& origin)
{
origin_ = origin;
return *this;
}
// Set Access-Control-Allow-Methods. Default is "*"
/// Set Access-Control-Allow-Methods. Default is "*"
CORSRules& methods(crow::HTTPMethod method)
{
add_list_item(methods_, crow::method_name(method));
return *this;
}
// Set Access-Control-Allow-Methods. Default is "*"
/// Set Access-Control-Allow-Methods. Default is "*"
template<typename... Methods>
CORSRules& methods(crow::HTTPMethod method, Methods... method_list)
{
@ -35,14 +35,14 @@ namespace crow
return *this;
}
// Set Access-Control-Allow-Headers. Default is "*"
/// Set Access-Control-Allow-Headers. Default is "*"
CORSRules& headers(const std::string& header)
{
add_list_item(headers_, header);
return *this;
}
// Set Access-Control-Allow-Headers. Default is "*"
/// Set Access-Control-Allow-Headers. Default is "*"
template<typename... Headers>
CORSRules& headers(const std::string& header, Headers... header_list)
{
@ -51,33 +51,33 @@ namespace crow
return *this;
}
// Set Access-Control-Max-Age. Default is none
/// Set Access-Control-Max-Age. Default is none
CORSRules& max_age(int max_age)
{
max_age_ = std::to_string(max_age);
return *this;
}
// Enable Access-Control-Allow-Credentials
/// Enable Access-Control-Allow-Credentials
CORSRules& allow_credentials()
{
allow_credentials_ = true;
return *this;
}
// Ignore CORS and don't send any headers
/// Ignore CORS and don't send any headers
void ignore()
{
ignore_ = true;
}
// Handle CORS on specific prefix path
/// Handle CORS on specific prefix path
CORSRules& prefix(const std::string& prefix);
// Handle CORS for specific blueprint
/// Handle CORS for specific blueprint
CORSRules& blueprint(const Blueprint& bp);
// Global CORS policy
/// Global CORS policy
CORSRules& global();
private:
@ -85,7 +85,7 @@ namespace crow
CORSRules(CORSHandler* handler):
handler_(handler) {}
// build comma separated list
/// build comma separated list
void add_list_item(std::string& list, const std::string& val)
{
if (list == "*") list = "";
@ -93,7 +93,7 @@ namespace crow
list += val;
}
// Set header `key` to `value` if it is not set
/// Set header `key` to `value` if it is not set
void set_header_no_override(const std::string& key, const std::string& value, crow::response& res)
{
if (value.size() == 0) return;
@ -101,7 +101,7 @@ namespace crow
res.add_header(key, value);
}
// Set response headers
/// Set response headers
void apply(crow::response& res)
{
if (ignore_) return;
@ -124,6 +124,7 @@ namespace crow
};
/// CORSHandler is a global middleware for setting CORS headers.
///
/// By default, it sets Access-Control-Allow-Origin/Methods/Headers to "*".
/// The default behaviour can be changed with the `global()` cors rule.
@ -142,21 +143,21 @@ namespace crow
rule.apply(res);
}
// Handle CORS on specific prefix path
/// Handle CORS on a specific prefix path
CORSRules& prefix(const std::string& prefix)
{
rules.emplace_back(prefix, CORSRules(this));
return rules.back().second;
}
// Handle CORS for specific blueprint
/// Handle CORS for a specific blueprint
CORSRules& blueprint(const Blueprint& bp)
{
rules.emplace_back(bp.prefix(), CORSRules(this));
return rules.back().second;
}
// Global CORS policy
/// Get the global CORS policy
CORSRules& global()
{
return default_;

View File

@ -272,6 +272,7 @@ namespace crow
class CatchallRule
{
public:
/// @cond SKIP
CatchallRule() {}
template<typename Func>
@ -349,7 +350,7 @@ namespace crow
handler_ = std::move(f);
}
/// @endcond
bool has_handler()
{
return (handler_ != nullptr);

View File

@ -22,6 +22,7 @@
namespace crow
{
/// @cond SKIP
namespace black_magic
{
#ifndef CROW_MSVC_WORKAROUND
@ -528,6 +529,7 @@ namespace crow
template<size_t i>
using arg = typename std::tuple_element<i, std::tuple<Args...>>::type;
};
/// @endcond
inline static std::string base64encode(const unsigned char* data, size_t size, const char* key = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/")
{

View File

@ -52,9 +52,11 @@ nav:
- Blueprints: guides/blueprints.md
- Compression: guides/compression.md
- Websockets: guides/websockets.md
- Base64: guides/base64.md
- Writing Tests: guides/testing.md
- Using Crow:
- HTTP Authorization: guides/auth.md
- CORS Setup: guides/CORS.md
- Server setup:
- Proxies: guides/proxies.md
- Systemd run on startup: guides/syste.md