aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorJaeseung Ha <ipknhama@gmail.com>2017-09-17 18:01:57 +0900
committerGitHub <noreply@github.com>2017-09-17 18:01:57 +0900
commitef17b8cb9b79921805f13f4947dadb07763ac475 (patch)
tree1f9c4ffe0dc004dc4cb648b2b58ac99c8b0dca79 /include
parentc63113f8250c3ef0eb4dfc25aeab7e2e7c475fc4 (diff)
parentc43c052112cd15ac8be1d0cb90b6ad2570b2b99a (diff)
downloadcrow-ef17b8cb9b79921805f13f4947dadb07763ac475.tar.gz
crow-ef17b8cb9b79921805f13f4947dadb07763ac475.zip
Merge branch 'master' into master
Diffstat (limited to 'include')
-rw-r--r--include/crow/http_connection.h1
-rw-r--r--include/crow/http_server.h21
-rw-r--r--include/crow/json.h17
-rw-r--r--include/crow/query_string.h58
-rw-r--r--include/crow/routing.h40
-rw-r--r--include/crow/websocket.h17
6 files changed, 138 insertions, 16 deletions
diff --git a/include/crow/http_connection.h b/include/crow/http_connection.h
index 96f2d14..3ef8089 100644
--- a/include/crow/http_connection.h
+++ b/include/crow/http_connection.h
@@ -374,6 +374,7 @@ namespace crow
{401, "HTTP/1.1 401 Unauthorized\r\n"},
{403, "HTTP/1.1 403 Forbidden\r\n"},
{404, "HTTP/1.1 404 Not Found\r\n"},
+ {422, "HTTP/1.1 422 Unprocessable Entity\r\n"},
{500, "HTTP/1.1 500 Internal Server Error\r\n"},
{501, "HTTP/1.1 501 Not Implemented\r\n"},
diff --git a/include/crow/http_server.h b/include/crow/http_server.h
index d5abb11..7e4da56 100644
--- a/include/crow/http_server.h
+++ b/include/crow/http_server.h
@@ -121,12 +121,19 @@ namespace crow
timer.async_wait(handler);
init_count ++;
- try
+ while(1)
{
- io_service_pool_[i]->run();
- } catch(std::exception& e)
- {
- CROW_LOG_ERROR << "Worker Crash: An uncaught exception occurred: " << e.what();
+ try
+ {
+ if (io_service_pool_[i]->run() == 0)
+ {
+ // when io_service.run returns 0, there are no more works to do.
+ break;
+ }
+ } catch(std::exception& e)
+ {
+ CROW_LOG_ERROR << "Worker Crash: An uncaught exception occurred: " << e.what();
+ }
}
}));
@@ -193,6 +200,10 @@ namespace crow
p->start();
});
}
+ else
+ {
+ delete p;
+ }
do_accept();
});
}
diff --git a/include/crow/json.h b/include/crow/json.h
index 891fedf..8b58180 100644
--- a/include/crow/json.h
+++ b/include/crow/json.h
@@ -1264,6 +1264,23 @@ namespace crow
return *this;
}
+ wvalue& operator=(std::vector<wvalue>&& v)
+ {
+ if (t_ != type::List)
+ reset();
+ t_ = type::List;
+ if (!l)
+ l = std::unique_ptr<std::vector<wvalue>>(new std::vector<wvalue>{});
+ l->clear();
+ l->resize(v.size());
+ size_t idx = 0;
+ for(auto& x:v)
+ {
+ (*l)[idx++] = std::move(x);
+ }
+ return *this;
+ }
+
template <typename T>
wvalue& operator=(const std::vector<T>& v)
{
diff --git a/include/crow/query_string.h b/include/crow/query_string.h
index 3f8bffe..78ccc67 100644
--- a/include/crow/query_string.h
+++ b/include/crow/query_string.h
@@ -4,7 +4,9 @@
#include <string.h>
#include <string>
#include <vector>
+#include <unordered_map>
#include <iostream>
+#include <boost/optional.hpp>
namespace crow
{
@@ -197,6 +199,48 @@ inline char * qs_k2v(const char * key, char * const * qs_kv, int qs_kv_size, int
return NULL;
}
+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)
+{
+ int i;
+ size_t name_len, skip_to_eq, skip_to_brace_open, skip_to_brace_close;
+
+ name_len = strlen(dict_name);
+
+#ifdef _qsSORTING
+// TODO: binary search for key in the sorted qs_kv
+#else // _qsSORTING
+ for(i=0; i<qs_kv_size; i++)
+ {
+ if ( strncmp(dict_name, qs_kv[i], name_len) == 0 )
+ {
+ skip_to_eq = strcspn(qs_kv[i], "=");
+ if ( qs_kv[i][skip_to_eq] == '=' )
+ skip_to_eq++;
+ skip_to_brace_open = strcspn(qs_kv[i], "[");
+ if ( qs_kv[i][skip_to_brace_open] == '[' )
+ skip_to_brace_open++;
+ skip_to_brace_close = strcspn(qs_kv[i], "]");
+
+ if ( skip_to_brace_open <= skip_to_brace_close &&
+ skip_to_brace_open > 0 &&
+ skip_to_brace_close > 0 &&
+ nth == 0 )
+ {
+ auto key = std::string(qs_kv[i] + skip_to_brace_open, skip_to_brace_close - skip_to_brace_open);
+ auto value = std::string(qs_kv[i] + skip_to_eq);
+ return boost::make_optional(std::make_pair(key, value));
+ }
+ else
+ {
+ --nth;
+ }
+ }
+ }
+#endif // _qsSORTING
+
+ return boost::none;
+}
+
inline char * qs_scanvalue(const char * key, const char * qs, char * val, size_t val_len)
{
@@ -336,6 +380,20 @@ namespace crow
return ret;
}
+ std::unordered_map<std::string, std::string> get_dict (const std::string& name) const
+ {
+ std::unordered_map<std::string, std::string> ret;
+
+ int count = 0;
+ while(1)
+ {
+ if (auto element = qs_dict_name2kv(name.c_str(), key_value_pairs_.data(), key_value_pairs_.size(), count++))
+ ret.insert(*element);
+ else
+ break;
+ }
+ return ret;
+ }
private:
std::string url_;
diff --git a/include/crow/routing.h b/include/crow/routing.h
index a8aa233..cdfa480 100644
--- a/include/crow/routing.h
+++ b/include/crow/routing.h
@@ -156,7 +156,7 @@ namespace crow
struct Wrapped
{
template <typename ... Args>
- void set(Func f, typename std::enable_if<
+ void set_(Func f, typename std::enable_if<
!std::is_same<typename std::tuple_element<0, std::tuple<Args..., void>>::type, const request&>::value
, int>::type = 0)
{
@@ -190,7 +190,7 @@ namespace crow
};
template <typename ... Args>
- void set(Func f, typename std::enable_if<
+ void set_(Func f, typename std::enable_if<
std::is_same<typename std::tuple_element<0, std::tuple<Args..., void>>::type, const request&>::value &&
!std::is_same<typename std::tuple_element<1, std::tuple<Args..., void, void>>::type, response&>::value
, int>::type = 0)
@@ -205,7 +205,7 @@ namespace crow
}
template <typename ... Args>
- void set(Func f, typename std::enable_if<
+ void set_(Func f, typename std::enable_if<
std::is_same<typename std::tuple_element<0, std::tuple<Args..., void>>::type, const request&>::value &&
std::is_same<typename std::tuple_element<1, std::tuple<Args..., void, void>>::type, response&>::value
, int>::type = 0)
@@ -276,12 +276,12 @@ namespace crow
void handle_upgrade(const request& req, response&, SocketAdaptor&& adaptor) override
{
- new crow::websocket::Connection<SocketAdaptor>(req, std::move(adaptor), open_handler_, message_handler_, close_handler_, error_handler_);
+ new crow::websocket::Connection<SocketAdaptor>(req, std::move(adaptor), open_handler_, message_handler_, close_handler_, error_handler_, accept_handler_);
}
#ifdef CROW_ENABLE_SSL
void handle_upgrade(const request& req, response&, SSLAdaptor&& adaptor) override
{
- new crow::websocket::Connection<SSLAdaptor>(req, std::move(adaptor), open_handler_, message_handler_, close_handler_, error_handler_);
+ new crow::websocket::Connection<SSLAdaptor>(req, std::move(adaptor), open_handler_, message_handler_, close_handler_, error_handler_, accept_handler_);
}
#endif
@@ -313,11 +313,19 @@ namespace crow
return *this;
}
+ template <typename Func>
+ self_t& onaccept(Func f)
+ {
+ accept_handler_ = f;
+ return *this;
+ }
+
protected:
std::function<void(crow::websocket::connection&)> open_handler_;
std::function<void(crow::websocket::connection&, const std::string&, bool)> message_handler_;
std::function<void(crow::websocket::connection&, const std::string&)> close_handler_;
std::function<void(crow::websocket::connection&)> error_handler_;
+ std::function<bool(const crow::request&)> accept_handler_;
};
template <typename T>
@@ -410,7 +418,7 @@ namespace crow
throw std::runtime_error("route_dynamic: Handler type is mismatched with URL parameters: " + rule_);
}
auto ret = detail::routing_handler_call_helper::Wrapped<Func, typename function_t::template arg<Indices>...>();
- ret.template set<
+ ret.template set_<
typename function_t::template arg<Indices>...
>(std::move(f));
return ret;
@@ -456,10 +464,16 @@ namespace crow
static_assert(!std::is_same<void, decltype(f(std::declval<Args>()...))>::value,
"Handler function cannot have void return type; valid return types: string, int, crow::resposne, crow::json::wvalue");
- handler_ = [f = std::move(f)](const request&, response& res, Args ... args){
+ handler_ = (
+#ifdef CROW_CAN_USE_CPP14
+ [f = std::move(f)]
+#else
+ [f]
+#endif
+ (const request&, response& res, Args ... args){
res = response(f(args...));
res.end();
- };
+ });
}
template <typename Func>
@@ -475,10 +489,16 @@ namespace crow
static_assert(!std::is_same<void, decltype(f(std::declval<crow::request>(), std::declval<Args>()...))>::value,
"Handler function cannot have void return type; valid return types: string, int, crow::resposne, crow::json::wvalue");
- handler_ = [f = std::move(f)](const crow::request& req, crow::response& res, Args ... args){
+ handler_ = (
+#ifdef CROW_CAN_USE_CPP14
+ [f = std::move(f)]
+#else
+ [f]
+#endif
+ (const crow::request& req, crow::response& res, Args ... args){
res = response(f(req, args...));
res.end();
- };
+ });
}
template <typename Func>
diff --git a/include/crow/websocket.h b/include/crow/websocket.h
index 3724375..d21d7e9 100644
--- a/include/crow/websocket.h
+++ b/include/crow/websocket.h
@@ -1,5 +1,6 @@
#pragma once
#include <boost/algorithm/string/predicate.hpp>
+#include <boost/array.hpp>
#include "crow/socket_adaptors.h"
#include "crow/http_request.h"
#include "crow/TinySHA1.hpp"
@@ -39,8 +40,10 @@ namespace crow
std::function<void(crow::websocket::connection&)> open_handler,
std::function<void(crow::websocket::connection&, const std::string&, bool)> message_handler,
std::function<void(crow::websocket::connection&, const std::string&)> close_handler,
- std::function<void(crow::websocket::connection&)> error_handler)
+ std::function<void(crow::websocket::connection&)> error_handler,
+ std::function<bool(const crow::request&)> accept_handler)
: adaptor_(std::move(adaptor)), open_handler_(std::move(open_handler)), message_handler_(std::move(message_handler)), close_handler_(std::move(close_handler)), error_handler_(std::move(error_handler))
+ , accept_handler_(std::move(accept_handler))
{
if (!boost::iequals(req.get_header_value("upgrade"), "websocket"))
{
@@ -48,6 +51,17 @@ namespace crow
delete this;
return;
}
+
+ if (accept_handler_)
+ {
+ if (!accept_handler_(req))
+ {
+ adaptor.close();
+ delete this;
+ return;
+ }
+ }
+
// Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
// Sec-WebSocket-Version: 13
std::string magic = req.get_header_value("Sec-WebSocket-Key") + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
@@ -486,6 +500,7 @@ namespace crow
std::function<void(crow::websocket::connection&, const std::string&, bool)> message_handler_;
std::function<void(crow::websocket::connection&, const std::string&)> close_handler_;
std::function<void(crow::websocket::connection&)> error_handler_;
+ std::function<bool(const crow::request&)> accept_handler_;
};
}
}