aboutsummaryrefslogtreecommitdiff
path: root/lib/crow/examples
diff options
context:
space:
mode:
Diffstat (limited to 'lib/crow/examples')
-rw-r--r--lib/crow/examples/CMakeLists.txt63
-rw-r--r--lib/crow/examples/example.cpp173
-rw-r--r--lib/crow/examples/example.py19
-rw-r--r--lib/crow/examples/example_chat.cpp91
-rw-r--r--lib/crow/examples/example_chat.html54
-rw-r--r--lib/crow/examples/example_test.py44
-rw-r--r--lib/crow/examples/example_vs.cpp131
-rw-r--r--lib/crow/examples/example_with_all.cpp94
-rw-r--r--lib/crow/examples/helloworld.cpp13
-rw-r--r--lib/crow/examples/ssl/example_ssl.cpp27
-rw-r--r--lib/crow/examples/websocket/example_ws.cpp48
-rw-r--r--lib/crow/examples/websocket/templates/ws.html42
12 files changed, 799 insertions, 0 deletions
diff --git a/lib/crow/examples/CMakeLists.txt b/lib/crow/examples/CMakeLists.txt
new file mode 100644
index 0000000..efb4acc
--- /dev/null
+++ b/lib/crow/examples/CMakeLists.txt
@@ -0,0 +1,63 @@
+cmake_minimum_required(VERSION 2.8)
+project (crow_examples)
+
+if (MSVC)
+ add_executable(example_vs example_vs.cpp)
+ target_link_libraries(example_vs ${Boost_LIBRARIES})
+ target_link_libraries(example_vs ${CMAKE_THREAD_LIBS_INIT})
+else ()
+ add_executable(helloworld helloworld.cpp)
+ target_link_libraries(helloworld ${Boost_LIBRARIES})
+ target_link_libraries(helloworld ${CMAKE_THREAD_LIBS_INIT})
+
+if (OPENSSL_FOUND)
+ add_executable(example_ssl ssl/example_ssl.cpp)
+ target_link_libraries(example_ssl ${Boost_LIBRARIES})
+ target_link_libraries(example_ssl ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES})
+endif()
+
+add_executable(example_websocket websocket/example_ws.cpp)
+target_link_libraries(example_websocket ${Boost_LIBRARIES})
+target_link_libraries(example_websocket ${CMAKE_THREAD_LIBS_INIT} ${OPENSSL_LIBRARIES})
+add_custom_command(OUTPUT ws.html
+ COMMAND ${CMAKE_COMMAND} -E
+ copy ${PROJECT_SOURCE_DIR}/websocket/templates/ws.html ${CMAKE_CURRENT_BINARY_DIR}/templates/ws.html
+ DEPENDS ${PROJECT_SOURCE_DIR}/websocket/templates/ws.html
+)
+add_custom_target(example_ws_copy ALL DEPENDS ws.html)
+
+add_executable(example example.cpp)
+#target_link_libraries(example crow)
+target_link_libraries(example ${Boost_LIBRARIES})
+target_link_libraries(example ${CMAKE_THREAD_LIBS_INIT})
+
+if (Tcmalloc_FOUND)
+ target_link_libraries(example ${Tcmalloc_LIBRARIES})
+endif(Tcmalloc_FOUND)
+
+add_executable(example_with_all example_with_all.cpp)
+add_dependencies(example_with_all amalgamation)
+#target_link_libraries(example crow)
+target_link_libraries(example_with_all ${Boost_LIBRARIES})
+target_link_libraries(example_with_all ${CMAKE_THREAD_LIBS_INIT})
+
+add_custom_command(OUTPUT example_test.py
+ COMMAND ${CMAKE_COMMAND} -E
+ copy ${PROJECT_SOURCE_DIR}/example_test.py ${CMAKE_CURRENT_BINARY_DIR}/example_test.py
+ DEPENDS ${PROJECT_SOURCE_DIR}/example_test.py
+)
+add_custom_target(example_copy ALL DEPENDS example_test.py)
+
+add_executable(example_chat example_chat.cpp)
+target_link_libraries(example_chat ${Boost_LIBRARIES})
+target_link_libraries(example_chat ${CMAKE_THREAD_LIBS_INIT})
+add_custom_command(OUTPUT example_chat.html
+ COMMAND ${CMAKE_COMMAND} -E
+ copy ${PROJECT_SOURCE_DIR}/example_chat.html ${CMAKE_CURRENT_BINARY_DIR}/example_chat.html
+ DEPENDS ${PROJECT_SOURCE_DIR}/example_chat.html
+)
+add_custom_target(example_chat_copy ALL DEPENDS example_chat.html)
+
+#SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -pg" )
+#SET( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -g -pg" )
+endif()
diff --git a/lib/crow/examples/example.cpp b/lib/crow/examples/example.cpp
new file mode 100644
index 0000000..1355b03
--- /dev/null
+++ b/lib/crow/examples/example.cpp
@@ -0,0 +1,173 @@
+#include "crow.h"
+
+#include <sstream>
+
+class ExampleLogHandler : public crow::ILogHandler {
+ public:
+ void log(std::string /*message*/, crow::LogLevel /*level*/) override {
+// cerr << "ExampleLogHandler -> " << message;
+ }
+};
+
+struct ExampleMiddleware
+{
+ std::string message;
+
+ ExampleMiddleware()
+ {
+ message = "foo";
+ }
+
+ void setMessage(std::string newMsg)
+ {
+ message = newMsg;
+ }
+
+ struct context
+ {
+ };
+
+ void before_handle(crow::request& /*req*/, crow::response& /*res*/, context& /*ctx*/)
+ {
+ CROW_LOG_DEBUG << " - MESSAGE: " << message;
+ }
+
+ void after_handle(crow::request& /*req*/, crow::response& /*res*/, context& /*ctx*/)
+ {
+ // no-op
+ }
+};
+
+int main()
+{
+ crow::App<ExampleMiddleware> app;
+
+ app.get_middleware<ExampleMiddleware>().setMessage("hello");
+
+ CROW_ROUTE(app, "/")
+ .name("hello")
+ ([]{
+ return "Hello World!";
+ });
+
+ CROW_ROUTE(app, "/about")
+ ([](){
+ return "About Crow example.";
+ });
+
+ // a request to /path should be forwarded to /path/
+ CROW_ROUTE(app, "/path/")
+ ([](){
+ return "Trailing slash test case..";
+ });
+
+
+ // simple json response
+ // To see it in action enter {ip}:18080/json
+ CROW_ROUTE(app, "/json")
+ ([]{
+ crow::json::wvalue x;
+ x["message"] = "Hello, World!";
+ return x;
+ });
+
+ // To see it in action enter {ip}:18080/hello/{integer_between -2^32 and 100} and you should receive
+ // {integer_between -2^31 and 100} bottles of beer!
+ 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());
+ });
+
+ // To see it in action submit {ip}:18080/add/1/2 and you should receive 3 (exciting, isn't it)
+ CROW_ROUTE(app,"/add/<int>/<int>")
+ ([](const crow::request& /*req*/, crow::response& res, int a, int b){
+ std::ostringstream os;
+ os << a+b;
+ res.write(os.str());
+ res.end();
+ });
+
+ // Compile error with message "Handler type is mismatched with URL paramters"
+ //CROW_ROUTE(app,"/another/<int>")
+ //([](int a, int b){
+ //return crow::response(500);
+ //});
+
+ // more json example
+
+ // To see it in action, I recommend to use the Postman Chrome extension:
+ // * Set the address to {ip}:18080/add_json
+ // * Set the method to post
+ // * Select 'raw' and then JSON
+ // * Add {"a": 1, "b": 1}
+ // * Send and you should receive 2
+
+ // A simpler way for json example:
+ // * curl -d '{"a":1,"b":2}' {ip}:18080/add_json
+ 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()};
+ });
+
+ // Example of a request taking URL parameters
+ // If you want to activate all the functions just query
+ // {ip}:18080/params?foo='blabla'&pew=32&count[]=a&count[]=b
+ CROW_ROUTE(app, "/params")
+ ([](const crow::request& req){
+ std::ostringstream os;
+
+ // To get a simple string from the url params
+ // To see it in action /params?foo='blabla'
+ os << "Params: " << req.url_params << "\n\n";
+ os << "The key 'foo' was " << (req.url_params.get("foo") == nullptr ? "not " : "") << "found.\n";
+
+ // To get a double from the request
+ // To see in action submit something like '/params?pew=42'
+ if(req.url_params.get("pew") != nullptr) {
+ double countD = boost::lexical_cast<double>(req.url_params.get("pew"));
+ os << "The value of 'pew' is " << countD << '\n';
+ }
+
+ // To get a list from the request
+ // You have to submit something like '/params?count[]=a&count[]=b' to have a list with two values (a and b)
+ auto count = req.url_params.get_list("count");
+ os << "The key 'count' contains " << count.size() << " value(s).\n";
+ for(const auto& countVal : count) {
+ os << " - " << countVal << '\n';
+ }
+
+ // To get a dictionary from the request
+ // You have to submit something like '/params?mydict[a]=b&mydict[abcd]=42' to have a list of pairs ((a, b) and (abcd, 42))
+ auto mydict = req.url_params.get_dict("mydict");
+ os << "The key 'dict' contains " << mydict.size() << " value(s).\n";
+ for(const auto& mydictVal : mydict) {
+ os << " - " << mydictVal.first << " -> " << mydictVal.second << '\n';
+ }
+
+ return crow::response{os.str()};
+ });
+
+ CROW_ROUTE(app, "/large")
+ ([]{
+ return std::string(512*1024, ' ');
+ });
+
+ // enables all log
+ app.loglevel(crow::LogLevel::DEBUG);
+ //crow::logger::setHandler(std::make_shared<ExampleLogHandler>());
+
+ app.port(18080)
+ .multithreaded()
+ .run();
+}
diff --git a/lib/crow/examples/example.py b/lib/crow/examples/example.py
new file mode 100644
index 0000000..1fd8fcd
--- /dev/null
+++ b/lib/crow/examples/example.py
@@ -0,0 +1,19 @@
+from flask import Flask
+app = Flask(__name__)
+
+@app.route("/")
+def hello():
+ return "Hello World!"
+
+@app.route("/about/<path:path>/hello")
+def hello1(path):
+ return "about1"
+
+@app.route("/about")
+def hello2():
+ return "about2"
+
+print app.url_map
+
+if __name__ == "__main__":
+ app.run(host="0.0.0.0", port=8888)
diff --git a/lib/crow/examples/example_chat.cpp b/lib/crow/examples/example_chat.cpp
new file mode 100644
index 0000000..c510bb0
--- /dev/null
+++ b/lib/crow/examples/example_chat.cpp
@@ -0,0 +1,91 @@
+#include "crow.h"
+#include <string>
+#include <vector>
+#include <chrono>
+
+using namespace std;
+
+vector<string> msgs;
+vector<pair<crow::response*, decltype(chrono::steady_clock::now())>> ress;
+
+void broadcast(const string& msg)
+{
+ msgs.push_back(msg);
+ crow::json::wvalue x;
+ x["msgs"][0] = msgs.back();
+ x["last"] = msgs.size();
+ string body = crow::json::dump(x);
+ for(auto p : ress)
+ {
+ auto* res = p.first;
+ CROW_LOG_DEBUG << res << " replied: " << body;
+ res->end(body);
+ }
+ ress.clear();
+}
+// To see how it works go on {ip}:40080 but I just got it working with external build (not directly in IDE, I guess a problem with dependency)
+int main()
+{
+ crow::SimpleApp app;
+ crow::mustache::set_base(".");
+
+ CROW_ROUTE(app, "/")
+ ([]{
+ crow::mustache::context ctx;
+ return crow::mustache::load("example_chat.html").render();
+ });
+
+ CROW_ROUTE(app, "/logs")
+ ([]{
+ CROW_LOG_INFO << "logs requested";
+ crow::json::wvalue x;
+ int start = max(0, (int)msgs.size()-100);
+ for(int i = start; i < (int)msgs.size(); i++)
+ x["msgs"][i-start] = msgs[i];
+ x["last"] = msgs.size();
+ CROW_LOG_INFO << "logs completed";
+ return x;
+ });
+
+ CROW_ROUTE(app, "/logs/<int>")
+ ([](const crow::request& /*req*/, crow::response& res, int after){
+ CROW_LOG_INFO << "logs with last " << after;
+ if (after < (int)msgs.size())
+ {
+ crow::json::wvalue x;
+ for(int i = after; i < (int)msgs.size(); i ++)
+ x["msgs"][i-after] = msgs[i];
+ x["last"] = msgs.size();
+
+ res.write(crow::json::dump(x));
+ res.end();
+ }
+ else
+ {
+ vector<pair<crow::response*, decltype(chrono::steady_clock::now())>> filtered;
+ for(auto p : ress)
+ {
+ if (p.first->is_alive() && chrono::steady_clock::now() - p.second < chrono::seconds(30))
+ filtered.push_back(p);
+ else
+ p.first->end();
+ }
+ ress.swap(filtered);
+ ress.push_back({&res, chrono::steady_clock::now()});
+ CROW_LOG_DEBUG << &res << " stored " << ress.size();
+ }
+ });
+
+ CROW_ROUTE(app, "/send")
+ .methods("GET"_method, "POST"_method)
+ ([](const crow::request& req)
+ {
+ CROW_LOG_INFO << "msg from client: " << req.body;
+ broadcast(req.body);
+ return "";
+ });
+
+ app.port(40080)
+ //.multithreaded()
+ .run();
+}
diff --git a/lib/crow/examples/example_chat.html b/lib/crow/examples/example_chat.html
new file mode 100644
index 0000000..233e093
--- /dev/null
+++ b/lib/crow/examples/example_chat.html
@@ -0,0 +1,54 @@
+<html>
+<head>
+<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
+</head>
+<body>
+<input id="msg" type="text">
+<button id="send">Send</button>
+<div id="logs">
+</div>
+<script>
+$(document).ready(function(){
+ $("#send").click(function(){
+ var msg = $("#msg").val();
+ console.log(msg);
+ if (msg.length > 0)
+ $.post("/send", msg);
+ $("#msg").val("");
+ });
+ $("#msg").keyup(function(event){
+ if(event.keyCode == 13){
+ $("#send").click();
+ }
+ });
+ var lastLog = 0;
+ var updateLog;
+ updateLog = function(data)
+ {
+ console.log("recv ");
+ console.log(data);
+ var lastLog = data.last*1;
+ console.log("lastLog: " + lastLog);
+ var s = "";
+ function htmlEncode(s)
+ {
+ return s.replace(/&(?!\w+([;\s]|$))/g, "&amp;")
+ .replace(/</g, "&lt;").replace(/>/g, "&gt;");
+ }
+ for(var x in data.msgs)
+ {
+
+ s = htmlEncode(data.msgs[x]) + "<BR>" + s;
+ }
+ $("#logs").html(s+$("#logs").html());
+ var failFunction;
+ failFunction = function(){
+ $.getJSON("/logs/"+lastLog, updateLog).fail(failFunction);
+ };
+ $.getJSON("/logs/"+lastLog, updateLog).fail(failFunction);
+ }
+ $.getJSON("/logs", updateLog);
+});
+</script>
+</body>
+</html>
diff --git a/lib/crow/examples/example_test.py b/lib/crow/examples/example_test.py
new file mode 100644
index 0000000..d252df0
--- /dev/null
+++ b/lib/crow/examples/example_test.py
@@ -0,0 +1,44 @@
+import urllib
+assert "Hello World!" == urllib.urlopen('http://localhost:18080').read()
+assert "About Crow example." == urllib.urlopen('http://localhost:18080/about').read()
+assert 404 == urllib.urlopen('http://localhost:18080/list').getcode()
+assert "3 bottles of beer!" == urllib.urlopen('http://localhost:18080/hello/3').read()
+assert "100 bottles of beer!" == urllib.urlopen('http://localhost:18080/hello/100').read()
+assert 400 == urllib.urlopen('http://localhost:18080/hello/500').getcode()
+assert "3" == urllib.urlopen('http://localhost:18080/add_json', data='{"a":1,"b":2}').read()
+assert "3" == urllib.urlopen('http://localhost:18080/add/1/2').read()
+
+# test persistent connection
+import socket
+import time
+s = socket.socket()
+s.connect(('localhost', 18080))
+for i in xrange(10):
+ s.send('''GET / HTTP/1.1
+Host: localhost\r\n\r\n''');
+ assert 'Hello World!' in s.recv(1024)
+
+# test large
+s = socket.socket()
+s.connect(('localhost', 18080))
+s.send('''GET /large HTTP/1.1
+Host: localhost\r\nConnection: close\r\n\r\n''')
+r = ''
+while True:
+ d = s.recv(1024*1024)
+ if not d:
+ break;
+ r += d
+ print len(r), len(d)
+print len(r), r[:100]
+assert len(r) > 512*1024
+
+# test timeout
+s = socket.socket()
+s.connect(('localhost', 18080))
+# invalid request, connection will be closed after timeout
+s.send('''GET / HTTP/1.1
+hHhHHefhwjkefhklwejfklwejf
+''')
+print s.recv(1024)
+
diff --git a/lib/crow/examples/example_vs.cpp b/lib/crow/examples/example_vs.cpp
new file mode 100644
index 0000000..dbc4d31
--- /dev/null
+++ b/lib/crow/examples/example_vs.cpp
@@ -0,0 +1,131 @@
+#include "crow.h"
+
+#include <sstream>
+
+class ExampleLogHandler : public crow::ILogHandler {
+ public:
+ void log(std::string message, crow::LogLevel level) override {
+// cerr << "ExampleLogHandler -> " << message;
+ }
+};
+
+struct ExampleMiddleware
+{
+ std::string message;
+
+ ExampleMiddleware()
+ {
+ message = "foo";
+ }
+
+ void setMessage(std::string newMsg)
+ {
+ message = newMsg;
+ }
+
+ struct context
+ {
+ };
+
+ void before_handle(crow::request& req, crow::response& res, context& ctx)
+ {
+ CROW_LOG_DEBUG << " - MESSAGE: " << message;
+ }
+
+ void after_handle(crow::request& req, crow::response& res, context& ctx)
+ {
+ // no-op
+ }
+};
+
+int main()
+{
+ crow::App<ExampleMiddleware> app;
+
+ app.get_middleware<ExampleMiddleware>().setMessage("hello");
+
+ app.route_dynamic("/")
+ ([]{
+ return "Hello World!";
+ });
+
+ app.route_dynamic("/about")
+ ([](){
+ return "About Crow example.";
+ });
+
+ // a request to /path should be forwarded to /path/
+ app.route_dynamic("/path/")
+ ([](){
+ return "Trailing slash test case..";
+ });
+
+ // simple json response
+ app.route_dynamic("/json")
+ ([]{
+ crow::json::wvalue x;
+ x["message"] = "Hello, World!";
+ return x;
+ });
+
+ app.route_dynamic("/hello/<int>")
+ ([](int count){
+ if (count > 100)
+ return crow::response(400);
+ std::ostringstream os;
+ os << count << " bottles of beer!";
+ return crow::response(os.str());
+ });
+
+ app.route_dynamic("/add/<int>/<int>")
+ ([](const crow::request& req, crow::response& res, int a, int b){
+ std::ostringstream os;
+ os << a+b;
+ res.write(os.str());
+ res.end();
+ });
+
+ // Compile error with message "Handler type is mismatched with URL paramters"
+ //CROW_ROUTE(app,"/another/<int>")
+ //([](int a, int b){
+ //return crow::response(500);
+ //});
+
+ // more json example
+ app.route_dynamic("/add_json")
+ .methods(crow::HTTPMethod::POST)
+ ([](const crow::request& req){
+ auto x = crow::json::load(req.body);
+ if (!x)
+ return crow::response(400);
+ auto sum = x["a"].i()+x["b"].i();
+ std::ostringstream os;
+ os << sum;
+ return crow::response{os.str()};
+ });
+
+ app.route_dynamic("/params")
+ ([](const crow::request& req){
+ std::ostringstream os;
+ os << "Params: " << req.url_params << "\n\n";
+ os << "The key 'foo' was " << (req.url_params.get("foo") == nullptr ? "not " : "") << "found.\n";
+ if(req.url_params.get("pew") != nullptr) {
+ double countD = boost::lexical_cast<double>(req.url_params.get("pew"));
+ os << "The value of 'pew' is " << countD << '\n';
+ }
+ auto count = req.url_params.get_list("count");
+ os << "The key 'count' contains " << count.size() << " value(s).\n";
+ for(const auto& countVal : count) {
+ os << " - " << countVal << '\n';
+ }
+ return crow::response{os.str()};
+ });
+
+ // ignore all log
+ crow::logger::setLogLevel(crow::LogLevel::DEBUG);
+ //crow::logger::setHandler(std::make_shared<ExampleLogHandler>());
+
+ app.port(18080)
+ .multithreaded()
+ .run();
+}
diff --git a/lib/crow/examples/example_with_all.cpp b/lib/crow/examples/example_with_all.cpp
new file mode 100644
index 0000000..56ac4cd
--- /dev/null
+++ b/lib/crow/examples/example_with_all.cpp
@@ -0,0 +1,94 @@
+#include "../amalgamate/crow_all.h"
+
+#include <sstream>
+
+class ExampleLogHandler : public crow::ILogHandler {
+ public:
+ void log(std::string /*message*/, crow::LogLevel /*level*/) override {
+// cerr << "ExampleLogHandler -> " << message;
+ }
+};
+
+int main()
+{
+ crow::SimpleApp app;
+
+ CROW_ROUTE(app, "/")
+ .name("hello")
+ ([]{
+ return "Hello World!";
+ });
+
+ CROW_ROUTE(app, "/about")
+ ([](){
+ return "About Crow example.";
+ });
+
+ // simple json response
+ CROW_ROUTE(app, "/json")
+ ([]{
+ crow::json::wvalue x;
+ x["message"] = "Hello, World!";
+ return x;
+ });
+
+ 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());
+ });
+
+ CROW_ROUTE(app,"/add/<int>/<int>")
+ ([](const crow::request& /*req*/, crow::response& res, int a, int b){
+ std::ostringstream os;
+ os << a+b;
+ res.write(os.str());
+ res.end();
+ });
+
+ // Compile error with message "Handler type is mismatched with URL paramters"
+ //CROW_ROUTE(app,"/another/<int>")
+ //([](int a, int b){
+ //return crow::response(500);
+ //});
+
+ // more json example
+ CROW_ROUTE(app, "/add_json")
+ ([](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()};
+ });
+
+ CROW_ROUTE(app, "/params")
+ ([](const crow::request& req){
+ std::ostringstream os;
+ os << "Params: " << req.url_params << "\n\n";
+ os << "The key 'foo' was " << (req.url_params.get("foo") == nullptr ? "not " : "") << "found.\n";
+ if(req.url_params.get("pew") != nullptr) {
+ double countD = boost::lexical_cast<double>(req.url_params.get("pew"));
+ os << "The value of 'pew' is " << countD << '\n';
+ }
+ auto count = req.url_params.get_list("count");
+ os << "The key 'count' contains " << count.size() << " value(s).\n";
+ for(const auto& countVal : count) {
+ os << " - " << countVal << '\n';
+ }
+ return crow::response{os.str()};
+ });
+
+ // ignore all log
+ crow::logger::setLogLevel(crow::LogLevel::Debug);
+ //crow::logger::setHandler(std::make_shared<ExampleLogHandler>());
+
+ app.port(18080)
+ .multithreaded()
+ .run();
+}
diff --git a/lib/crow/examples/helloworld.cpp b/lib/crow/examples/helloworld.cpp
new file mode 100644
index 0000000..8b77490
--- /dev/null
+++ b/lib/crow/examples/helloworld.cpp
@@ -0,0 +1,13 @@
+#include "crow.h"
+
+int main()
+{
+ crow::SimpleApp app;
+
+ CROW_ROUTE(app, "/")
+ ([]() {
+ return "Hello world!";
+ });
+
+ app.port(18080).run();
+}
diff --git a/lib/crow/examples/ssl/example_ssl.cpp b/lib/crow/examples/ssl/example_ssl.cpp
new file mode 100644
index 0000000..601aa57
--- /dev/null
+++ b/lib/crow/examples/ssl/example_ssl.cpp
@@ -0,0 +1,27 @@
+#define CROW_ENABLE_SSL
+#include "crow.h"
+
+int main()
+{
+ crow::SimpleApp app;
+
+ CROW_ROUTE(app, "/")
+ ([]() {
+ return "Hello world!";
+ });
+
+ app.port(18080).ssl_file("test.crt", "test.key").run();
+
+ // Use .pem file
+ //app.port(18080).ssl_file("test.pem").run();
+
+ // Use custom context; see boost::asio::ssl::context
+ /*
+ * crow::ssl_context_t ctx;
+ * ctx.set_verify_mode(...)
+ *
+ * ... configuring ctx
+ *
+ * app.port(18080).ssl(ctx).run();
+ */
+}
diff --git a/lib/crow/examples/websocket/example_ws.cpp b/lib/crow/examples/websocket/example_ws.cpp
new file mode 100644
index 0000000..173d062
--- /dev/null
+++ b/lib/crow/examples/websocket/example_ws.cpp
@@ -0,0 +1,48 @@
+#include "crow.h"
+#include <unordered_set>
+#include <mutex>
+
+
+int main()
+{
+ crow::SimpleApp app;
+
+ std::mutex mtx;;
+ std::unordered_set<crow::websocket::connection*> users;
+
+ CROW_ROUTE(app, "/ws")
+ .websocket()
+ .onopen([&](crow::websocket::connection& conn){
+ CROW_LOG_INFO << "new websocket connection";
+ std::lock_guard<std::mutex> _(mtx);
+ users.insert(&conn);
+ })
+ .onclose([&](crow::websocket::connection& conn, const std::string& reason){
+ CROW_LOG_INFO << "websocket connection closed: " << reason;
+ std::lock_guard<std::mutex> _(mtx);
+ users.erase(&conn);
+ })
+ .onmessage([&](crow::websocket::connection& /*conn*/, const std::string& data, bool is_binary){
+ std::lock_guard<std::mutex> _(mtx);
+ for(auto u:users)
+ if (is_binary)
+ u->send_binary(data);
+ else
+ u->send_text(data);
+ });
+
+ CROW_ROUTE(app, "/")
+ ([]{
+ char name[256];
+ gethostname(name, 256);
+ crow::mustache::context x;
+ x["servername"] = name;
+
+ auto page = crow::mustache::load("ws.html");
+ return page.render(x);
+ });
+
+ app.port(40080)
+ .multithreaded()
+ .run();
+}
diff --git a/lib/crow/examples/websocket/templates/ws.html b/lib/crow/examples/websocket/templates/ws.html
new file mode 100644
index 0000000..2d38fdf
--- /dev/null
+++ b/lib/crow/examples/websocket/templates/ws.html
@@ -0,0 +1,42 @@
+<!doctype html>
+<html>
+<head>
+ <script src="https://code.jquery.com/jquery-3.1.0.min.js"></script>
+</head>
+<body>
+ <input id="msg" type="text"></input>
+ <button id="send">
+ Send
+ </button><BR>
+ <textarea id="log" cols=100 rows=50>
+ </textarea>
+ <script>
+var sock = new WebSocket("ws://{{servername}}:40080/ws");
+
+sock.onopen = ()=>{
+ console.log('open')
+}
+sock.onerror = (e)=>{
+ console.log('error',e)
+}
+sock.onclose = ()=>{
+ console.log('close')
+}
+sock.onmessage = (e)=>{
+ $("#log").val(
+ e.data +"\n" + $("#log").val());
+}
+$("#msg").keypress(function(e){
+ if (e.which == 13)
+ {
+ sock.send($("#msg").val());
+ $("#msg").val("");
+ }
+});
+$("#send").click(()=>{
+ sock.send($("#msg").val());
+ $("#msg").val("");
+});
+ </script>
+</body>
+</html>