Incremental
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0070dde..bf0354d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -72,6 +72,8 @@
endif(MSAN)
endif(LIBC++)
+#SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wall")
+
# general
option(BUILD_SHARED_LIBS "Build as shared library" OFF)
option(BUILD_UT "Enable Unit test" ON)
@@ -90,7 +92,7 @@
add_definitions(-DBOOST_ERROR_CODE_HEADER_ONLY)
add_definitions(-DBOOST_SYSTEM_NO_DEPRECATED)
add_definitions(-DBOOST_ALL_NO_LIB)
-set(Boost_USE_STATIC_LIBS ON)
+#set(Boost_USE_STATIC_LIBS ON)
hunter_add_package(Boost)
find_package(Boost REQUIRED)
include_directories(${Boost_INCLUDE_DIRS})
@@ -99,6 +101,7 @@
hunter_add_package(OpenSSL)
find_package(OpenSSL REQUIRED)
include_directories(${OPENSSL_INCLUDE_DIR})
+message("OPENSSL_INCLUDE_DIR ${OPENSSL_INCLUDE_DIR}")
#g3 logging
# G3logger does some unfortunate compile options, so cheat a little bit and copy/paste
diff --git a/crow/include/crow/ci_map.h b/crow/include/crow/ci_map.h
index bf50fd0..456e528 100644
--- a/crow/include/crow/ci_map.h
+++ b/crow/include/crow/ci_map.h
@@ -2,6 +2,7 @@
#include <algorithm>
#include <iostream>
+#include <string>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/container/flat_map.hpp>
#include <boost/functional/hash.hpp>
@@ -10,9 +11,9 @@
struct ci_key_eq {
bool operator()(const std::string& left, const std::string& right) const {
- unsigned int lsz = left.size();
- unsigned int rsz = right.size();
- for (unsigned int i = 0; i < std::min(lsz, rsz); ++i) {
+ size_t lsz = left.size();
+ size_t rsz = right.size();
+ for (size_t i = 0; i < std::min(lsz, rsz); ++i) {
auto lchar = tolower(left[i]);
auto rchar = tolower(right[i]);
if (lchar != rchar) {
diff --git a/crow/include/crow/http_connection.h b/crow/include/crow/http_connection.h
index 5ead372..04810bd 100644
--- a/crow/include/crow/http_connection.h
+++ b/crow/include/crow/http_connection.h
@@ -5,6 +5,7 @@
#include <boost/algorithm/string/predicate.hpp>
#include <boost/array.hpp>
#include <boost/asio.hpp>
+#include <boost/asio/ssl.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/container/flat_map.hpp>
@@ -26,29 +27,33 @@
namespace detail {
template <typename MW>
struct check_before_handle_arity_3_const {
- template <typename T, void (T::*)(request&, response&, typename MW::context&)
- const = &T::before_handle>
+ template <typename T,
+ void (T::*)(request&, response&, typename MW::context&) const =
+ &T::before_handle>
struct get {};
};
template <typename MW>
struct check_before_handle_arity_3 {
- template <typename T, void (T::*)(request&, response&,
- typename MW::context&) = &T::before_handle>
+ template <typename T,
+ void (T::*)(request&, response&, typename MW::context&) =
+ &T::before_handle>
struct get {};
};
template <typename MW>
struct check_after_handle_arity_3_const {
- template <typename T, void (T::*)(request&, response&, typename MW::context&)
- const = &T::after_handle>
+ template <typename T,
+ void (T::*)(request&, response&, typename MW::context&) const =
+ &T::after_handle>
struct get {};
};
template <typename MW>
struct check_after_handle_arity_3 {
- template <typename T, void (T::*)(request&, response&,
- typename MW::context&) = &T::after_handle>
+ template <typename T,
+ void (T::*)(request&, response&, typename MW::context&) =
+ &T::after_handle>
struct get {};
};
@@ -252,8 +257,9 @@
if (parser_.check_version(1, 0)) {
// HTTP/1.0
if (req.headers.count("connection")) {
- if (boost::iequals(req.get_header_value("connection"), "Keep-Alive"))
+ if (boost::iequals(req.get_header_value("connection"), "Keep-Alive")) {
add_keep_alive_ = true;
+ }
} else
close_connection_ = true;
} else if (parser_.check_version(1, 1)) {
@@ -262,8 +268,9 @@
if (req.get_header_value("connection") == "close")
close_connection_ = true;
else if (boost::iequals(req.get_header_value("connection"),
- "Keep-Alive"))
+ "Keep-Alive")) {
add_keep_alive_ = true;
+ }
}
if (!req.headers.count("Host")) {
is_invalid_request = true;
@@ -288,6 +295,7 @@
<< req.url;
need_to_call_after_handlers_ = false;
+
if (!is_invalid_request) {
res.complete_request_handler_ = [] {};
res.is_alive_helper_ = [this]() -> bool { return adaptor_.is_open(); };
@@ -303,7 +311,7 @@
res.complete_request_handler_ = [this] { this->complete_request(); };
need_to_call_after_handlers_ = true;
handler_->handle(req, res);
- if (add_keep_alive_) res.set_header("connection", "Keep-Alive");
+ if (add_keep_alive_) res.add_header("connection", "Keep-Alive");
} else {
complete_request();
}
@@ -358,11 +366,9 @@
{503, "HTTP/1.1 503 Service Unavailable\r\n"},
};
- static std::string seperator = ": ";
- static std::string crlf = "\r\n";
buffers_.clear();
- buffers_.reserve(4 * (res.headers.size() + 5) + 3);
+ buffers_.reserve(20);
if (res.body.empty() && res.json_value.t() == json::type::Object) {
res.body = json::dump(res.json_value);
@@ -376,41 +382,29 @@
if (res.code >= 400 && res.body.empty())
res.body = statusCodes[res.code].substr(9);
+
+
- for (auto& kv : res.headers) {
- buffers_.emplace_back(kv.first.data(), kv.first.size());
- buffers_.emplace_back(seperator.data(), seperator.size());
- buffers_.emplace_back(kv.second.data(), kv.second.size());
- buffers_.emplace_back(crlf.data(), crlf.size());
- }
+ const static std::string crlf = "\r\n";
+ content_length_ = std::to_string(res.body.size());
+ static const std::string content_length_tag = "Content-Length";
+ res.add_header(content_length_tag, content_length_);
- if (!res.headers.count("content-length")) {
- content_length_ = std::to_string(res.body.size());
- static std::string content_length_tag = "Content-Length: ";
- buffers_.emplace_back(content_length_tag.data(),
- content_length_tag.size());
- buffers_.emplace_back(content_length_.data(), content_length_.size());
- buffers_.emplace_back(crlf.data(), crlf.size());
- }
- if (!res.headers.count("server")) {
- static std::string server_tag = "Server: ";
- buffers_.emplace_back(server_tag.data(), server_tag.size());
- buffers_.emplace_back(server_name_.data(), server_name_.size());
- buffers_.emplace_back(crlf.data(), crlf.size());
- }
- if (!res.headers.count("date")) {
- static std::string date_tag = "Date: ";
- date_str_ = get_cached_date_str();
- buffers_.emplace_back(date_tag.data(), date_tag.size());
- buffers_.emplace_back(date_str_.data(), date_str_.size());
- buffers_.emplace_back(crlf.data(), crlf.size());
- }
+ static const std::string server_tag = "Server: ";
+ res.add_header(server_tag, server_name_);
+
+ static const std::string date_tag = "Date: ";
+ date_str_ = get_cached_date_str();
+ res.add_header(date_tag, date_str_);
+
if (add_keep_alive_) {
- static std::string keep_alive_tag = "Connection: Keep-Alive";
- buffers_.emplace_back(keep_alive_tag.data(), keep_alive_tag.size());
- buffers_.emplace_back(crlf.data(), crlf.size());
+ static const std::string keep_alive_tag = "Connection";
+ static const std::string keep_alive_value = "Keep-Alive";
+ res.add_header(keep_alive_tag, keep_alive_value);
}
+buffers_.emplace_back(res.headers.data(), res.headers.size());
+
buffers_.emplace_back(crlf.data(), crlf.size());
res_body_copy_.swap(res.body);
buffers_.emplace_back(res_body_copy_.data(), res_body_copy_.size());
@@ -432,12 +426,30 @@
boost::asio::buffer(buffer_),
[this](const boost::system::error_code& ec,
std::size_t bytes_transferred) {
+ CROW_LOG_ERROR << "Read " << bytes_transferred << " Bytes";
bool error_while_reading = true;
if (!ec) {
bool ret = parser_.feed(buffer_.data(), bytes_transferred);
if (ret && adaptor_.is_open()) {
error_while_reading = false;
}
+ } else {
+ CROW_LOG_ERROR << "Error while reading: " << ec.message();
+ if (ec.category() == boost::asio::error::get_ssl_category()) {
+ auto err =
+ std::string(" (") +
+ boost::lexical_cast<std::string>(ERR_GET_LIB(ec.value())) +
+ "," +
+ boost::lexical_cast<std::string>(ERR_GET_FUNC(ec.value())) +
+ "," +
+ boost::lexical_cast<std::string>(ERR_GET_REASON(ec.value())) +
+ ") ";
+ // ERR_PACK /* crypto/err/err.h */
+ char buf[128];
+ ::ERR_error_string_n(ec.value(), buf, sizeof(buf));
+ err += buf;
+ CROW_LOG_ERROR << err;
+ }
}
if (error_while_reading) {
cancel_deadline_timer();
@@ -465,23 +477,37 @@
void do_write() {
// auto self = this->shared_from_this();
is_writing = true;
- boost::asio::async_write(adaptor_.socket(), buffers_,
- [&](const boost::system::error_code& ec,
- std::size_t /*bytes_transferred*/) {
- is_writing = false;
- res.clear();
- res_body_copy_.clear();
- if (!ec) {
- if (close_connection_) {
- adaptor_.close();
- CROW_LOG_DEBUG << this << " from write(1)";
- check_destroy();
- }
- } else {
- CROW_LOG_DEBUG << this << " from write(2)";
- check_destroy();
- }
- });
+ CROW_LOG_DEBUG << "Doing Write";
+ boost::asio::async_write(
+ adaptor_.socket(), buffers_, [&](const boost::system::error_code& ec,
+ std::size_t bytes_transferred) {
+ CROW_LOG_DEBUG << "Wrote " << bytes_transferred << "bytes";
+ for (auto& buffer : buffers_) {
+ /*
+ CROW_LOG_DEBUG << "2nd passbuffer is "
+ << std::string(
+ boost::asio::buffer_cast<const char*>(buffer),
+ boost::asio::buffer_size(buffer));
+ */
+ CROW_LOG_DEBUG << "pointer address "
+ << (int)boost::asio::buffer_cast<const char*>(
+ buffer);
+ }
+
+ is_writing = false;
+ res.clear();
+ res_body_copy_.clear();
+ if (!ec) {
+ if (close_connection_) {
+ adaptor_.close();
+ CROW_LOG_DEBUG << this << " from write(1)";
+ check_destroy();
+ }
+ } else {
+ CROW_LOG_DEBUG << this << " from write(2)";
+ check_destroy();
+ }
+ });
}
void check_destroy() {
diff --git a/crow/include/crow/http_request.h b/crow/include/crow/http_request.h
index 354f997..acb417c 100644
--- a/crow/include/crow/http_request.h
+++ b/crow/include/crow/http_request.h
@@ -41,7 +41,7 @@
headers(std::move(headers)),
body(std::move(body)) {}
- void add_header(std::string key, std::string value) {
+ void add_header(const std::string& key, const std::string& value) {
headers.emplace(std::move(key), std::move(value));
}
diff --git a/crow/include/crow/http_response.h b/crow/include/crow/http_response.h
index 322147b..3ba2872 100644
--- a/crow/include/crow/http_response.h
+++ b/crow/include/crow/http_response.h
@@ -4,6 +4,7 @@
#include "crow/ci_map.h"
#include "crow/http_request.h"
#include "crow/json.h"
+#include "crow/logging.h"
namespace crow {
template <typename Adaptor, typename Handler, typename... Middlewares>
@@ -17,18 +18,18 @@
json::wvalue json_value;
// `headers' stores HTTP headers.
- ci_map headers;
+ //ci_map headers;
- void set_header(std::string key, std::string value) {
- headers.erase(key);
- headers.emplace(std::move(key), std::move(value));
- }
- void add_header(std::string key, std::string value) {
- headers.emplace(std::move(key), std::move(value));
- }
+ std::string headers;
- const std::string& get_header_value(const std::string& key) {
- return crow::get_header_value(headers, key);
+ void add_header(const std::string& key, const std::string& value) {
+
+ const static std::string seperator = ": ";
+ const static std::string crlf = "\r\n";
+ headers.append(key);
+ headers.append(seperator);
+ headers.append(value);
+ headers.append(crlf);
}
response() {}
@@ -46,11 +47,19 @@
json_mode();
}
- response(response&& r) { *this = std::move(r); }
+ response(response&& r) {
+ CROW_LOG_WARNING << "Moving response containers";
+ *this = std::move(r);
+ }
+
+ ~response(){
+ CROW_LOG_WARNING << "Destroying response";
+ }
response& operator=(const response& r) = delete;
response& operator=(response&& r) noexcept {
+ CROW_LOG_WARNING << "Moving response containers";
body = std::move(r.body);
json_value = std::move(r.json_value);
code = r.code;
@@ -62,6 +71,7 @@
bool is_completed() const noexcept { return completed_; }
void clear() {
+ CROW_LOG_WARNING << "Clearing response containers";
body.clear();
json_value.clear();
code = 200;
@@ -94,6 +104,6 @@
std::function<bool()> is_alive_helper_;
// In case of a JSON object, set the Content-Type header
- void json_mode() { set_header("Content-Type", "application/json"); }
+ void json_mode() { add_header("Content-Type", "application/json"); }
};
}
diff --git a/crow/include/crow/socket_adaptors.h b/crow/include/crow/socket_adaptors.h
index c55e4d5..13b4a20 100644
--- a/crow/include/crow/socket_adaptors.h
+++ b/crow/include/crow/socket_adaptors.h
@@ -3,6 +3,7 @@
#ifdef CROW_ENABLE_SSL
#include <boost/asio/ssl.hpp>
#endif
+#include "crow/logging.h"
#include "crow/settings.h"
namespace crow {
using namespace boost;
@@ -85,7 +86,7 @@
failed, because is_open now returns False (which could also mean the client
disconnected during parse)
UPdate: The parser does in fact have an "is_upgrade" method that is intended
- for exactly this purpose. Todo is now to make do_read obey the flag
+ for exactly this purpose. Todo is now to make do_read obey the flag
appropriately.
*/
if (ssl_socket_ != nullptr) {
@@ -99,7 +100,10 @@
if (ssl_socket_ == nullptr) {
return;
}
- ssl_socket_->lowest_layer().close();
+ boost::system::error_code ec;
+
+ // SHut it down
+ this->ssl_socket_->lowest_layer().close();
}
boost::asio::io_service& get_io_service() {
diff --git a/include/ssl_key_handler.hpp b/include/ssl_key_handler.hpp
index 5cd29a8..aade3fb 100644
--- a/include/ssl_key_handler.hpp
+++ b/include/ssl_key_handler.hpp
@@ -298,7 +298,7 @@
std::string lighttp_ciphers = "AES128+EECDH:AES128+EDH:!aNULL:!eNULL";
- if (SSL_CTX_set_cipher_list(m_ssl_context.native_handle(), ciphers.c_str()) !=
+ if (SSL_CTX_set_cipher_list(m_ssl_context.native_handle(), lighttp_ciphers.c_str()) !=
1) {
CROW_LOG_ERROR << "Error setting cipher list\n";
}
diff --git a/scripts/build_web_assets.py b/scripts/build_web_assets.py
index 955f21e..46bf199 100755
--- a/scripts/build_web_assets.py
+++ b/scripts/build_web_assets.py
@@ -36,7 +36,7 @@
res.code = 200;
// TODO, if you have a browser from the dark ages that doesn't support gzip,
// unzip it before sending based on Accept-Encoding header
- res.add_header("Content-Encoding", "{content_encoding}");
+ res.add_header("Content-Encoding", {content_encoding});
res.add_header("Content-Type", "{content_type}");
res.write(staticassets::{relative_path_escaped});
@@ -242,6 +242,8 @@
"\n"
"namespace crow {\n"
"namespace webassets {\n"
+ "static const std::string gzip_string = \"gzip\";\n"
+ "static const std::string none_string = \"none\";\n"
)
hpp_output.write("struct staticassets {\n")
@@ -273,7 +275,7 @@
get_sha1_path_from_relative(relative_path, sha1)
#print("relative_path_sha1: " + relative_path_sha1)
#print("sha1: " + sha1)
- content_encoding = 'gzip' if gzip_content else 'none'
+ content_encoding = 'gzip_string' if gzip_content else 'none_string'
environment = {
'relative_path': relative_path,