diff --git a/docs/guides/templating.md b/docs/guides/templating.md
index cdf1952b3..47e54be3a 100644
--- a/docs/guides/templating.md
+++ b/docs/guides/templating.md
@@ -26,3 +26,8 @@ To return a mustache template, you need to load a page using `#!cpp auto page =
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;`).
With your context and page ready, just `#!cpp return page.render(ctx);`. This will use the context data to return a filled template.
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.
+
diff --git a/include/crow/mustache.h b/include/crow/mustache.h
index 866d8dc6c..e69be72e6 100644
--- a/include/crow/mustache.h
+++ b/include/crow/mustache.h
@@ -6,6 +6,7 @@
#include
#include "crow/json.h"
#include "crow/logging.h"
+#include "crow/returnable.h"
#include "crow/utility.h"
namespace crow
@@ -29,6 +30,22 @@ namespace crow
std::string msg;
};
+ struct rendered_template : returnable
+ {
+ rendered_template():
+ returnable("text/html") {}
+
+ rendered_template(std::string& body):
+ returnable("text/html"), body_(std::move(body)) {}
+
+ std::string body_;
+
+ std::string dump() const override
+ {
+ return body_;
+ }
+ };
+
enum class ActionType
{
Ignore,
@@ -231,7 +248,7 @@ namespace crow
while (execute_result.find("{{") != std::string::npos)
{
template_t result_plug(execute_result);
- execute_result = result_plug.render(*(stack[0]));
+ execute_result = result_plug.render_string(*(stack[0]));
}
if (action.t == ActionType::Tag)
@@ -339,7 +356,31 @@ namespace crow
}
public:
- std::string render() const
+ /// Output a returnable template from this mustache template
+ rendered_template render() const
+ {
+ context empty_ctx;
+ std::vector stack;
+ stack.emplace_back(&empty_ctx);
+
+ std::string ret;
+ render_internal(0, fragments_.size() - 1, stack, ret, 0);
+ return rendered_template(ret);
+ }
+
+ /// Apply the values from the context provided and output a returnable template from this mustache template
+ rendered_template render(context& ctx) const
+ {
+ std::vector stack;
+ stack.emplace_back(&ctx);
+
+ std::string ret;
+ render_internal(0, fragments_.size() - 1, stack, ret, 0);
+ return rendered_template(ret);
+ }
+
+ /// Output a returnable template from this mustache template
+ std::string render_string() const
{
context empty_ctx;
std::vector stack;
@@ -349,7 +390,9 @@ namespace crow
render_internal(0, fragments_.size() - 1, stack, ret, 0);
return ret;
}
- std::string render(context& ctx) const
+
+ /// Apply the values from the context provided and output a returnable template from this mustache template
+ std::string render_string(context& ctx) const
{
std::vector stack;
stack.emplace_back(&ctx);
diff --git a/tests/template/mustachetest.cpp b/tests/template/mustachetest.cpp
index 5a347a712..2701be2c9 100644
--- a/tests/template/mustachetest.cpp
+++ b/tests/template/mustachetest.cpp
@@ -29,6 +29,6 @@ int main()
return "";
});
context ctx(data);
- cout << templ.render(ctx);
+ cout << templ.render_string(ctx);
return 0;
}
diff --git a/tests/unittest.cpp b/tests/unittest.cpp
index e74761c78..e8d6c1b3c 100644
--- a/tests/unittest.cpp
+++ b/tests/unittest.cpp
@@ -1136,7 +1136,7 @@ TEST_CASE("template_basic")
auto t = crow::mustache::compile(R"---(attack of {{name}})---");
crow::mustache::context ctx;
ctx["name"] = "killer tomatoes";
- auto result = t.render(ctx);
+ auto result = t.render_string(ctx);
CHECK("attack of killer tomatoes" == result);
} // template_basic
@@ -1148,7 +1148,7 @@ TEST_CASE("template_function")
ctx["func"] = [&](std::string) {
return std::string("{{name}}, IN SPACE!");
};
- auto result = t.render(ctx);
+ auto result = t.render_string(ctx);
CHECK("attack of killer tomatoes, IN SPACE!" == result);
}
@@ -1159,11 +1159,38 @@ TEST_CASE("template_load")
auto t = crow::mustache::load("test.mustache");
crow::mustache::context ctx;
ctx["name"] = "killer tomatoes";
- auto result = t.render(ctx);
+ auto result = t.render_string(ctx);
CHECK("attack of killer tomatoes" == result);
unlink("test.mustache");
} // template_load
+TEST_CASE("TemplateRouting")
+{
+ SimpleApp app;
+
+ CROW_ROUTE(app, "/temp")
+ ([] {
+ auto t = crow::mustache::compile(R"---(attack of {{name}})---");
+ crow::mustache::context ctx;
+ ctx["name"] = "killer tomatoes";
+ return crow::response(t.render(ctx));
+ });
+
+ app.validate();
+
+ {
+ request req;
+ response res;
+
+ req.url = "/temp";
+
+ app.handle(req, res);
+
+ CHECK("attack of killer tomatoes" == res.body);
+ CHECK("text/html" == crow::get_header_value(res.headers, "Content-Type"));
+ }
+} // PathRouting
+
TEST_CASE("black_magic")
{
using namespace black_magic;