Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 38 additions & 4 deletions docs/guides/static.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,51 @@
<span class="tag">[:octicons-feed-tag-16: v0.2](https://github.com/CrowCpp/Crow/releases/0.2)</span>


A static file is any file that resides in the server's storage.

Crow supports returning static files as responses either implicitly or explicitly.

## 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 file system, while the endpoint changes the URL that the client needs to access.
The static folder or endpoint can be changed by defining the macros :
```cpp
#define CROW_STATIC_DIRECTORY "alternative_directory/"
#define CROW_STATIC_ENDPOINT "/alternative_endpoint/<path>"
```
`CROW_STATIC_DIRECTORY` changes the directory in the server's file system, while `CROW_STATIC_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 working directory.
You can return a static file by using the `CROW_STATIC_FILE(<app>, <EndPoint>, <FilePath>)` macro.</br>
Or by using `app.static_file(<EndPoint>, <FilePath>)` function of Crow::App.</br>
The path is relative to the working directory.

However for a dedicated case, you can directly return a static file by using the `crow::response` and set the file path and mime-type by `#!cpp response.set_static_file_info(<FilePath>,<mime-type>)`.

### Example

```cpp
auto app = crow::SimpleApp(); // or crow::App()

// by Macro
CROW_STATIC_FILE(app, "/" , "home.html");
CROW_STATIC_FILE(app, "/home.html" , "home.html");

// by Function
app.static_file("/favicon.ico", "images/home.png");
app.static_file("/style.css", "style.css");

// Explicit route to add more information
CROW_ROUTE(app, "/customDataType.xyz")
([](const crow::request&, crow::response& res) {
res.set_static_file_info(
"data/customType.xyz",
"application/octet-stream"
);
res.end();
});
```


## Notes

!!! Warning

Expand Down
43 changes: 43 additions & 0 deletions include/crow/app.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,21 @@
*/
#define CROW_ROUTE(app, url) app.template route<crow::black_magic::get_parameter_tag(url)>(url)

/**
* \def CROW_STATIC_FILE(app, url, internalPath)
* \brief Creates a static route for app for given url to internalPath.
*
*
* ```cpp
* auto app = crow::SimpleApp(); // or crow::App()
* CROW_STATIC_FILE(app, "/home", "home.html");
* CROW_STATIC_FILE(app, "/favicon.ico", "favicon.png");
* ```
*
*/
#define CROW_STATIC_FILE(app, url, internalPath) app.static_file(url, internalPath)


/**
* \def CROW_BP_ROUTE(blueprint, url)
* \brief Creates a route for a blueprint using a rule.
Expand Down Expand Up @@ -261,6 +276,34 @@ namespace crow
return router_.new_rule_tagged<Tag>(rule);
}

/// \brief Create a static route to given url
///
/// \param url public URL
/// \return The rule
///
StaticRule& route_static(const std::string& url)
{
return router_.new_rule<StaticRule>(url);
}

/// \brief Creates a static route for given url to internalPath.
///
/// \param url public URL
/// \param internalPath internal path to reach te file
/// \return The rule
///
StaticRule& static_file(std::string_view url, std::string_view internalPath){
StaticRule& rt = route_static(std::string(url));

// make a copy of given view of internalPath
rt([=,localFile=std::string(internalPath)](crow::response& resp) -> void {
resp.set_static_file_info(localFile);
resp.end();
});

return rt;
}

/// \brief Create a route for any requests without a proper route (**Use CROW_CATCHALL_ROUTE instead**)
CatchallRule& catchall_route()
{
Expand Down
8 changes: 8 additions & 0 deletions include/crow/routing.h
Original file line number Diff line number Diff line change
Expand Up @@ -719,6 +719,8 @@ namespace crow // NOTE: Already documented in "crow/app.h"
std::function<void(crow::request&, crow::response&, Args...)> handler_;
};

using StaticRule = TaggedRule<>;

constexpr size_t RULE_SPECIAL_REDIRECT_SLASH = 1;

/// A search tree.
Expand Down Expand Up @@ -1285,6 +1287,12 @@ namespace crow // NOTE: Already documented in "crow/app.h"
{
using RuleT = typename black_magic::arguments<N>::type::template rebind<TaggedRule>;

return new_rule<RuleT>(rule);
}

template<typename RuleT=StaticRule>
auto& new_rule(const std::string& rule)
{
auto ruleObject = new RuleT(rule);
all_rules_.emplace_back(ruleObject);

Expand Down
26 changes: 8 additions & 18 deletions tests/unittest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1833,30 +1833,20 @@ TEST_CASE("send_file")

SimpleApp app;

CROW_ROUTE(app, "/jpg")
([](const crow::request&, crow::response& res) {
res.set_static_file_info("tests/img/cat.jpg");
res.end();
});

CROW_ROUTE(app, "/jpg2")
([](const crow::request&, crow::response& res) {
res.set_static_file_info(
"tests/img/cat2.jpg"); // This file is nonexistent on purpose
res.end();
});
CROW_STATIC_FILE(app, "/jpg", "tests/img/cat.jpg");
CROW_STATIC_FILE(app, "/jpg2", "tests/img/cat2.jpg"); // This file is nonexistent on purpose

// Explicit route to add more informations
CROW_ROUTE(app, "/jpg3")
([](const crow::request&, crow::response& res) {
res.set_static_file_info("tests/img/cat.jpg", "application/octet-stream"); // Set Content-Type explicitly
res.set_static_file_info(
"tests/img/cat.jpg",
"application/octet-stream"); // Set Content-Type explicitly
res.end();
});

CROW_ROUTE(app, "/filewith.badext")
([](const crow::request&, crow::response& res) {
res.set_static_file_info("tests/img/filewith.badext");
res.end();
});
// Bad Extension test
CROW_STATIC_FILE(app, "/filewith.badext", "tests/img/filewith.badext");

app.validate();

Expand Down
Loading